elanous 0.2.29 → 0.2.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  93. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  94. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  109. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  121. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-a5635eba0d73b84e.js → page-2ebb8fd59b9461f9.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0a07363b130182a1.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-521ee23ac8c0abfa.js} +1 -1
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-9f92737b8766009a.js → page-149dc1caba411bb9.js} +1 -1
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  183. package/apps/pwa/out/_next/static/css/{72becfd42807b50d.css → 3f5fc6f96e2cf7b2.css} +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/bin/elanous.mjs +7 -3
  278. package/graphs/context/nightly-condense.yaml +1 -0
  279. package/graphs/intake/intake-daily.yaml +8 -1
  280. package/graphs/intake/recipes.yaml +5 -0
  281. package/graphs/lecture/lecture-note.yaml +2 -2
  282. package/graphs/ops/harness-gc.yaml +1 -0
  283. package/graphs/release/recipes.yaml +3 -0
  284. package/graphs/release/release-loop.yaml +9 -5
  285. package/graphs/units/recipes.yaml +3 -0
  286. package/graphs/units/release-gate-recheck.yaml +15 -0
  287. package/package.json +2 -1
  288. package/scripts/check-native-tool-wiring.ts +3 -2
  289. package/scripts/ci-android-unit-tests.ts +16 -0
  290. package/scripts/ci-typecheck-changed.ts +37 -9
  291. package/scripts/coord-channel-watch.sh +22 -16
  292. package/scripts/coord-role-pack.ts +81 -2
  293. package/scripts/cron-run.ts +96 -3
  294. package/scripts/detect-test-interference.ts +38 -5
  295. package/scripts/gate-pr-cache.ts +65 -0
  296. package/scripts/gh-surface/capture.ts +126 -0
  297. package/scripts/gh-surface/gh +40 -0
  298. package/scripts/import-graph-scc.ts +38 -0
  299. package/scripts/install.ps1 +19 -0
  300. package/scripts/intake-social.ts +181 -0
  301. package/scripts/lecture-note/node.ts +71 -4
  302. package/scripts/lib/android-toolchain.ts +32 -0
  303. package/scripts/lib/deterministic-env.ts +62 -0
  304. package/scripts/lib/gate-test-env.ts +19 -0
  305. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  306. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  307. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  308. package/scripts/release-loop/cut-branch.ts +4 -3
  309. package/scripts/release-loop/export-check-node.ts +0 -1
  310. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  311. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  312. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  313. package/scripts/release-loop/gate-closure.ts +12 -8
  314. package/scripts/release-loop/gate-diff.ts +1 -1
  315. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  316. package/scripts/release-loop/gate-node.ts +523 -75
  317. package/scripts/release-loop/gate-partial.ts +106 -9
  318. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  319. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  320. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  321. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  322. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  323. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  324. package/scripts/release-loop/import-graph-scc.ts +215 -0
  325. package/scripts/release-loop/node-verdict.ts +2 -0
  326. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  327. package/scripts/release-loop/resume-release.ts +33 -4
  328. package/scripts/release-loop/resume.ts +13 -5
  329. package/scripts/release-loop/spawn-lane.ts +2 -19
  330. package/scripts/release-loop/tui-sim-node.ts +3 -2
  331. package/scripts/release-loop/unattended-release.ts +16 -0
  332. package/scripts/test-deterministic.ts +5 -61
  333. package/scripts/train-reach-grouping.ts +48 -0
  334. package/scripts/tsc-incremental-cache.ts +86 -0
  335. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  336. package/scripts/tsc-main-safety-net.ts +2 -2
  337. package/src/acp/client.ts +4 -1
  338. package/src/acp/core-turn-bridge.ts +50 -5
  339. package/src/ad-pipeline/run.ts +4 -2
  340. package/src/agent/runner.ts +169 -3
  341. package/src/agent/subagent-callable.ts +3 -2
  342. package/src/agent-mission/review-loop.ts +6 -3
  343. package/src/agent-substrate/acp-implementer.ts +14 -2
  344. package/src/agent-substrate/pr-reviewer.ts +12 -0
  345. package/src/agent-substrate/self-review-cli.ts +30 -4
  346. package/src/autopilot/pr-manager.ts +62 -7
  347. package/src/briefing/brief-items.ts +24 -22
  348. package/src/capture/tui-self-report.ts +15 -0
  349. package/src/chat/chat-cli.ts +10 -2
  350. package/src/chat/index.ts +77 -11
  351. package/src/chat/input-control-key.ts +5 -3
  352. package/src/chat/tool-interrupt-behavior.ts +38 -0
  353. package/src/chat/tool-render/dispatch.ts +5 -1
  354. package/src/chat/turn-typeahead.ts +75 -20
  355. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  356. package/src/cli/agent-cli.ts +41 -13
  357. package/src/cli/config-audit.ts +123 -0
  358. package/src/cli/decisions-cli.ts +80 -6
  359. package/src/cli/log-event-names.ts +7 -0
  360. package/src/cli/mcp-login.ts +21 -5
  361. package/src/cli/msg-cli.ts +88 -0
  362. package/src/cli/pr-cli.ts +214 -57
  363. package/src/cli/pr-land-heavy-remote.ts +2 -2
  364. package/src/cli/pr-land-overlap-evidence.ts +63 -9
  365. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  366. package/src/cli/pr-land-pod-shadow.ts +16 -3
  367. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  368. package/src/cli/release-cli.ts +80 -14
  369. package/src/cli/seat-cli.ts +138 -3
  370. package/src/cli/self-update.ts +5 -2
  371. package/src/cli/tasks-cli.ts +97 -19
  372. package/src/context-bus/context-first.ts +13 -0
  373. package/src/context-bus/context-now.ts +13 -2
  374. package/src/context-bus/ops-events.ts +75 -0
  375. package/src/control-plane/lease-holder.ts +12 -8
  376. package/src/control-plane/ledger.ts +163 -4
  377. package/src/control-plane/server.ts +91 -11
  378. package/src/core-turn/run-core-turn.ts +1 -0
  379. package/src/core-turn/run-goal-loop.ts +222 -3
  380. package/src/core-turn/seat-turn-cap.ts +79 -0
  381. package/src/core-turn/short-question.ts +38 -6
  382. package/src/core-turn/types.ts +3 -0
  383. package/src/dashboard/acp-boot.ts +3 -0
  384. package/src/dashboard/index.ts +224 -615
  385. package/src/dashboard/input/chat-main-entry-runtime.ts +1 -1
  386. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  387. package/src/dashboard/input/chat-main-session.ts +8 -1
  388. package/src/dashboard/input/chat-main-turn.ts +12 -3
  389. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  390. package/src/dashboard/input/external-input-host.ts +26 -0
  391. package/src/dashboard/input/internal-turn.ts +261 -0
  392. package/src/dashboard/input/seat-autowake.ts +318 -0
  393. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  394. package/src/dashboard/loop-scheduler.ts +72 -0
  395. package/src/dashboard/seat-boot-preamble.ts +18 -0
  396. package/src/dashboard/skill-runtime.ts +2 -0
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  398. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  399. package/src/dashboard/slash-runtime/index.ts +13 -0
  400. package/src/dashboard/turn-busy-teardown.ts +50 -0
  401. package/src/decisions/decision-ledger.ts +45 -4
  402. package/src/discord-self-message.ts +4 -4
  403. package/src/domains/release-tool.ts +18 -1
  404. package/src/field-note/transcribe.ts +17 -0
  405. package/src/github/remote-call.ts +81 -0
  406. package/src/goals/registry.ts +46 -6
  407. package/src/goals/types.ts +7 -1
  408. package/src/graph-runner/runner.ts +1 -0
  409. package/src/grok/credential.ts +26 -0
  410. package/src/harness/harness-clean.ts +2 -1
  411. package/src/harness/harness-cli-command.ts +52 -5
  412. package/src/harness/harness-gc.ts +2 -1
  413. package/src/harness/harness-incidents.ts +57 -20
  414. package/src/harness/harness-pod-dispatch.ts +87 -10
  415. package/src/harness/harness-queue.ts +53 -4
  416. package/src/harness/harness-stop.ts +4 -3
  417. package/src/harness/harness-substrate-default.ts +78 -7
  418. package/src/harness/harness-worktree-auto.ts +2 -1
  419. package/src/harness/harness-worktrees.ts +3 -2
  420. package/src/hooks/dispatch.ts +2 -1
  421. package/src/index.ts +152 -25
  422. package/src/input/external-input-queue.ts +33 -1
  423. package/src/intake-plane/slash.ts +14 -3
  424. package/src/keybindings.ts +4 -1
  425. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  426. package/src/llm.ts +138 -19
  427. package/src/loops/consensus.ts +348 -0
  428. package/src/loops/msg-wake.ts +206 -4
  429. package/src/loops/observe.ts +19 -3
  430. package/src/loops/orchestrator/tick.ts +64 -10
  431. package/src/loops/orchestrator/traffic.ts +64 -1
  432. package/src/loops/registry.ts +30 -0
  433. package/src/market/signed-index.ts +14 -0
  434. package/src/mcp/mcp-oauth.ts +54 -5
  435. package/src/models/prompts.ts +28 -0
  436. package/src/msg/msg-sse-client.ts +223 -0
  437. package/src/msg/msg-store.ts +86 -2
  438. package/src/mss/logging/log-store.ts +225 -1
  439. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  440. package/src/nexus/api/http-server.ts +54 -15
  441. package/src/nexus/api/loop-resources.ts +19 -3
  442. package/src/nexus/api/ops-api.ts +11 -0
  443. package/src/nexus/daemon-thin-inventory.md +37 -0
  444. package/src/nexus/index.ts +70 -0
  445. package/src/nexus/state/state.ts +1 -0
  446. package/src/oauth/store.ts +32 -7
  447. package/src/onboarding/first-run.ts +28 -3
  448. package/src/ops/overview-cache.ts +16 -4
  449. package/src/ops/resources.ts +82 -0
  450. package/src/plugins/maker/connector-maker.ts +41 -0
  451. package/src/plugins/maker/skill-maker.ts +42 -0
  452. package/src/pr-tool/census.ts +288 -0
  453. package/src/prompt-library/chat-conciseness.ts +13 -0
  454. package/src/prompt-library/universal-preamble.ts +10 -5
  455. package/src/release-loop/gate-host-reservation.ts +97 -0
  456. package/src/release-loop/landing-freeze.ts +5 -0
  457. package/src/release-loop/light-rc.ts +5 -2
  458. package/src/release-loop/placement.ts +92 -1
  459. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  460. package/src/release-loop/rehearsal.ts +73 -17
  461. package/src/repl/index.ts +20 -2
  462. package/src/seat-loop/seat-knowhow.ts +282 -0
  463. package/src/seat-loop/seat-loop.ts +41 -2
  464. package/src/seat-loop/traffic-signal.ts +3 -0
  465. package/src/self-dev/ask-launch-flow.ts +24 -3
  466. package/src/self-dev/decompose-compose-graph.ts +28 -27
  467. package/src/self-dev/decompose-proposal.ts +53 -38
  468. package/src/self-dev/decompose.ts +17 -0
  469. package/src/self-dev/dev-pipeline.ts +31 -2
  470. package/src/self-dev/draft-residue.ts +24 -9
  471. package/src/self-dev/draft-sweep.ts +59 -4
  472. package/src/self-dev/external-call-zero.ts +77 -0
  473. package/src/self-dev/launch-preflight-text.ts +6 -0
  474. package/src/self-dev/launch-preflight.ts +25 -3
  475. package/src/self-dev/local-supervisor-judge.ts +185 -0
  476. package/src/self-dev/run-supervisor.ts +229 -19
  477. package/src/self-dev/run-types.ts +20 -0
  478. package/src/self-dev/shard-aggregate.ts +13 -2
  479. package/src/self-dev/shard-plan.ts +47 -0
  480. package/src/self-dev/shard-run.ts +112 -10
  481. package/src/self-dev/spawn-lane-files.ts +19 -0
  482. package/src/self-implement/app-api-budget.ts +51 -11
  483. package/src/self-implement/config-gate.ts +2 -1
  484. package/src/self-implement/expose-gate.ts +2 -1
  485. package/src/self-implement/gate-artifacts.ts +405 -0
  486. package/src/self-implement/gate-cli.ts +201 -16
  487. package/src/self-implement/gate-remote.ts +110 -25
  488. package/src/self-implement/gate-scenario.ts +85 -0
  489. package/src/self-implement/goal-author.ts +160 -8
  490. package/src/self-implement/graph-authority.ts +38 -6
  491. package/src/self-implement/graph-overlay-condition.ts +92 -1
  492. package/src/self-implement/heal-triage.ts +79 -0
  493. package/src/self-implement/host-regate.ts +61 -3
  494. package/src/self-implement/orchestrator.ts +14 -123
  495. package/src/self-implement/pr-title.ts +123 -0
  496. package/src/self-implement/run-checkpoint.ts +235 -0
  497. package/src/self-implement/run-ledger.ts +155 -10
  498. package/src/self-implement/run-stop.ts +4 -3
  499. package/src/self-implement/run-ttl.ts +28 -4
  500. package/src/self-implement/seams.ts +2 -0
  501. package/src/self-implement/shadow-stage.ts +7 -6
  502. package/src/self-implement/stop-autoheal.ts +2 -1
  503. package/src/self-implement/train-gate-remote.ts +37 -8
  504. package/src/self-implement/train-reach-grouping.ts +157 -0
  505. package/src/self-implement/train-scenario-layers.ts +133 -0
  506. package/src/self-implement/uncommitted-work.ts +2 -0
  507. package/src/session/pending-input.ts +19 -0
  508. package/src/session/session-start.ts +224 -0
  509. package/src/session-runtime/parallel-dispatch.ts +22 -5
  510. package/src/skills/tools/dev-harness.ts +6 -4
  511. package/src/skills/tools/shell.ts +1 -1
  512. package/src/steward/resync-tick.ts +114 -23
  513. package/src/steward/ta-repair-event-collect.ts +158 -0
  514. package/src/task-agent/card-evidence.ts +25 -1
  515. package/src/task-agent/green-sweep.ts +8 -3
  516. package/src/task-agent/judge.ts +76 -0
  517. package/src/task-agent/land-queue.ts +79 -0
  518. package/src/task-agent/live-moves.ts +30 -9
  519. package/src/task-agent/postland-card.ts +5 -0
  520. package/src/task-agent/prelaunch-already-done.ts +98 -0
  521. package/src/task-agent/real-launch-guard.ts +37 -0
  522. package/src/task-agent/rejudge-on-head.ts +89 -12
  523. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  524. package/src/task-agent/repair-cycle.ts +45 -7
  525. package/src/task-agent/repair-worker.ts +7 -0
  526. package/src/task-agent/run-identity.ts +200 -0
  527. package/src/task-agent/shadow.ts +50 -3
  528. package/src/task-agent/task-hand.ts +158 -5
  529. package/src/task-agent/train-landing.ts +77 -0
  530. package/src/task-agent/work-order.ts +104 -0
  531. package/src/task-orchestrator/surfaces/pod-command-job.ts +88 -28
  532. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  533. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  534. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  535. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  536. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  537. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  538. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  539. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  540. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  541. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  542. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  543. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  544. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  545. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  546. package/src/task-orchestrator/surfaces/self-implement-pod.ts +132 -15
  547. package/src/telegram.ts +2 -4
  548. package/src/tui/input/pickers.ts +732 -0
  549. package/src/tui/slash/mission.ts +492 -0
  550. package/src/tui/slash/term.ts +877 -0
  551. package/src/tui-client/dashboard-session.ts +9 -0
  552. package/src/tui.ts +48 -0
  553. package/src/user-config/gemini-server-tools.ts +9 -0
  554. package/src/user-config.ts +53 -16
  555. package/src/util/spawn-sync-output.ts +7 -0
  556. package/src/ux-sim/fake-bin.ts +154 -0
  557. package/src/ux-sim/fake-clock.ts +36 -0
  558. package/src/ux-sim/headless-tui.ts +72 -0
  559. package/src/ux-sim/in-process-cli.ts +2 -1
  560. package/src/ux-sim/temp-git-remote.ts +82 -0
  561. package/src/version/packed-revision.json +1 -1
  562. package/src/video-pipeline/recipes/vlog.ts +25 -7
  563. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  567. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  569. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  572. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  573. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  576. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  578. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  584. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  588. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  599. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  605. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  608. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  609. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  610. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  613. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  615. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  616. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  617. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  619. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  625. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  632. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  635. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  640. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  642. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  703. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  709. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -1,4 +1,4 @@
1
- import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, isAbsolute, join, resolve } from 'node:path';
3
3
  import { refuseProductionLedgerWriteInTest } from '../harness/ledger-write-guard.js';
4
4
  import { tracedPathReferences, verbatimOriginalAsk } from './goal-author.js';
@@ -20,6 +20,7 @@ export interface RunLedgerEntry {
20
20
  event: string;
21
21
  data: Record<string, unknown>;
22
22
  goalId?: string;
23
+ devProject?: string;
23
24
  orchestrationId?: string;
24
25
  shardId?: string;
25
26
  siblingShardIds?: string[];
@@ -412,8 +413,12 @@ export function appendRunLedgerEntry(entry: RunLedgerEntry, dir = runLedgerDir()
412
413
  if (refuseProductionLedgerWriteInTest(dir, 'run-ledger')) return;
413
414
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
414
415
  const live = runLedgerPath(entry.runId, dir);
416
+ const devProject = process.env.ELANOUS_DEV_PROJECT;
417
+ const row = entry.devProject === undefined && typeof devProject === 'string' && devProject.startsWith('prj-')
418
+ ? { ...entry, devProject }
419
+ : entry;
415
420
  withRunLedgerLock(dir, entry.runId, () => {
416
- const line = `${JSON.stringify(entry)}\n`;
421
+ const line = `${JSON.stringify(row)}\n`;
417
422
  if (!restoreArchivedRunLedger(dir, entry.runId, line)) appendFileSync(live, line, 'utf8');
418
423
  });
419
424
  }
@@ -1315,6 +1320,10 @@ export interface UnfinishedRunLedgerQuery {
1315
1320
  terminalByTrailingRunStatus?: number;
1316
1321
  cacheHits?: number;
1317
1322
  cacheMisses?: number;
1323
+ /** Hits served by the persisted cross-process scan index (subset of cacheHits). */
1324
+ indexHits?: number;
1325
+ /** Whether that index was loaded from disk, started fresh, or was bypassed. */
1326
+ indexOrigin?: RunLedgerScanIndexOrigin;
1318
1327
  pathFilter?: string;
1319
1328
  matchingPathCount?: number;
1320
1329
  unknownPathCount?: number;
@@ -1674,6 +1683,96 @@ function unfinishedLedgerCacheKey(path: string, read?: RunLedgerReader): string
1674
1683
  return `${path}\u0000reader:${id}`;
1675
1684
  }
1676
1685
 
1686
+ // ⭐ 프로세스 간 유효 스캔 색인(칸 CONTEXT-NOW-RUN-SCAN-INDEX).
1687
+ // `/now`(contextNowInWorker)는 요청마다 «새 워커 프로세스»를 띄우므로 위 프로세스 캐시는 매번 빈 채로 시작한다
1688
+ // (실측 2026-10-14: scanned=7893, cacheHits=0, 조회 6.3~8.9초). 색인은 파싱된 파일별 facts 를
1689
+ // 원장 옆에 (size, mtimeMs) 스탬프로 저장하고, 스탬프가 같으면 재사용한다. 원장에 무엇이 «붙으면»
1690
+ // 스탬프가 바뀌므로 무효화는 자동이다. 읽기 실패는 전부 fail-soft: 색인이 없으면 그냥 새로 읽는다.
1691
+ const RUN_LEDGER_SCAN_INDEX_FILE = '.unfinished-scan-index.json';
1692
+ const RUN_LEDGER_SCAN_INDEX_VERSION = 1;
1693
+ const RUN_LEDGER_SCAN_INDEX_LIMIT = 32_768;
1694
+
1695
+ /** Where the persisted scan index lives: beside its ledgers, never mistaken for one (readdir filters canonical names). */
1696
+ export function runLedgerScanIndexPath(dir: string): string {
1697
+ return join(dir, RUN_LEDGER_SCAN_INDEX_FILE);
1698
+ }
1699
+
1700
+ export interface RunLedgerScanIndexRecord {
1701
+ size: number;
1702
+ mtimeMs: number;
1703
+ facts: UnfinishedLedgerFacts;
1704
+ }
1705
+
1706
+ /** Whether the persisted index was loaded, started fresh, or was bypassed (noCache or an injected reader). */
1707
+ export type RunLedgerScanIndexOrigin = 'loaded' | 'fresh' | 'bypassed';
1708
+
1709
+ const UNFINISHED_LIFECYCLE_WORDS = new Set<string>([
1710
+ 'live', 'orphaned', 'human-stopped', 'terminal-other-vocabulary', 'terminal-run-status-superseded', 'unjudgeable',
1711
+ ]);
1712
+
1713
+ function isScanIndexFacts(value: unknown): value is UnfinishedLedgerFacts {
1714
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
1715
+ const facts = value as Record<string, unknown>;
1716
+ return typeof facts.terminal === 'boolean'
1717
+ && typeof facts.terminalByTrailingRunStatus === 'boolean'
1718
+ && (facts.branch === null || typeof facts.branch === 'string')
1719
+ && (facts.lastActivityTimestamp === null || typeof facts.lastActivityTimestamp === 'string')
1720
+ && typeof facts.lastActivityStatus === 'string'
1721
+ && (facts.targetRoot === null || typeof facts.targetRoot === 'string')
1722
+ && (facts.goalFile === null || typeof facts.goalFile === 'string')
1723
+ && typeof facts.fixedLifecycle === 'string' && UNFINISHED_LIFECYCLE_WORDS.has(facts.fixedLifecycle);
1724
+ }
1725
+
1726
+ function isScanIndexRecord(value: unknown): value is RunLedgerScanIndexRecord {
1727
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
1728
+ const record = value as Record<string, unknown>;
1729
+ return Number.isFinite(record.size) && Number.isFinite(record.mtimeMs) && isScanIndexFacts(record.facts);
1730
+ }
1731
+
1732
+ const scanIndexCache = new Map<string, { stamp: string; entries: Map<string, RunLedgerScanIndexRecord> }>();
1733
+
1734
+ function scanIndexFileStamp(path: string): string {
1735
+ try { const stat = statSync(path); return `${stat.size}:${stat.mtimeMs}`; } catch { return 'missing'; }
1736
+ }
1737
+
1738
+ /** Load (memoized by index-file stamp) the persisted per-directory scan index; malformed or absent behaves as fresh. */
1739
+ export function loadRunLedgerScanIndex(dir: string): Map<string, RunLedgerScanIndexRecord> {
1740
+ const path = runLedgerScanIndexPath(dir);
1741
+ const stamp = scanIndexFileStamp(path);
1742
+ const cached = scanIndexCache.get(dir);
1743
+ if (cached && cached.stamp === stamp) return cached.entries;
1744
+ const entries = new Map<string, RunLedgerScanIndexRecord>();
1745
+ if (stamp !== 'missing') {
1746
+ try {
1747
+ const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));
1748
+ const raw = parsed && typeof parsed === 'object' && !Array.isArray(parsed)
1749
+ && (parsed as Record<string, unknown>).version === RUN_LEDGER_SCAN_INDEX_VERSION
1750
+ && typeof (parsed as Record<string, unknown>).entries === 'object'
1751
+ && (parsed as Record<string, unknown>).entries !== null && !Array.isArray((parsed as Record<string, unknown>).entries)
1752
+ ? (parsed as { entries: Record<string, unknown> }).entries : null;
1753
+ if (raw) for (const [runId, record] of Object.entries(raw)) {
1754
+ if (isScanIndexRecord(record)) entries.set(runId, record);
1755
+ }
1756
+ } catch { /* a malformed index behaves as absent */ }
1757
+ }
1758
+ scanIndexCache.set(dir, { stamp, entries });
1759
+ return entries;
1760
+ }
1761
+
1762
+ /** Persist the index beside its ledgers, best-effort: any failure just leaves the next scan reading fresh. */
1763
+ function persistRunLedgerScanIndex(dir: string, entries: ReadonlyMap<string, RunLedgerScanIndexRecord>): boolean {
1764
+ if (refuseProductionLedgerWriteInTest(dir, 'run-ledger-scan-index')) return false;
1765
+ const bounded = entries.size > RUN_LEDGER_SCAN_INDEX_LIMIT
1766
+ ? new Map([...entries].slice(entries.size - RUN_LEDGER_SCAN_INDEX_LIMIT))
1767
+ : entries;
1768
+ try {
1769
+ writeFileSync(runLedgerScanIndexPath(dir), JSON.stringify({ version: RUN_LEDGER_SCAN_INDEX_VERSION, entries: Object.fromEntries(bounded) }), 'utf8');
1770
+ return true;
1771
+ } catch {
1772
+ return false;
1773
+ }
1774
+ }
1775
+
1677
1776
  function unfinishedLedgerFacts(ledger: readonly RunLedgerEntry[]): UnfinishedLedgerFacts {
1678
1777
  const last = ledger.at(-1)?.timestamp;
1679
1778
  const lastActivityTimestamp = last !== undefined && Number.isFinite(Date.parse(last)) ? last : null;
@@ -1690,7 +1789,13 @@ function unfinishedLedgerFacts(ledger: readonly RunLedgerEntry[]): UnfinishedLed
1690
1789
  };
1691
1790
  }
1692
1791
 
1693
- function readUnfinishedLedgerFacts(runId: string, dir: string, read?: RunLedgerReader, noCache?: boolean): { facts: UnfinishedLedgerFacts; hit: boolean } {
1792
+ function readUnfinishedLedgerFacts(
1793
+ runId: string,
1794
+ dir: string,
1795
+ read?: RunLedgerReader,
1796
+ noCache?: boolean,
1797
+ index?: Map<string, RunLedgerScanIndexRecord>,
1798
+ ): { facts: UnfinishedLedgerFacts; hit: boolean; source: 'process' | 'index' | 'read' } {
1694
1799
  const path = runLedgerPath(runId, dir);
1695
1800
  const key = noCache ? null : unfinishedLedgerCacheKey(path, read);
1696
1801
  const stamp = noCache ? null : statSync(path);
@@ -1698,9 +1803,18 @@ function readUnfinishedLedgerFacts(runId: string, dir: string, read?: RunLedgerR
1698
1803
  if (cached && stamp && key !== null && cached.size === stamp.size && cached.mtimeMs === stamp.mtimeMs) {
1699
1804
  unfinishedLedgerCache.delete(key);
1700
1805
  unfinishedLedgerCache.set(key, cached);
1701
- return { facts: cached.facts, hit: true };
1806
+ return { facts: cached.facts, hit: true, source: 'process' };
1702
1807
  }
1703
1808
  if (key !== null) unfinishedLedgerCache.delete(key);
1809
+ // ⭐ 프로세스 캐시가 비었어도(새 워커) 디스크 색인의 스탬프가 같으면 재사용한다.
1810
+ // 주입된 reader 는 실제 파일 내용과 무관한 대역이라 색인에 넣지 «도», 색인에서 읽지 «도» 않는다.
1811
+ if (index !== undefined && stamp && read === undefined) {
1812
+ const record = index.get(runId);
1813
+ if (record && record.size === stamp.size && record.mtimeMs === stamp.mtimeMs) {
1814
+ if (key !== null) unfinishedLedgerCache.set(key, { size: stamp.size, mtimeMs: stamp.mtimeMs, facts: record.facts });
1815
+ return { facts: record.facts, hit: true, source: 'index' };
1816
+ }
1817
+ }
1704
1818
  try {
1705
1819
  const ledger = loadRunLedger(runId, dir, read);
1706
1820
  if (ledger === null && stamp !== null) throw new Error(`run ledger disappeared after stat: ${path}`);
@@ -1712,9 +1826,14 @@ function readUnfinishedLedgerFacts(runId: string, dir: string, read?: RunLedgerR
1712
1826
  if (unfinishedLedgerCache.size > UNFINISHED_LEDGER_CACHE_LIMIT) unfinishedLedgerCache.delete(unfinishedLedgerCache.keys().next().value!);
1713
1827
  }
1714
1828
  }
1715
- return { facts, hit: false };
1829
+ if (index !== undefined && stamp !== null && read === undefined) {
1830
+ index.set(runId, { size: stamp.size, mtimeMs: stamp.mtimeMs, facts });
1831
+ }
1832
+ return { facts, hit: false, source: 'read' };
1716
1833
  } catch (error) {
1717
1834
  if (key !== null) unfinishedLedgerCache.delete(key);
1835
+ // 원장이 사라졌거나 바뀐 사이에 읽었다 — 색인의 스탬프는 이미 무효이므로 치운다(무효화).
1836
+ index?.delete(runId);
1718
1837
  throw error;
1719
1838
  }
1720
1839
  }
@@ -1734,6 +1853,11 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1734
1853
  const goalsDir = resolve(options.goalsDir ?? resolveGoalDocumentsDir(process.cwd()).directory);
1735
1854
  const list = options.list ?? readdirSync;
1736
1855
  const liveWindowMs = options.liveWindowMs ?? DEFAULT_UNFINISHED_LIVE_WINDOW_MS;
1856
+ // ⭐ 색인은 noCache 나 주입된 reader 가 아니어야만 켠다 — 그 둘은 «정직한 재읽기» 계약을 지켜야 한다.
1857
+ const scanIndex = !options.noCache && options.read === undefined ? loadRunLedgerScanIndex(dir) : undefined;
1858
+ const indexOrigin: RunLedgerScanIndexOrigin = scanIndex === undefined ? 'bypassed' : scanIndex.size > 0 ? 'loaded' : 'fresh';
1859
+ let indexHits = 0;
1860
+ let indexChanged = false;
1737
1861
  let fileNames: string[];
1738
1862
  try {
1739
1863
  fileNames = list(dir);
@@ -1748,6 +1872,8 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1748
1872
  terminalByTrailingRunStatus: 0,
1749
1873
  cacheHits: 0,
1750
1874
  cacheMisses: 0,
1875
+ indexHits: 0,
1876
+ indexOrigin,
1751
1877
  ...(options.path === undefined ? {} : { pathFilter: options.path, matchingPathCount: 0, unknownPathCount: 0 }),
1752
1878
  scope: 'self-implement-run-ledger',
1753
1879
  note: UNFINISHED_RUN_LEDGER_NOTE,
@@ -1760,6 +1886,8 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1760
1886
  terminalByTrailingRunStatus: 0,
1761
1887
  cacheHits: 0,
1762
1888
  cacheMisses: 0,
1889
+ indexOrigin,
1890
+ indexHits: 0,
1763
1891
  ms: Date.now() - startedAt,
1764
1892
  });
1765
1893
  return missing;
@@ -1782,12 +1910,18 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1782
1910
  scanned += 1;
1783
1911
  let facts: UnfinishedLedgerFacts;
1784
1912
  try {
1785
- const observed = readUnfinishedLedgerFacts(runId, dir, options.read, options.noCache);
1913
+ const observed = readUnfinishedLedgerFacts(runId, dir, options.read, options.noCache, scanIndex);
1786
1914
  facts = observed.facts;
1787
- if (observed.hit) cacheHits += 1;
1788
- else cacheMisses += 1;
1915
+ if (observed.hit) {
1916
+ cacheHits += 1;
1917
+ if (observed.source === 'index') indexHits += 1;
1918
+ } else {
1919
+ cacheMisses += 1;
1920
+ if (scanIndex !== undefined) indexChanged = true;
1921
+ }
1789
1922
  } catch {
1790
1923
  cacheMisses += 1;
1924
+ if (scanIndex?.delete(runId)) indexChanged = true;
1791
1925
  unreadableLedgerCount += 1;
1792
1926
  entries.push({ runId, branch: null, status: 'ledger-unreadable', plannedPaths: [], plannedPathStatus: 'unknown', ...unknownDeclaredPaths(), pathMatchReasons: {}, goalDocumentPath: null, goalLookupBasis: 'caller-cwd', goalDocumentSearchDirectory: null, lastActivityTimestamp: null, lastActivityAgeMs: null, lastActivityStatus: 'ledger-unreadable', lifecycle: 'unjudgeable' });
1793
1927
  callerCwdCount += 1;
@@ -1840,6 +1974,7 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1840
1974
  }
1841
1975
  }
1842
1976
  entries.sort((left, right) => left.runId.localeCompare(right.runId));
1977
+ if (scanIndex !== undefined && indexChanged) persistRunLedgerScanIndex(dir, scanIndex);
1843
1978
  debug.log('self-implement.run-ledger', 'goal-lookup-basis', { ledgerTarget: ledgerTargetCount, callerCwd: callerCwdCount });
1844
1979
  debug.log('self-implement.run-ledger', 'unfinished-query', {
1845
1980
  scanned,
@@ -1848,10 +1983,12 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1848
1983
  terminalByTrailingRunStatus,
1849
1984
  cacheHits,
1850
1985
  cacheMisses,
1986
+ indexOrigin,
1987
+ indexHits,
1851
1988
  ms: Date.now() - startedAt,
1852
1989
  });
1853
1990
  if (options.path === undefined) {
1854
- return { entries, ledgerDirectory: dir, goalsDirectory: goalsDir, unreadableLedgerCount, ledgerDirectoryMissing: false, terminalByTrailingRunStatus, cacheHits, cacheMisses, scope: 'self-implement-run-ledger', note: UNFINISHED_RUN_LEDGER_NOTE };
1991
+ return { entries, ledgerDirectory: dir, goalsDirectory: goalsDir, unreadableLedgerCount, ledgerDirectoryMissing: false, terminalByTrailingRunStatus, cacheHits, cacheMisses, indexHits, indexOrigin, scope: 'self-implement-run-ledger', note: UNFINISHED_RUN_LEDGER_NOTE };
1855
1992
  }
1856
1993
  const pathFilter = options.path;
1857
1994
  const unknownPathStatus = (entry: UnfinishedRunLedgerEntry): boolean => entry.plannedPathStatus !== 'found-ledger-goal-file'
@@ -1871,6 +2008,8 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
1871
2008
  terminalByTrailingRunStatus,
1872
2009
  cacheHits,
1873
2010
  cacheMisses,
2011
+ indexHits,
2012
+ indexOrigin,
1874
2013
  pathFilter,
1875
2014
  matchingPathCount: matchingEntries.length,
1876
2015
  unknownPathCount: unknownEntries.length,
@@ -1908,6 +2047,8 @@ export interface FederatedUnfinishedRunLedgerQuery {
1908
2047
  reconciledTerminatedElsewhereCount: number;
1909
2048
  cacheHits?: number;
1910
2049
  cacheMisses?: number;
2050
+ /** Hits served by the persisted cross-process scan index (subset of cacheHits). */
2051
+ indexHits?: number;
1911
2052
  pathFilter?: string;
1912
2053
  matchingPathCount?: number;
1913
2054
  unknownPathCount?: number;
@@ -1947,6 +2088,7 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
1947
2088
  let unknownPathCount = 0;
1948
2089
  let cacheHits = 0;
1949
2090
  let cacheMisses = 0;
2091
+ let indexHits = 0;
1950
2092
  const recordDirectoryFailure = (kind: FederatedLedgerDirectoryFailureKind): void => {
1951
2093
  if (kind === 'missing') missingLedgerDirectoryCount += 1;
1952
2094
  else if (kind === 'unreadable') unreadableLedgerDirectoryAccessCount += 1;
@@ -1972,6 +2114,7 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
1972
2114
  unknownPathCount += result.unknownPathCount ?? 0;
1973
2115
  cacheHits += result.cacheHits ?? 0;
1974
2116
  cacheMisses += result.cacheMisses ?? 0;
2117
+ indexHits += result.indexHits ?? 0;
1975
2118
  entries.push(...result.entries.map((entry) => ({ ...entry, ledgerDirectory })));
1976
2119
  } catch (error) {
1977
2120
  recordDirectoryFailure(classifyFederatedLedgerDirectoryReadFailure(error));
@@ -1993,7 +2136,8 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
1993
2136
  for (const runId of unfinishedRunIds) {
1994
2137
  for (const ledgerDirectory of ledgerDirectories) {
1995
2138
  try {
1996
- if (readUnfinishedLedgerFacts(runId, ledgerDirectory, undefined, options.noCache).facts.terminal) { terminatedElsewhere.add(runId); break; }
2139
+ const reconciliationIndex = options.noCache ? undefined : loadRunLedgerScanIndex(ledgerDirectory);
2140
+ if (readUnfinishedLedgerFacts(runId, ledgerDirectory, undefined, options.noCache, reconciliationIndex).facts.terminal) { terminatedElsewhere.add(runId); break; }
1997
2141
  } catch { /* An absent or unreadable sibling cannot establish termination. */ }
1998
2142
  }
1999
2143
  }
@@ -2014,6 +2158,7 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2014
2158
  reconciledTerminatedElsewhereCount,
2015
2159
  cacheHits,
2016
2160
  cacheMisses,
2161
+ indexHits,
2017
2162
  ...(options.path === undefined ? {} : { pathFilter: options.path, matchingPathCount, unknownPathCount }),
2018
2163
  scope: 'self-implement-run-ledger-federated',
2019
2164
  note: FEDERATED_UNFINISHED_RUN_LEDGER_NOTE,
@@ -15,7 +15,7 @@ import { appendRunLedgerEntry, type RunLedgerEntry, type RunLedgerWriter, type R
15
15
  /** 닫힌 목록 — 못 고르면 `unclassified`. */
16
16
  export const RUN_STOP_CLASSES = [
17
17
  'env-unrelated', 'main-sync', 'pod-died', 'review-repeat',
18
- 'review-out-of-scope', 'evidence-uncovered', 'fabric', 'launch-failed', 'unclassified',
18
+ 'review-out-of-scope', 'evidence-uncovered', 'fabric', 'launch-failed', 'gate-failed', 'unclassified',
19
19
  ] as const;
20
20
  export type RunStopClass = typeof RUN_STOP_CLASSES[number];
21
21
 
@@ -68,8 +68,9 @@ export function classifyMergeHoldStop(mergeReason: string | undefined): RunStopC
68
68
  return 'unclassified';
69
69
  }
70
70
 
71
- /** Pod exit 분류 사유 → 닫힌 목록. */
72
- export function classifyPodExitStop(reason: string | undefined): RunStopClass {
71
+ /** Pod exit 분류 사유 → 닫힌 목록. `stage` 가 호스트 재게이트 실패(`host-regate-failed`)면 `gate-failed`, 인자가 없으면 지금과 똑같이. */
72
+ export function classifyPodExitStop(reason: string | undefined, stage?: string): RunStopClass {
73
+ if (stage === 'host-regate-failed') return 'gate-failed';
73
74
  switch (reason) {
74
75
  case 'pod-failure': case 'pod-error': case 'OOMKilled': case 'ENOBUFS': case 'signal': return 'pod-died';
75
76
  case 'no-launch': return 'launch-failed';
@@ -5,7 +5,9 @@
5
5
  * Past `tools.selfImplement.runTtlHours` (default 24) since its last commit, the sweep makes one pre-emptive move:
6
6
  * · live owning run → one resync memo in its control inbox (same path as SIBLING-RESYNC #24893/#24899),
7
7
  * at most once per (PR, head sha) — a rebase moves the head and re-arms it
8
- * · no live run → the registered `elanous:needs-rebase` label, once (QUIET-PR-COMMENTS: never a comment)
8
+ * · no live run → the registered `elanous:needs-rebase` label, once (QUIET-PR-COMMENTS: never a comment);
9
+ * when `requestRegate` is supplied, at most one of those stale PRs is also selected
10
+ * for a re-gate request (shadow: would-regate observation only; live: one call)
9
11
  *
10
12
  * Mode `tools.selfImplement.runTtl.mode`: `shadow` (default) only logs what it would do; `live` writes.
11
13
  * Cost bound: a PR opened inside the TTL is still inside its own time-to-landing and is never fetched
@@ -63,6 +65,8 @@ export interface RunTtlResult {
63
65
  readonly memo: readonly number[];
64
66
  /** Label added (live) or would be added (shadow). */
65
67
  readonly label: readonly number[];
68
+ /** Re-gate requested (live) or would be requested (shadow). Empty when the adapter is omitted. */
69
+ readonly regate: readonly number[];
66
70
  readonly alreadyMarked: readonly number[];
67
71
  readonly alreadyMemoed: readonly number[];
68
72
  /** Owning run lookup failed — left alone (a failed lookup is not a dead run). */
@@ -109,6 +113,8 @@ export async function runRunTtlSweep(input: {
109
113
  concurrency?: number;
110
114
  now?: () => number;
111
115
  log?: (category: string, event: string, data: Record<string, unknown>) => void;
116
+ /** Optional: among stale PRs with no live run, request a re-gate for at most one per sweep. */
117
+ requestRegate?: (pr: RunTtlCandidate) => Promise<void> | void;
112
118
  }): Promise<RunTtlResult> {
113
119
  const { adapters } = input;
114
120
  const now = input.now ?? Date.now;
@@ -132,6 +138,7 @@ export async function runRunTtlSweep(input: {
132
138
  const stale: number[] = [];
133
139
  const memo: number[] = [];
134
140
  const label: number[] = [];
141
+ const regate: number[] = [];
135
142
  const alreadyMarked: number[] = [];
136
143
  const alreadyMemoed: number[] = [];
137
144
  const unresolved: number[] = [];
@@ -139,17 +146,17 @@ export async function runRunTtlSweep(input: {
139
146
  const skippedFetchCap: number[] = [];
140
147
  const failed: number[] = [];
141
148
  const result = (reason?: string): RunTtlResult => ({
142
- mode, ttlHours, considered, freshByCreation, fetched, fresh, unknown, stale, memo, label, alreadyMarked,
149
+ mode, ttlHours, considered, freshByCreation, fetched, fresh, unknown, stale, memo, label, regate, alreadyMarked,
143
150
  alreadyMemoed, unresolved, skippedOverCap, skippedFetchCap, failed, durationMs: Math.max(0, now() - startedAt),
144
151
  ...(reason ? { reason } : {}),
145
152
  });
146
153
  const summary = (out: RunTtlResult): RunTtlResult => {
147
154
  emit('summary', {
148
155
  ttlHours, cap, maxFetch, concurrency, considered, freshByCreation, fetched, fresh,
149
- unknown: unknown.length, stale: stale.length, memo: memo.length, label: label.length,
156
+ unknown: unknown.length, stale: stale.length, memo: memo.length, label: label.length, regate: regate.length,
150
157
  alreadyMarked: alreadyMarked.length, alreadyMemoed: alreadyMemoed.length, unresolved: unresolved.length,
151
158
  skippedOverCap: skippedOverCap.length, skippedFetchCap: skippedFetchCap.length, failed: failed.length,
152
- memoPrs: memo, labelPrs: label, durationMs: out.durationMs, ...(out.reason ? { reason: out.reason } : {}),
159
+ memoPrs: memo, labelPrs: label, regatePrs: regate, durationMs: out.durationMs, ...(out.reason ? { reason: out.reason } : {}),
153
160
  });
154
161
  return out;
155
162
  };
@@ -200,6 +207,7 @@ export async function runRunTtlSweep(input: {
200
207
  }
201
208
  stalePrs.sort((a, b) => b.ageMs - a.ageMs || a.pr.number - b.pr.number);
202
209
  let actions = 0;
210
+ let selectedRegate = false;
203
211
  for (const { pr, target, ageMs } of stalePrs) {
204
212
  const ageHours = ageMs / 3_600_000;
205
213
  const key = `${pr.number}:${pr.headSha}`;
@@ -240,9 +248,15 @@ export async function runRunTtlSweep(input: {
240
248
  }
241
249
  }
242
250
  const reason = target.alive ? 'memo-failed' : target.reason;
251
+ const canRegate = Boolean(input.requestRegate) && !target.alive && !selectedRegate;
243
252
  if (mode === 'shadow') {
244
253
  label.push(pr.number);
245
254
  emit('would-label', { pr: pr.number, label: RUN_TTL_MARKER_LABEL, reason, ageHours: Math.floor(ageHours) });
255
+ if (canRegate) {
256
+ selectedRegate = true;
257
+ regate.push(pr.number);
258
+ emit('would-regate', { pr: pr.number, reason, ageHours: Math.floor(ageHours) });
259
+ }
246
260
  continue;
247
261
  }
248
262
  try {
@@ -253,6 +267,16 @@ export async function runRunTtlSweep(input: {
253
267
  failed.push(pr.number);
254
268
  emit('label-failed', { pr: pr.number, error: String(error) });
255
269
  }
270
+ if (canRegate) {
271
+ selectedRegate = true;
272
+ try {
273
+ await input.requestRegate!(pr);
274
+ regate.push(pr.number);
275
+ emit('regate-requested', { pr: pr.number, reason, ageHours: Math.floor(ageHours) });
276
+ } catch (error) {
277
+ emit('regate-failed', { pr: pr.number, error: String(error) });
278
+ }
279
+ }
256
280
  }
257
281
  return summary(result());
258
282
  }
@@ -2493,6 +2493,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2493
2493
 
2494
2494
  openPr: async ({ title, body, head, base, draft, labels, cwd }) => {
2495
2495
  const resolvedBase = assertBaseBranchOnOrigin(cwd, base);
2496
+ const harnessSeat = process.env.ELANOUS_HARNESS_SEAT;
2496
2497
  const outcome = (o.prManager ?? makePrManager()).upsertPr({
2497
2498
  branch: head,
2498
2499
  worktreePath: cwd,
@@ -2501,6 +2502,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2501
2502
  commitMessage: title,
2502
2503
  ...(resolvedBase ? { base: resolvedBase } : {}),
2503
2504
  ...(draft !== undefined ? { draft } : {}),
2505
+ ...(harnessSeat === 'OP' || harnessSeat === 'TC' || harnessSeat === 'MK' || harnessSeat === 'UX' ? { seat: harnessSeat } : {}),
2504
2506
  // BENCH-ISOLATED-ARMS ② — base 가 `bench/<id>/base` 면 라벨 `elanous:bench` 를 더한다.
2505
2507
  ...(() => {
2506
2508
  const all = benchIdFromBase(resolvedBase) && !labels?.includes(BENCH_LABEL) ? [...(labels ?? []), BENCH_LABEL] : labels;
@@ -10,6 +10,7 @@
10
10
  // 배선은 P4(현재 비-git 은 front door 에서 refuse 유지 → 이 적용 경로는 프로덕션 미도달).
11
11
 
12
12
  import { spawnSync } from 'node:child_process';
13
+ import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
13
14
  import { cpSync, existsSync, statSync } from 'node:fs';
14
15
  import { tmpdir } from 'node:os';
15
16
  import { basename, dirname, join } from 'node:path';
@@ -49,7 +50,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
49
50
  const slug = basename(target).replace(/[^a-zA-Z0-9._-]/g, '-');
50
51
  const shadowPath = join(tmpdir(), `elanous-shadow-${slug}-${process.pid}`);
51
52
  // 이전 세대 잔여 정리(고아 방지·createWorktree resetExisting 정합).
52
- try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
53
+ try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
53
54
 
54
55
  // ② 대상 → 그림자 복사(내용 전체·심볼릭 보존 X: cpSync 기본).
55
56
  cpSync(target, shadowPath, { recursive: true });
@@ -69,7 +70,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
69
70
  path: shadowPath,
70
71
  branch,
71
72
  base,
72
- cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
73
+ cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
73
74
  };
74
75
  }
75
76
 
@@ -94,9 +95,9 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
94
95
  const fileName = basename(target);
95
96
  const slug = fileName.replace(/[^a-zA-Z0-9._-]/g, '-');
96
97
  const shadowPath = join(tmpdir(), `elanous-shadow-file-${slug}-${process.pid}`);
97
- try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
98
+ try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
98
99
 
99
- spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS });
100
+ spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
100
101
  cpSync(target, join(shadowPath, fileName));
101
102
 
102
103
  git(shadowPath, ['init', '-b', 'shadow-base']);
@@ -113,7 +114,7 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
113
114
  fileName,
114
115
  branch,
115
116
  base,
116
- cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
117
+ cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
117
118
  };
118
119
  }
119
120
 
@@ -166,7 +167,7 @@ export function applyShadowToTarget(opts: { shadowPath: string; target: string;
166
167
  debug.log('harness.target', 'apply.backup', { target: target.slice(-48), backup: backup.slice(-48) });
167
168
 
168
169
  // ② rsync 미러링(--delete·그림자 git 메타 제외). rsync 부재 = fail-closed(백업만 남기고 미적용).
169
- const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000 });
170
+ const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
170
171
  if (probe.status !== 0) {
171
172
  debug.log('harness.target', 'apply.no-rsync', { target: target.slice(-48) });
172
173
  return { backup, applied: false, log: 'rsync 미설치 → 적용 안 함(백업만 생성·fail-closed). 수동 적용 필요.' };
@@ -13,7 +13,7 @@
13
13
  * main-sync → rebase-regate 리베이스(MERGE-INTENT-RESOLVE 의도 해석) 뒤 재게이트
14
14
  * pod-died → resume-from-salvage `salvage/run-<6hex>/<leaf>` 가지에서 resume(DRAFT-NOT-ARCHIVE)
15
15
  * evidence-uncovered → derive-evidence-rejudge 런 출력·시험·배선에서 증거를 끌어내 1회 재판정
16
- * review-repeat · review-out-of-scope · fabric · launch-failed · unclassified → needs-owner(새 라운드 없음)
16
+ * review-repeat · review-out-of-scope · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
17
17
  *
18
18
  * 사다리의 «출처»: `graphs/overlays/stop-heal-ladder.yaml` 이 갈래마다 처방 노드(id = 처방 이름)를 선언한다.
19
19
  * 그 갈래에 얹힌 오버레이가 더한 노드 id 가 처방이다(source='graph'). 선언이 없거나 못 읽으면
@@ -52,6 +52,7 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
52
52
  'review-out-of-scope': 'needs-owner',
53
53
  fabric: 'needs-owner',
54
54
  'launch-failed': 'needs-owner',
55
+ 'gate-failed': 'needs-owner',
55
56
  unclassified: 'needs-owner',
56
57
  };
57
58
 
@@ -3,9 +3,10 @@
3
3
  * Unlike `dispatchHeavyCheck` it never falls back to a local run: a busy host or an infra failure is «unmeasured».
4
4
  * The only local commands are git (cat-file · rev-parse · push · diff). */
5
5
  import { debug } from '../debug/log.js';
6
+ import { parseGateScenario, readGateScenarioFile } from './gate-scenario.js';
6
7
  import { getDefaultLogStore } from '../mss/logging/log-store.js';
7
8
  import {
8
- realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
9
+ gateRemoteHostCap, realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
9
10
  type GateRemoteRunner, type GateRemoteSettings, type RemoteRunOutcome,
10
11
  } from './gate-remote.js';
11
12
 
@@ -21,6 +22,9 @@ export interface TrainGateInput {
21
22
  changedFiles: readonly string[];
22
23
  /** Paths deleted by the integration commit — kept in `changedFiles` for tsc/PWA reach, never run as tests. */
23
24
  deletedFiles?: readonly string[];
25
+ /** Optional v0 JSON scenario. Selected tests are additive; invalid input is unmeasured. */
26
+ scenario?: unknown;
27
+ scenarioFile?: string;
24
28
  settings?: GateRemoteSettings;
25
29
  }
26
30
 
@@ -42,9 +46,10 @@ const quote = (value: string) => `'${value.replaceAll("'", `'\\''`)}'`;
42
46
  const TEST_FILE = /\.test\.[cm]?[jt]sx?$/;
43
47
 
44
48
  /** The host-side shell body: each step runs only if the one before it passed. Exported for tests. */
45
- export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set()): string {
49
+ export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set(), scenarioTests: readonly string[] = []): string {
46
50
  // A deleted test file is a changed path (tsc/PWA reach) but not something to run.
47
- const tests = changedFiles.filter((file) => TEST_FILE.test(file) && !deleted.has(file));
51
+ const changedTests = changedFiles.filter((file) => TEST_FILE.test(file) && !deleted.has(file));
52
+ const tests = scenarioTests.length ? [...new Set([...changedTests, ...scenarioTests])] : changedTests;
48
53
  const steps = [
49
54
  `TSC_BASE_REF=${quote(baseSha)} bun scripts/ci-typecheck-changed.ts --local`,
50
55
  ...(tests.length ? [`bun run test:deterministic ${tests.map(quote).join(' ')}`] : []),
@@ -72,6 +77,30 @@ export const TRAIN_GATE_HOST = 'node-b';
72
77
  export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): Promise<TrainGateResult> {
73
78
  const settings = input.settings ?? await loadSettings();
74
79
  const host = settings.host;
80
+ const hostCap = gateRemoteHostCap(settings, host);
81
+ let scenarioTests: string[] = [];
82
+ if (input.scenario !== undefined || input.scenarioFile !== undefined) {
83
+ try {
84
+ if (input.scenario !== undefined && input.scenarioFile !== undefined) throw new Error('choose scenario or scenarioFile');
85
+ const scenario = parseGateScenario(input.scenarioFile === undefined ? input.scenario : readGateScenarioFile(input.scenarioFile), { baseSha: input.baseSha, headSha: input.commit, changedFiles: input.changedFiles });
86
+ if (scenario.selectedTests.some(({ path }) => input.deletedFiles?.includes(path))) throw new Error('selected test deleted');
87
+ scenarioTests = scenario.selectedTests.map(({ path }) => path);
88
+ // The remote checks out this exact commit. Verify every path against its tree locally before spending a host slot.
89
+ for (const path of scenarioTests) {
90
+ const file = runner.local('git', ['cat-file', '-e', `${input.commit}:${path}`], input.repo);
91
+ if (file.rc !== 0 || file.error) throw new Error(`selected test missing at head: ${path}`);
92
+ const tree = runner.local('git', ['ls-tree', '-z', input.commit, '--', path], input.repo);
93
+ if (tree.rc !== 0 || tree.error || !/^100(?:644|755) blob [0-9a-f]{40}\t/.test(tree.stdout)
94
+ || !tree.stdout.endsWith(`\t${path}\0`)) throw new Error(`selected test is not a regular file at head: ${path}`);
95
+ }
96
+ } catch (error) {
97
+ const reason = error instanceof Error ? error.message : String(error);
98
+ const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason, changedFiles: input.changedFiles.length };
99
+ debug.log('merge-queue', 'train-gate', entry);
100
+ try { (deps.observe ?? defaultObserve)(entry); } catch { /* observation only */ }
101
+ return { outcome: 'unmeasured', host, reason };
102
+ }
103
+ }
75
104
  if (host !== TRAIN_GATE_HOST) {
76
105
  const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason: `host-not-gate-host (${host} ≠ ${TRAIN_GATE_HOST})`, changedFiles: input.changedFiles.length };
77
106
  debug.log('merge-queue', 'train-gate', entry);
@@ -81,13 +110,13 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
81
110
  const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
82
111
  const now = deps.now ?? Date.now;
83
112
  const deadline = now() + settings.slotWaitSeconds * 1000;
84
- const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []));
113
+ const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []), scenarioTests);
85
114
  let outcome: RemoteRunOutcome;
86
115
  for (;;) {
87
116
  try {
88
117
  outcome = runOnRemote({
89
118
  repo: input.repo, host, mirror: settings.mirror, commit: input.commit, refs: [input.baseSha],
90
- argv: ['sh', '-c', script], installPwa: true, hostCap: settings.hostCap,
119
+ argv: ['sh', '-c', script], installPwa: true, hostCap,
91
120
  }, runner);
92
121
  } catch (error) {
93
122
  outcome = { kind: 'infra', reason: `exception: ${error instanceof Error ? error.message : String(error)}` };
@@ -100,7 +129,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
100
129
  }
101
130
  const result: TrainGateResult = outcome.kind === 'ran'
102
131
  ? { outcome: outcome.rc === 0 ? 'pass' : 'fail', host, ms: outcome.ms, rc: outcome.rc }
103
- : { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (cap ${settings.hostCap} held for ${settings.slotWaitSeconds}s)` : outcome.reason };
132
+ : { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (occupied ${outcome.occupied ?? 'unknown'}/${hostCap}, held for ${settings.slotWaitSeconds}s)` : outcome.reason };
104
133
  const entry: TrainGateObservation = {
105
134
  host, commit: input.commit, baseSha: input.baseSha, outcome: result.outcome,
106
135
  rc: result.rc, ms: result.ms, reason: result.reason, changedFiles: input.changedFiles.length,
@@ -116,7 +145,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
116
145
  * integration commit's diff against `baseSha` (local git only); a diff failure is «unmeasured», never a local run. */
117
146
  export type TrainGate = (commitSha: string, prNumbers: readonly number[]) => Promise<TrainGateOutcome>;
118
147
 
119
- export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
148
+ export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings; scenario?: unknown; scenarioFile?: string }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
120
149
  const unmeasured = (commitSha: string, reason: string): 'unmeasured' => {
121
150
  const entry: TrainGateObservation = { host: opts.settings?.host ?? TRAIN_GATE_HOST, commit: commitSha, baseSha: opts.baseSha, outcome: 'unmeasured', reason, changedFiles: 0 };
122
151
  debug.log('merge-queue', 'train-gate', entry);
@@ -128,7 +157,7 @@ export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?
128
157
  const diff = runner.local('git', ['diff', '--name-status', '-z', opts.baseSha, commitSha], opts.repo);
129
158
  if (diff.rc !== 0 || diff.error) return unmeasured(commitSha, 'changed-files-unavailable');
130
159
  const { changedFiles, deletedFiles } = parseNameStatus(diff.stdout);
131
- return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings }, runner, deps)).outcome;
160
+ return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings, scenario: opts.scenario, scenarioFile: opts.scenarioFile }, runner, deps)).outcome;
132
161
  } catch (error) {
133
162
  // Any preparation failure (local git spawn, parse, settings) is «unmeasured» — never a rejected promise, never a local run.
134
163
  return unmeasured(commitSha, `prepare-failed: ${error instanceof Error ? error.message : String(error)}`.slice(0, 200));