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
@@ -6,7 +6,15 @@ export const STOP_CLASS_NO_LAUNCH = 'no-launch' as const;
6
6
  const CHILD_RESULT_KINDS = new Set(['self', 'external']);
7
7
 
8
8
  /** The dev child's terminal line nests the stage: {ok, kind, result:{stage, ok, node, outcome, …}}. Other JSON rows are not results. */
9
- export function nestedPodResult(row: Record<string, unknown>): { stage: string; ok: boolean; error?: string } | null {
9
+ export function nestedPodResult(row: Record<string, unknown>): {
10
+ stage: string;
11
+ ok: boolean;
12
+ error?: string;
13
+ reasonCode?: string;
14
+ checkName?: string;
15
+ targetPath?: string;
16
+ preflightChecks?: PreflightCheck[];
17
+ } | null {
10
18
  if (typeof row.kind !== 'string' || !CHILD_RESULT_KINDS.has(row.kind) || typeof row.ok !== 'boolean') return null;
11
19
  if (!row.result || typeof row.result !== 'object' || Array.isArray(row.result)) return null;
12
20
  const result = row.result as Record<string, unknown>;
@@ -18,28 +26,72 @@ export function nestedPodResult(row: Record<string, unknown>): { stage: string;
18
26
  ? (classification as Record<string, unknown>).classification : undefined;
19
27
  const reason = [result.node, result.outcome].filter((part): part is string => typeof part === 'string' && part.length > 0).join(' ');
20
28
  const error = [reason || (typeof result.error === 'string' ? result.error : ''), typeof detail === 'string' && detail ? detail : ''].filter(Boolean).join(' · ');
21
- return { stage: result.stage, ok: false, ...(error ? { error } : {}) };
29
+ // PREFLIGHT-RESULT-LINE: a nested preflight rejection carries its blockers under result.blockers — the same ledger fields as the flat row.
30
+ const blockers = result.stage === 'preflight-blocked' ? preflightBlockerText(result.blockers)
31
+ : { error: '', preflightChecks: [] as PreflightCheck[] };
32
+ return {
33
+ stage: result.stage,
34
+ ok: false,
35
+ ...(error || blockers.error ? { error: error || blockers.error } : {}),
36
+ ...(blockers.preflightChecks.length === 1 ? blockers.preflightChecks[0] : {}),
37
+ ...(blockers.preflightChecks.length > 1 ? { preflightChecks: blockers.preflightChecks } : {}),
38
+ };
22
39
  }
23
40
 
24
- /** One line naming each preflight blocker (`(대상 경로 0) — …`), or '' when the row carries none. */
25
- function preflightBlockerText(blockers: unknown): string {
26
- if (!Array.isArray(blockers)) return '';
27
- return blockers.flatMap((blocker) => {
28
- if (!blocker || typeof blocker !== 'object' || Array.isArray(blocker)) return [];
29
- const { name, detail } = blocker as Record<string, unknown>;
30
- const parts = [name, detail].filter((part): part is string => typeof part === 'string' && part.trim().length > 0).map((part) => part.trim().replace(/\s+/gu, ' '));
31
- return parts.length ? [parts.join(' — ')] : [];
32
- }).join(' · ');
41
+ function ledgerString(value: unknown): string {
42
+ return typeof value === 'string' && value.trim().length > 0 ? value : '';
43
+ }
44
+
45
+ type PreflightCheck = { reasonCode: string; checkName: string; targetPath?: string };
46
+
47
+ /** Keep each structured check paired with its own path; legacy blockers retain their name/detail diagnostic. */
48
+ function preflightBlockerText(blockers: unknown): { error: string; preflightChecks: PreflightCheck[] } {
49
+ if (!Array.isArray(blockers)) return { error: '', preflightChecks: [] };
50
+ const errors: string[] = [];
51
+ const preflightChecks: PreflightCheck[] = [];
52
+ for (const blocker of blockers) {
53
+ if (!blocker || typeof blocker !== 'object' || Array.isArray(blocker)) continue;
54
+ const record = blocker as Record<string, unknown>;
55
+ const reasonCode = ledgerString(record.reasonCode);
56
+ const checkName = ledgerString(record.checkName);
57
+ if (reasonCode && checkName) {
58
+ const targetPath = ledgerString(record.targetPath);
59
+ preflightChecks.push({ reasonCode, checkName, ...(targetPath ? { targetPath } : {}) });
60
+ errors.push(`${reasonCode} · ${checkName}`);
61
+ continue;
62
+ }
63
+ const parts = [record.name, record.detail]
64
+ .filter((part): part is string => typeof part === 'string' && part.trim().length > 0)
65
+ .map((part) => part.trim().replace(/\s+/gu, ' '));
66
+ if (parts.length) errors.push(parts.join(' — '));
67
+ }
68
+ return { error: errors.join(' · '), preflightChecks };
33
69
  }
34
70
 
35
71
  /** A child terminal row: the legacy flat form {stage, ok, error?} (no kind, or a child kind) or the nested dev result. Any other kind is not a result. */
36
- export function podTerminalRow(row: Record<string, unknown>): { stage: string; ok: boolean; error?: string } | null {
72
+ export function podTerminalRow(row: Record<string, unknown>): {
73
+ stage: string;
74
+ ok: boolean;
75
+ error?: string;
76
+ reasonCode?: string;
77
+ checkName?: string;
78
+ targetPath?: string;
79
+ preflightChecks?: PreflightCheck[];
80
+ } | null {
37
81
  if (typeof row.kind === 'string' && !CHILD_RESULT_KINDS.has(row.kind)) return null;
38
82
  if (typeof row.stage === 'string' && typeof row.ok === 'boolean') {
39
- if (typeof row.error === 'string') return { stage: row.stage, ok: row.ok, error: row.error };
40
- // PREFLIGHT-RESULT-LINE: `{kind:'self', ok:false, stage:'preflight-blocked', blockers}` carries its reason in the blockers, not in `error`.
41
- const blockers = row.ok === false && row.stage === 'preflight-blocked' ? preflightBlockerText(row.blockers) : '';
42
- return { stage: row.stage, ok: row.ok, ...(blockers ? { error: blockers } : {}) };
83
+ // PREFLIGHT-RESULT-LINE: preserve structured blockers even when an explicit error supplies the human-readable reason.
84
+ if (row.ok === false && row.stage === 'preflight-blocked') {
85
+ const blockers = preflightBlockerText(row.blockers);
86
+ return {
87
+ stage: row.stage,
88
+ ok: row.ok,
89
+ ...(typeof row.error === 'string' ? { error: row.error } : blockers.error ? { error: blockers.error } : {}),
90
+ ...(blockers.preflightChecks.length === 1 ? blockers.preflightChecks[0] : {}),
91
+ ...(blockers.preflightChecks.length > 1 ? { preflightChecks: blockers.preflightChecks } : {}),
92
+ };
93
+ }
94
+ return { stage: row.stage, ok: row.ok, ...(typeof row.error === 'string' ? { error: row.error } : {}) };
43
95
  }
44
96
  return nestedPodResult(row);
45
97
  }
@@ -64,9 +116,21 @@ export function classifyPodExit(input: {
64
116
  jobReason?: string | null;
65
117
  logs: string;
66
118
  result?: Record<string, unknown> | null;
67
- }): { class: PodExitClass; errorCode: string | null; containerReason: string | null; exitCode: number | null; jobReason: string | null; tail: string[] } {
119
+ }): {
120
+ class: PodExitClass;
121
+ errorCode: string | null;
122
+ containerReason: string | null;
123
+ exitCode: number | null;
124
+ jobReason: string | null;
125
+ tail: string[];
126
+ reasonCode?: string;
127
+ checkName?: string;
128
+ targetPath?: string;
129
+ preflightChecks?: PreflightCheck[];
130
+ noResultLine?: true;
131
+ } {
68
132
  const logLines = input.logs.split(/\r\n|\n|\r/u).map((line) => line.trim()).filter(Boolean);
69
- let terminalResult: { stage: string; ok: boolean; error?: string } | null = null;
133
+ let terminalResult: ReturnType<typeof podTerminalRow> = null;
70
134
  for (const line of logLines) {
71
135
  if (!line.startsWith('{')) continue;
72
136
  let parsed: unknown;
@@ -74,8 +138,8 @@ export function classifyPodExit(input: {
74
138
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue;
75
139
  terminalResult = podTerminalRow(parsed as Record<string, unknown>) ?? terminalResult;
76
140
  }
77
- if (!terminalResult && input.result) terminalResult = podTerminalRow(input.result);
78
141
  const hasResultLine = terminalResult !== null;
142
+ if (!terminalResult && input.result) terminalResult = podTerminalRow(input.result);
79
143
  const askReprompt = logLines.some((line) =>
80
144
  /^\[ask\](?!\s+\d+\)\s).*(?:implementation[_ -]?target|reprompt|re-prompt|되묻)/iu.test(line));
81
145
  // 파싱되는 JSON 줄(진행·결과 행)은 오류 «줄»로 세지 않는다 — tail 과 같은 기준.
@@ -116,6 +180,11 @@ export function classifyPodExit(input: {
116
180
  exitCode: input.containerExitCode ?? null,
117
181
  jobReason: input.jobReason ?? null,
118
182
  tail,
183
+ ...(terminalResult?.reasonCode ? { reasonCode: terminalResult.reasonCode } : {}),
184
+ ...(terminalResult?.checkName ? { checkName: terminalResult.checkName } : {}),
185
+ ...(terminalResult?.targetPath ? { targetPath: terminalResult.targetPath } : {}),
186
+ ...(terminalResult?.preflightChecks ? { preflightChecks: terminalResult.preflightChecks } : {}),
187
+ ...(!hasResultLine ? { noResultLine: true as const } : {}),
119
188
  };
120
189
  }
121
190
 
@@ -11,6 +11,7 @@
11
11
  // ⛔ 기본 꺼짐(opt-in): 옵션 → env `ELANOUS_POD_HOST_ACP_REVIEW` → config `llm.podHostAcpReview` 순.
12
12
  // 📌 남은 조각(②-b): 이 문이 켜진 런에서 Pod 안 api 리뷰를 «끄는» 것은 Pod 이미지 쪽 변경이라 따로 간다.
13
13
  import { spawnSync } from 'node:child_process';
14
+ import { SPAWN_SYNC_MAX_BUFFER } from '../../util/spawn-sync-output.js';
14
15
  import { debug } from '../../debug/log.js';
15
16
  import type { ReviewResult } from '../../agent-substrate/pr-reviewer.js';
16
17
  import type { SubscriptionReviewerSpec } from '../../user-config.js';
@@ -57,7 +58,7 @@ export interface PodHostAcpReviewDeps {
57
58
  }
58
59
 
59
60
  function defaultReadPr(prNumber: number, repoRoot: string): { headRefOid: string; title: string; body: string; diff: string } | undefined {
60
- const view = spawnSync('gh', ['pr', 'view', String(prNumber), '--json', 'headRefOid,title,body'], { cwd: repoRoot, encoding: 'utf8', timeout: 60_000 });
61
+ const view = spawnSync('gh', ['pr', 'view', String(prNumber), '--json', 'headRefOid,title,body'], { cwd: repoRoot, encoding: 'utf8', timeout: 60_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
61
62
  if (view.status !== 0) return undefined;
62
63
  const diff = spawnSync('gh', ['pr', 'diff', String(prNumber)], { cwd: repoRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 64 * 1024 * 1024 });
63
64
  if (diff.status !== 0) return undefined;
@@ -14,6 +14,7 @@
14
14
  * 이미지는 표준판(elanous-harness)만 — 이 발사 경로는 lite 를 쓰지 않는다.
15
15
  */
16
16
  import { spawnSync } from 'node:child_process';
17
+ import { SPAWN_SYNC_MAX_BUFFER } from '../../util/spawn-sync-output.js';
17
18
  import { debug } from '../../debug/log.js';
18
19
  import { memberHasRegistry, registryImageRef, type RemoteRun } from './pod-pool.js';
19
20
 
@@ -71,7 +72,7 @@ export function memberPinRegistry(member: PodImageMember, source: Extract<PodIma
71
72
 
72
73
  /** 실제 조회 — 원격은 pod-pool 의 SSH 판정, 로컬은 이 기계의 docker/curl 로 조회한다. */
73
74
  export function podPoolImageLookup(run?: RemoteRun, localRun: (cmd: string, args: readonly string[]) => { status: number | null; stdout: string } = (cmd, args) => {
74
- const r = spawnSync(cmd, [...args], { encoding: 'utf8', timeout: 10_000 });
75
+ const r = spawnSync(cmd, [...args], { encoding: 'utf8', timeout: 10_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
75
76
  return { status: r.status, stdout: r.stdout ?? '' };
76
77
  }): {
77
78
  hasRegistry: (member: PodImageMember & { context: string }, registry: string) => boolean;
@@ -1,3 +1,5 @@
1
+ import { spawn } from 'node:child_process';
2
+
1
3
  // GATE-INSTALL-CACHE (0.2.20) — a node-wide throttle for the release-gate shards' `bun install`.
2
4
  //
3
5
  // Cause, measured on the 0.2.19 gate (`elanous logs --category release-loop.gate --event pod-shard --all --include-test`):
@@ -21,8 +23,8 @@ export const POD_INSTALL_SLOTS_HOST_PATH = '/var/lib/elanous/gate-install-slots'
21
23
  export const POD_INSTALL_SLOTS_DEFAULT = 4;
22
24
  export const POD_INSTALL_SLOTS_MOUNT = '/gate-install-slots';
23
25
 
24
- /** hostPath volume ⊕ mount for the tokens. `DirectoryOrCreate` makes a root-owned 0755 directory, so the Pod also needs
25
- * {@link podHostDirsInit} (the child runs as uid 1000). */
26
+ /** hostPath volume ⊕ mount for the tokens. `DirectoryOrCreate` makes a root-owned 0755 directory, so the node also needs
27
+ * {@link prepareHostDirsOnce} (the child runs as uid 1000). */
26
28
  export function podInstallSlotsVolume(hostPath: string = POD_INSTALL_SLOTS_HOST_PATH) {
27
29
  return {
28
30
  volume: { name: 'install-slots', hostPath: { path: hostPath, type: 'DirectoryOrCreate' } },
@@ -30,22 +32,125 @@ export function podInstallSlotsVolume(hostPath: string = POD_INSTALL_SLOTS_HOST_
30
32
  };
31
33
  }
32
34
 
35
+ // GATE-WARM-BOOT-NO-INIT (10-15) — the root hand-over of the hostPath directories left the Pod. It was an init container
36
+ // (`host-dirs`, then folded into `isolation-gate` by GATE-WARM-BOOT), and every init container cost a container
37
+ // transition on a loaded k3d node (#27805 on node-b: init 2 → 354 s · init 1 → 41 s · none → 1 s to the child start).
38
+ // The directories live on the node and outlive every Pod, so the hand-over is a node fact: done once per node from the
39
+ // pool host (`docker exec` into each k3d node container · idempotent `mkdir -p`/`chown`/`chmod`), and the child shell only
40
+ // reports a directory it still cannot write. Never fails the Pod: an unwritable directory means the child falls back
41
+ // (no cache · no throttle), exactly as before when the hand-over failed.
42
+
43
+ const SAFE_HOST_PATH = /^\/[A-Za-z0-9._/-]+$/;
44
+ const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
45
+ export const HOST_DIRS_PREP_LIMIT_MS = 30_000;
46
+
47
+ /** Child-shell line: report (never fail on) a mounted host directory the uid-1000 child cannot write. */
48
+ /** Root hand-over inside the Pod — only for runs whose hostPath dirs could not be prepared on the node (no pool member ·
49
+ * prep failed · prep disabled). Same lines the old `isolation-gate` init ran; it never fails the Pod. */
50
+ export function podHostDirsScript(mounts: ReadonlyArray<{ mountPath: string }>): string {
51
+ const paths = mounts.map((mount) => `'${mount.mountPath.replace(/'/g, `'\\''`)}'`).join(' ');
52
+ return `for d in ${paths}; do mkdir -p "$d" && chown 1000:1000 "$d" && chmod 0775 "$d" || echo "[host-dirs] could not prepare $d"; done; exit 0`;
53
+ }
54
+
55
+ export function podHostDirsCheckScript(mounts: ReadonlyArray<{ mountPath: string }>): string {
56
+ const paths = mounts.map((mount) => `'${mount.mountPath.replace(/'/g, `'\\''`)}'`).join(' ');
57
+ return `for d in ${paths}; do [ -d "$d" ] && [ -w "$d" ] || echo "[host-dirs] could not prepare $d (not writable by uid $(id -u) · node not prepared)"; done`;
58
+ }
59
+
60
+ /** Host-side shell (on the pool host): hand the node directories to uid 1000 in every k3d node container of `cluster`. */
61
+ export function podHostDirsNodeScript(o: { cluster: string; hostPaths: readonly string[] }): string {
62
+ if (!SAFE_NAME.test(o.cluster)) throw new Error(`invalid k3d cluster: ${o.cluster}`);
63
+ for (const path of o.hostPaths) if (!SAFE_HOST_PATH.test(path) || path.split('/').includes('..')) throw new Error(`invalid host dir: ${path}`);
64
+ const inner = `for d in ${o.hostPaths.join(' ')}; do mkdir -p "$d" && chown 1000:1000 "$d" && chmod 0775 "$d" || { echo "[host-dirs] could not prepare $d"; exit 1; }; done`;
65
+ return [
66
+ `nodes=$(docker ps --filter label=k3d.cluster=${o.cluster} --format '{{.Names}} {{.Label "k3d.role"}}' | awk '$2=="server"||$2=="agent"{print $1}')`,
67
+ `[ -n "$nodes" ] || { echo "[host-dirs] no k3d node for ${o.cluster}"; exit 2; }`,
68
+ 'rc=0',
69
+ `for n in $nodes; do docker exec "$n" sh -c '${inner}' || rc=1; done`,
70
+ 'exit $rc',
71
+ ].join('\n');
72
+ }
73
+
74
+ /** The member's current k3d server/agent container IDs, sorted — the node «generation» the hand-over memo is keyed by. */
75
+ export function podHostDirsNodeIdsScript(cluster: string): string {
76
+ if (!SAFE_NAME.test(cluster)) throw new Error(`invalid k3d cluster: ${cluster}`);
77
+ return `docker ps --no-trunc --filter label=k3d.cluster=${cluster} --format '{{.ID}} {{.Label "k3d.role"}}' | awk '$2=="server"||$2=="agent"{print $1}' | sort | tr '\\n' ' '`;
78
+ }
79
+
80
+ export interface HostDirsPrepResult { host: string; ok: boolean; ms: number; detail?: string }
81
+
82
+ type HostShell = (host: string | undefined, script: string, limitMs: number) => Promise<{ rc: number; output: string }>;
83
+
33
84
  /**
34
- * A root init container that hands the mounted hostPath directories to the child's uid. Without it a `DirectoryOrCreate`
35
- * hostPath stays root:root 0755 and the child's `[ -w … ]` guard silently skips it (the Bun cache option was a no-op).
85
+ * Bounded shell on the pool host (`ssh <host>`) or this machine (no host); never throws. At `limitMs` the whole process
86
+ * group is killed and the call returns rc 124 at once — a stuck `docker exec` grandchild holding the pipe must not keep
87
+ * the caller (and the Job launch behind it) waiting for `close`.
36
88
  */
37
- export function podHostDirsInit(image: string, imagePullPolicy: string, mounts: ReadonlyArray<{ name: string; mountPath: string; readOnly: boolean }>) {
38
- const paths = mounts.map((mount) => `'${mount.mountPath.replace(/'/g, `'\\''`)}'`).join(' ');
39
- return {
40
- name: 'host-dirs', image, imagePullPolicy,
41
- securityContext: { runAsUser: 0 },
42
- command: ['sh', '-c'],
43
- // Never fails the Pod: an unchanged directory only means the child falls back (no cache · no throttle).
44
- args: [`for d in ${paths}; do mkdir -p "$d" && chown 1000:1000 "$d" && chmod 0775 "$d" || echo "[host-dirs] could not prepare $d"; done; exit 0`],
45
- volumeMounts: mounts.map((mount) => ({ ...mount })),
46
- };
89
+ export function hostShellWithin(host: string | undefined, script: string, limitMs: number): Promise<{ rc: number; output: string }> {
90
+ const env = 'export PATH=/opt/homebrew/bin:/usr/local/bin:$HOME/.orbstack/bin:$PATH; ';
91
+ const [cmd, args] = host
92
+ ? ['ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', host, env + script]] as const
93
+ : ['bash', ['-c', env + script]] as const;
94
+ return new Promise((resolve) => {
95
+ let output = '';
96
+ let settled = false;
97
+ let timer: ReturnType<typeof setTimeout> | undefined;
98
+ const finish = (rc: number, text: string) => { if (!settled) { settled = true; clearTimeout(timer); resolve({ rc, output: text }); } };
99
+ let child: ReturnType<typeof spawn>;
100
+ try { child = spawn(cmd, [...args], { stdio: ['ignore', 'pipe', 'pipe'], detached: true }); }
101
+ catch (error) { resolve({ rc: 2, output: String(error) }); return; }
102
+ timer = setTimeout(() => {
103
+ try { if (child.pid) process.kill(-child.pid, 'SIGKILL'); else child.kill('SIGKILL'); } catch { child.kill('SIGKILL'); }
104
+ child.stdout?.destroy();
105
+ child.stderr?.destroy();
106
+ finish(124, `${output}\n[host-dirs] timed out after ${limitMs} ms`);
107
+ }, limitMs);
108
+ child.stdout?.on('data', (chunk) => { output += String(chunk); });
109
+ child.stderr?.on('data', (chunk) => { output += String(chunk); });
110
+ child.on('error', (error) => finish(2, `${output}\n${String(error)}`));
111
+ child.on('close', (code) => finish(code ?? 2, output));
112
+ });
47
113
  }
48
114
 
115
+ const prepared = new Map<string, Promise<HostDirsPrepResult>>();
116
+
117
+ /**
118
+ * Hand `hostPaths` to uid 1000 on the member's k3d nodes once per (host, cluster, node generation, path) in this process — every shard Job
119
+ * on the same member awaits the same run, and a path already handed over (or in flight) is not run again even when it
120
+ * comes with a different companion path. A failure is not memoized (the next Job tries again) and never throws.
121
+ */
122
+ export async function prepareHostDirsOnce(o: { member: { sshHost?: string; k3dCluster: string }; hostPaths: readonly string[]; shell?: HostShell; limitMs?: number }): Promise<HostDirsPrepResult> {
123
+ const host = o.member.sshHost;
124
+ const label = host ?? 'local';
125
+ const start = Date.now();
126
+ const shell = o.shell ?? hostShellWithin;
127
+ // Node generation (review mf): a recreated cluster or a new agent has other container IDs, so a hand-over remembered for
128
+ // the old node set is not reused. Unreadable IDs → no memo at all (every path runs, success is not remembered).
129
+ const ids = await shell(host, podHostDirsNodeIdsScript(o.member.k3dCluster), o.limitMs ?? HOST_DIRS_PREP_LIMIT_MS)
130
+ .catch(() => ({ rc: 2, output: '' }));
131
+ const generation = ids.rc === 0 && ids.output.trim() ? ids.output.trim() : null;
132
+ const gen = generation ?? `unknown-${start}-${Math.random()}`;
133
+ const keyOf = (path: string) => `${label}\0${o.member.k3dCluster}\0${gen}\0${path}`;
134
+ const paths = [...new Set(o.hostPaths)].sort();
135
+ const fresh = paths.filter((path) => !prepared.has(keyOf(path)));
136
+ if (fresh.length) {
137
+ const run = (async (): Promise<HostDirsPrepResult> => {
138
+ const script = podHostDirsNodeScript({ cluster: o.member.k3dCluster, hostPaths: fresh });
139
+ const r = await shell(host, script, o.limitMs ?? HOST_DIRS_PREP_LIMIT_MS);
140
+ const ms = Date.now() - start;
141
+ return r.rc === 0 ? { host: label, ok: true, ms } : { host: label, ok: false, ms, detail: r.output.trim().slice(-300) || `rc=${r.rc}` };
142
+ })().catch((error: unknown) => ({ host: label, ok: false, ms: Date.now() - start, detail: String(error).slice(0, 300) }))
143
+ .then((result) => { if (!result.ok || generation === null) for (const path of fresh) prepared.delete(keyOf(path)); return result; });
144
+ for (const path of fresh) prepared.set(keyOf(path), run);
145
+ }
146
+ const results = await Promise.all(paths.map((path) => prepared.get(keyOf(path))!));
147
+ const failed = results.find((result) => !result.ok);
148
+ return failed ?? { host: label, ok: true, ms: Date.now() - start };
149
+ }
150
+
151
+ /** Test seam — forget the per-process hand-over memo. */
152
+ export function resetHostDirsPrepMemo(): void { prepared.clear(); }
153
+
49
154
  const int = (value: number, label: string) => {
50
155
  if (!Number.isSafeInteger(value) || value < 1) throw new Error(`invalid ${label}: ${value}`);
51
156
  return value;
@@ -71,7 +176,9 @@ export function installSlotScript(o: { dir?: string; slots: number; waitSeconds?
71
176
  ' if [ ! -d "$d" ] || [ ! -w "$d" ]; then echo "[gate] install-slot none (directory not writable)"; return 0; fi',
72
177
  ' while :; do',
73
178
  ` for n in $(seq 0 ${slots - 1}); do`,
74
- ' if mkdir "$d/slot-$n" 2>/dev/null; then',
179
+ // The token is taken by bash's own noclobber create (O_EXCL), not by `mkdir`: uutils coreutils `mkdir` (0.8 · wsl gate host)
180
+ // let two racing callers both succeed on one path (10-16 · 3 holders on 2 slots). A directory token left by an older shell still counts as held.
181
+ ' if (set -C; : > "$d/slot-$n") 2>/dev/null; then',
75
182
  ' install_slot="$d/slot-$n"',
76
183
  ' echo "[gate] install-slot $n waited $(( $(date +%s) - t0 ))s"; return 0',
77
184
  ' fi',
@@ -11,13 +11,23 @@ import { hostLeaseBaseDir, type PendingJobIdentity } from '../../pod-lease/host-
11
11
  // POD-CPU-REQUEST-RIGHTSIZE(10-09 · OP 실측): 하니스 Pod 실사용은 대부분 100m 미만(LLM 응답 대기)인데 요청 1 CPU 를
12
12
  // 잡아 node-b 32코어가 «요청 31/32»로 막혔다(실사용 4.6코어 · 14%). 요청은 실사용 근처로, 한도(4)는 그대로 — 몰릴 때는 한도까지 쓴다.
13
13
  // 게이트·pod-command 기본은 pod-command-job.ts 의 POD_COMMAND_CPU_REQUEST_DEFAULT(1)로 따로 둔다(테스트 조각은 CPU 를 실제로 쓴다).
14
- export const POD_CHILD_REQUESTS = { cpu: '250m', memory: '6Gi' } as const;
14
+ // SI-TASK-ADMIT-RIGHTSIZE: one host env restores the previous 6Gi request and uncapped p95 admission.
15
+ // An invalid override fails conservative at 6Gi rather than silently under-reserving a Pod.
16
+ export function resolveSiTaskMemoryPolicy(override: string | undefined): { requestMemory: string; admissionCapBytes: number | null; source: string } {
17
+ if (override === undefined) return { requestMemory: '3Gi', admissionCapBytes: 3 * 1024 ** 3, source: 'default' };
18
+ if (override === '6Gi') return { requestMemory: '6Gi', admissionCapBytes: null, source: 'override' };
19
+ return { requestMemory: '6Gi', admissionCapBytes: null, source: 'invalid-override-fallback' };
20
+ }
21
+ const siMemoryPolicy = resolveSiTaskMemoryPolicy(process.env.ELANOUS_POD_SI_REQUEST_MEMORY);
22
+ export const POD_CHILD_REQUESTS = { cpu: '250m', memory: siMemoryPolicy.requestMemory } as const;
15
23
  /** Finished harness and command Jobs release their Pod slots after 30 minutes. */
16
24
  export const POD_JOB_TTL_AFTER_FINISHED_SECONDS = 1800;
17
25
  /** 게이트가 돌 때 하니스 «한 자리»로 셈하는 CPU — 요청(250m)보다 보수적으로 1 코어를 잡아 게이트 조각의 CPU 를 지킨다(GATE-RESERVE-AUTO 셈은 그대로). */
18
26
  export const HARNESS_SLOT_CPU_BESIDE_GATE = '1';
19
27
  /** POD-ADMIT-BY-USAGE — observed usage is scaled by this before it reserves memory. */
20
28
  const POD_USAGE_HEADROOM = 1.5;
29
+ /** New standard si-task admission only. Existing Running Pods keep their observed/requested reservation. */
30
+ export const POD_SI_ADMISSION_CAP_BYTES = siMemoryPolicy.admissionCapBytes;
21
31
  /** POD-ADMIT-BY-USAGE — a node keeps at least this share of allocatable memory free (real usage and bookkeeping). */
22
32
  const POD_NODE_FREE_FLOOR_RATIO = 0.1;
23
33
 
@@ -477,6 +487,7 @@ export function measurePoolLease(members: readonly PodPoolMember[], deps: { kube
477
487
  const leasedJobs = new Set<string>();
478
488
  const gateJobs = new Map<string, number>();
479
489
  const boundGateJobs = new Set<string>();
490
+ const commandJobs = new Set<string>();
480
491
  let jobsValid = true;
481
492
  for (const job of jobItems) {
482
493
  const meta = object(job.metadata);
@@ -484,6 +495,7 @@ export function measurePoolLease(members: readonly PodPoolMember[], deps: { kube
484
495
  if (object(meta.labels)?.['elanous.substrate'] !== 'pod') continue;
485
496
  if (typeof meta.name !== 'string' || !meta.name) { jobsValid = false; continue; }
486
497
  jobNames.add(meta.name);
498
+ if (object(meta.labels)?.['elanous.kind'] === 'command') commandJobs.add(meta.name);
487
499
  // GATE-RESERVE-AUTO: a release-gate shard Job (`gate-<uuid>`, kind=command) reserves its Pod template's CPU
488
500
  // from creation until it is terminal — also while its Pod is still Pending or not created yet.
489
501
  if (meta.name.startsWith('gate-') && object(meta.labels)?.['elanous.kind'] === 'command') {
@@ -521,7 +533,8 @@ export function measurePoolLease(members: readonly PodPoolMember[], deps: { kube
521
533
  } else reservationsValid = false;
522
534
  const ownerJob = String(labels?.['elanous.job'] ?? labels?.['job-name'] ?? '');
523
535
  const gatePod = metadata?.namespace === 'elanous-test' && gateJobs.has(ownerJob);
524
- const harness = metadata?.namespace === 'elanous-test' && labels?.['elanous.probe'] !== 'dns' && !gatePod &&
536
+ const commandPod = labels?.['elanous.kind'] === 'command' || commandJobs.has(ownerJob);
537
+ const harness = metadata?.namespace === 'elanous-test' && labels?.['elanous.probe'] !== 'dns' && !gatePod && !commandPod &&
525
538
  (labels?.['elanous.substrate'] === 'pod' || jobNames.has(String(labels?.['elanous.job'] ?? '')));
526
539
  const spec = object(pod.spec);
527
540
  let limit: number | null = null;
@@ -642,7 +655,7 @@ export function recommendConcurrency(measure: PoolLeaseMeasure, options: { capac
642
655
  if (goalBytes === null || goalBytes <= 0) return { ...empty, reason: '측정 불가: perGoalMemory' };
643
656
  const admission = admissionByUsage(measure, goalBytes, options.perGoalMemory !== undefined);
644
657
  if (!measure.members.length || measure.members.some((m) => m.running === null || m.pending === null || m.unleasedRunning === null || m.allocatableMemoryBytes === null || m.memoryLimitBytes === null || m.allocatableCpuMillicores === null || m.availableMemoryByNodeBytes === null)) {
645
- debug.log('pod-lease', 'admit-by-usage', { samples: admission.samples, p95Bytes: admission.p95Bytes, admitBytes: admission.admitBytes, fallback: admission.fallback, recommended: null, limitedBy: null, capacity: options.capacity, capacitySlots: null, memorySlots: null, running: null, pending: null });
658
+ debug.log('pod-lease', 'admit-by-usage', { samples: admission.samples, p95Bytes: admission.p95Bytes, admitBytes: admission.admitBytes, fallback: admission.fallback, requestMemory: siMemoryPolicy.requestMemory, admissionCapBytes: POD_SI_ADMISSION_CAP_BYTES, policySource: siMemoryPolicy.source, recommended: null, limitedBy: null, capacity: options.capacity, capacitySlots: null, memorySlots: null, running: null, pending: null });
646
659
  return { ...empty, reason: `측정 불가: cluster${measure.members.map((m) => m.reason ? ` ${m.context}: ${m.reason}` : '').join('')}` };
647
660
  }
648
661
  if (!Number.isSafeInteger(options.capacity) || options.capacity < 0) return { ...empty, reason: '측정 불가: capacity' };
@@ -694,7 +707,7 @@ export function recommendConcurrency(measure: PoolLeaseMeasure, options: { capac
694
707
  && m.reason !== 'dns' && m.running !== null && m.pending !== null && m.running + m.pending >= m.capacity);
695
708
  const limitedBy: PoolLeaseRecommendation['limitedBy'] = memoryBound < capacitySlots ? 'memory' : defaultCapFull ? 'pool-cap' : 'capacity';
696
709
  if (unleasedRunning > 0) debug.log('pod-lease', 'unleased', { unleasedRunning, running, recommended });
697
- debug.log('pod-lease', 'admit-by-usage', { samples: admission.samples, p95Bytes: admission.p95Bytes, admitBytes: admission.admitBytes, fallback: admission.fallback, recommended, limitedBy, capacity: options.capacity, capacitySlots, memorySlots, running, pending });
710
+ debug.log('pod-lease', 'admit-by-usage', { samples: admission.samples, p95Bytes: admission.p95Bytes, admitBytes: admission.admitBytes, fallback: admission.fallback, requestMemory: siMemoryPolicy.requestMemory, admissionCapBytes: POD_SI_ADMISSION_CAP_BYTES, policySource: siMemoryPolicy.source, recommended, limitedBy, capacity: options.capacity, capacitySlots, memorySlots, running, pending });
698
711
  return { recommended, limitedBy, reason: measure.members.some((m) => m.reason === 'dns') ? 'dns' : null, capacitySlots, memorySlots, liteMemorySlots, placeableSlots, accountSlots, running, pending, pendingJobs, unleasedRunning, admission };
699
712
  }
700
713
 
@@ -714,7 +727,8 @@ function admissionByUsage(measure: PoolLeaseMeasure, goalBytes: number, explicit
714
727
  : live.some((m) => m.harnessUsageBytes == null) ? (live.map((m) => m.harnessUsageBytes == null ? `${m.context}: ${m.usageReason ?? 'usage not measured'}` : '').filter(Boolean).join('; '))
715
728
  : p95Bytes === null ? 'no Running harness Pod usage samples'
716
729
  : null;
717
- const admitBytes = fallback !== null || p95Bytes === null ? goalBytes
718
- : Math.min(goalBytes, Math.max(requestBytes, Math.ceil(p95Bytes * POD_USAGE_HEADROOM)));
730
+ const observedBytes = p95Bytes === null ? null : Math.ceil(p95Bytes * POD_USAGE_HEADROOM);
731
+ const admitBytes = fallback !== null || observedBytes === null ? goalBytes
732
+ : Math.min(goalBytes, Math.max(requestBytes, POD_SI_ADMISSION_CAP_BYTES === null ? observedBytes : Math.min(observedBytes, POD_SI_ADMISSION_CAP_BYTES)));
719
733
  return { samples: samples.length, p95Bytes, admitBytes, fallback };
720
734
  }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * POD-LIFECYCLE-STAGES (P0 · Pod 재사용 기준선) — Pod 하나가 끝날 때 «어느 단계에 시간이 갔나»를 한 줄로 낸다.
3
+ *
4
+ * 계약: category `pod.lifecycle` · event `stages` ·
5
+ * data `{ runId, podJob, host, kind, stages: [{ stage, start, end, clock }], outcome, missing }`.
6
+ * - 시각은 epoch ms 하나로 통일한다(Pod 시계의 초 값은 ×1000).
7
+ * - `clock` 은 그 값이 어느 시계에서 왔나 — `host`(이 프로세스) · `k8s`(API 서버 시각) · `pod`(Pod 안 `date +%s`) · `mixed`.
8
+ * - ⛔ «0초»와 «못 잼»을 섞지 않는다: 시작·끝 둘 다 잰 단계만 `stages` 에 들어가고, 나머지는 이름만 `missing` 에 간다.
9
+ * 끝이 시작보다 앞서면(시계가 어긋났다) 그 단계도 지어내지 않고 `missing` 이다.
10
+ *
11
+ * 관측만 한다 — 판정·rc·파일을 바꾸지 않고, 내보내기가 실패해도 삼킨다.
12
+ */
13
+ import { debug } from '../../debug/log.js';
14
+
15
+ export const POD_LIFECYCLE_STAGES = ['create', 'schedule', 'clone', 'mirror', 'deps', 'test', 'delete'] as const;
16
+ /** si-task Pod 은 시험이 아니라 `self implement`(또는 harness ask/say) 본체를 돈다 — 그 칸은 `test` 가 아니라 `run` 이다. */
17
+ export const SI_TASK_POD_LIFECYCLE_STAGES = ['create', 'schedule', 'clone', 'mirror', 'deps', 'run', 'delete'] as const;
18
+ export type PodLifecycleStageName = typeof POD_LIFECYCLE_STAGES[number] | typeof SI_TASK_POD_LIFECYCLE_STAGES[number];
19
+ export type PodLifecycleClock = 'host' | 'k8s' | 'pod' | 'mixed';
20
+ export type PodLifecycleKind = 'gate' | 'si-task';
21
+
22
+ export interface PodLifecycleStage { stage: PodLifecycleStageName; start: number; end: number; clock: PodLifecycleClock }
23
+
24
+ export interface PodLifecycleEvent {
25
+ runId: string | null;
26
+ podJob: string | null;
27
+ host: string | null;
28
+ kind: PodLifecycleKind;
29
+ stages: PodLifecycleStage[];
30
+ outcome: string;
31
+ missing: PodLifecycleStageName[];
32
+ [extra: string]: unknown;
33
+ }
34
+
35
+ type Measured = Partial<Record<PodLifecycleStageName, { start?: number; end?: number; clock: PodLifecycleClock }>>;
36
+
37
+ /** ISO 문자열 → epoch ms (못 읽으면 undefined — 지어내지 않는다). */
38
+ export function isoMs(value: string | undefined): number | undefined {
39
+ if (typeof value !== 'string') return undefined;
40
+ const ms = Date.parse(value);
41
+ return Number.isFinite(ms) ? ms : undefined;
42
+ }
43
+
44
+ /** Pod 시계의 epoch 초 → ms. */
45
+ function podSecondsMs(value: number | undefined): number | undefined {
46
+ return typeof value === 'number' && Number.isFinite(value) ? value * 1000 : undefined;
47
+ }
48
+
49
+ /** 잰 것만 stages 로, 나머지는 missing 으로 — 계약의 단계 순서대로. */
50
+ export function splitPodLifecycleStages(measured: Measured, order: readonly PodLifecycleStageName[] = POD_LIFECYCLE_STAGES): { stages: PodLifecycleStage[]; missing: PodLifecycleStageName[] } {
51
+ const stages: PodLifecycleStage[] = [];
52
+ const missing: PodLifecycleStageName[] = [];
53
+ for (const name of order) {
54
+ const item = measured[name];
55
+ if (item && item.start !== undefined && item.end !== undefined && item.end >= item.start) stages.push({ stage: name, start: item.start, end: item.end, clock: item.clock });
56
+ else missing.push(name);
57
+ }
58
+ return { stages, missing };
59
+ }
60
+
61
+ /**
62
+ * gate shard Pod — `pod-N.json` 에 쓰는 바로 그 값(phaseTimes · podStages · podLifecycle)에서 단계를 고른다.
63
+ * - create = 풀 자리 배정(없으면 입장 끝 · host) → Pod 생성(k8s)
64
+ * - schedule = Pod 생성 → PodScheduled (k8s)
65
+ * - clone = 자식 컨테이너 PID 1(prep-start) → 셸 첫 줄(clone-end) (pod)
66
+ * - deps = deps-start → deps-end (pod) · test = test-start → test-end (pod)
67
+ * - mirror · delete = gate 는 Pod 별로 재지 않는다 → 늘 missing.
68
+ */
69
+ export function gatePodLifecycleStages(input: {
70
+ phaseTimes?: Readonly<Record<string, string>>;
71
+ podStages?: Readonly<Record<string, number>>;
72
+ podLifecycle?: Readonly<Record<string, string>>;
73
+ }): { stages: PodLifecycleStage[]; missing: PodLifecycleStageName[] } {
74
+ const phase = input.phaseTimes ?? {};
75
+ const pod = input.podStages ?? {};
76
+ const k8s = input.podLifecycle ?? {};
77
+ return splitPodLifecycleStages({
78
+ create: { start: isoMs(phase.poolPlaced) ?? isoMs(phase.admissionEnd), end: isoMs(k8s.podCreated), clock: 'mixed' },
79
+ schedule: { start: isoMs(k8s.podCreated), end: isoMs(k8s.podScheduled), clock: 'k8s' },
80
+ clone: { start: podSecondsMs(pod['prep-start']), end: podSecondsMs(pod['clone-end']), clock: 'pod' },
81
+ deps: { start: podSecondsMs(pod['deps-start']), end: podSecondsMs(pod['deps-end']), clock: 'pod' },
82
+ test: { start: podSecondsMs(pod['test-start']), end: podSecondsMs(pod['test-end']), clock: 'pod' },
83
+ });
84
+ }
85
+
86
+ /** gate shard 의 끝 — 판정 코드와 같은 순서(잡 실패 → 정지 → 시간 초과 → 판정 없음 → rc). */
87
+ export function gatePodOutcome(o: { jobFailed: boolean; stalled: boolean; timedOut: boolean; rc: number | undefined }): string {
88
+ if (o.jobFailed) return 'job-failed';
89
+ if (o.stalled) return 'stall';
90
+ if (o.timedOut) return 'timeout';
91
+ if (o.rc === undefined) return 'no-verdict';
92
+ return o.rc === 0 ? 'pass' : 'fail';
93
+ }
94
+
95
+ export function gatePodLifecycleEvent(input: {
96
+ runId?: string | null;
97
+ podJob?: string | null;
98
+ host?: string | null;
99
+ shard: string;
100
+ attemptId?: string;
101
+ phaseTimes?: Readonly<Record<string, string>>;
102
+ podStages?: Readonly<Record<string, number>>;
103
+ podLifecycle?: Readonly<Record<string, string>>;
104
+ outcome: string;
105
+ }): PodLifecycleEvent {
106
+ const { stages, missing } = gatePodLifecycleStages(input);
107
+ return { runId: input.runId ?? null, podJob: input.podJob ?? null, host: input.host ?? null, kind: 'gate', stages, outcome: input.outcome, missing,
108
+ shard: input.shard, ...(input.attemptId ? { attemptId: input.attemptId } : {}) };
109
+ }
110
+
111
+ /** si-task Pod 셸이 찍는 단계 표지 — `ELANOUS_POD_STAGE <stage> <start|end> <epoch초>` (Pod 시계 · `date +%s`). */
112
+ /** Pod 셸이 실제로 표지를 찍는 단계만 — deps 는 si-task Job 에 설치 단계가 없어 읽지도 않는다(늘 missing). */
113
+ const SI_TASK_MARKED_STAGES = ['clone', 'mirror', 'run'] as const;
114
+ export type SiTaskMarkedStage = typeof SI_TASK_MARKED_STAGES[number];
115
+
116
+ /** Pod 셸 한 줄 — 단계 경계에서 Pod 시계(초)를 찍는다. 실패해도 셸을 끊지 않는다(`|| true`). */
117
+ export function siTaskPodStageShell(stage: SiTaskMarkedStage, edge: 'start' | 'end'): string {
118
+ return `printf 'ELANOUS_POD_STAGE ${stage} ${edge} %s\\n' "$(date +%s)" || true`;
119
+ }
120
+ const SI_TASK_STAGE_LINE = /^ELANOUS_POD_STAGE (clone|mirror|run) (start|end) (\d{1,12})\r?$/gm;
121
+
122
+ /**
123
+ * Job 로그에서 단계 표지를 읽는다 → `{ 'clone-start': 초, 'clone-end': 초, … }` (gate 의 podStages 와 같은 꼴).
124
+ * 같은 표지가 두 번 나오면 «첫» 값 — 셸 표지는 모두 자식 출력(`cat /tmp/si.out`)보다 앞에 찍히므로, 자식이 같은 모양의 줄을
125
+ * 내도 셸 값을 덮지 못한다(리뷰 should-fix). 모르는 단계·꼴은 버린다(지어내지 않는다).
126
+ */
127
+ export function parseSiTaskPodStages(logs: string | undefined): Record<string, number> {
128
+ const out: Record<string, number> = {};
129
+ if (!logs) return out;
130
+ for (const match of logs.matchAll(SI_TASK_STAGE_LINE)) {
131
+ const key = `${match[1]}-${match[2]}`;
132
+ if (!(key in out)) out[key] = Number(match[3]);
133
+ }
134
+ return out;
135
+ }
136
+
137
+ /**
138
+ * si-task Pod — Pod 셸이 찍은 단계 표지(`parseSiTaskPodStages`)로 clone · mirror · deps · run 을 채운다(pod 시계).
139
+ * - clone = 소스 받기(`podSourceScript`) 시작 → 그 스크립트 전체가 끝난 뒤(`cd repo` 포함 · 어느 줄에서든 exit 하면 끝이 없다 → missing)
140
+ * - mirror = 호스트 미러 `clone --shared` 시도 → 성공(미러를 건너뛰면 끝이 없다 → missing)
141
+ * - deps = si-task Job 셸엔 의존성 설치 단계가 없다 → 표지를 읽지 않는다(`deps` 표지 줄이 있어도 늘 missing)
142
+ * - run = 본체(`self implement` · `harness ask`/`say`) 띄움 → `wait` 가 돌아옴(SIGTERM 이면 끝이 없다 → missing)
143
+ * - create · schedule · delete = 호스트가 잴 값이 없다 → missing.
144
+ * 호스트가 지켜본 구간은 단계가 아닌 `watch`(host 시계)로 따로 싣는다 — 단계로 지어내지 않는다.
145
+ */
146
+ export function siTaskPodLifecycleEvent(input: {
147
+ runId?: string | null;
148
+ podJob: string;
149
+ host?: string | null;
150
+ watchStart?: number;
151
+ watchEnd?: number;
152
+ podStages?: Readonly<Record<string, number>>;
153
+ outcome: string;
154
+ }): PodLifecycleEvent {
155
+ const pod = input.podStages ?? {};
156
+ const measured: Measured = {};
157
+ for (const name of SI_TASK_MARKED_STAGES) measured[name] = { start: podSecondsMs(pod[`${name}-start`]), end: podSecondsMs(pod[`${name}-end`]), clock: 'pod' };
158
+ const { stages, missing } = splitPodLifecycleStages(measured, SI_TASK_POD_LIFECYCLE_STAGES);
159
+ const watched = input.watchStart !== undefined && input.watchEnd !== undefined && Number.isFinite(input.watchStart) && Number.isFinite(input.watchEnd) && input.watchEnd >= input.watchStart;
160
+ return { runId: input.runId ?? null, podJob: input.podJob, host: input.host ?? null, kind: 'si-task', stages, outcome: input.outcome, missing,
161
+ ...(watched ? { watch: { start: input.watchStart, end: input.watchEnd, clock: 'host' as const } } : {}) };
162
+ }
163
+
164
+ export type PodLifecycleLog = (category: string, event: string, data: Record<string, unknown>) => void;
165
+
166
+ /** 한 줄 낸다 — 관측은 fail-soft(판정 경로를 절대 깨지 않는다). */
167
+ export function emitPodLifecycle(event: PodLifecycleEvent, log: PodLifecycleLog = (category, name, data) => debug.log(category, name, data)): void {
168
+ try { log('pod.lifecycle', 'stages', event); } catch { /* observation is fail-soft */ }
169
+ }