elanous 0.2.29 → 0.2.32

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 (775) 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 → IVKr3AlRUVLKsw2fh7eXF}/_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-98b64172bc1efe77.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/69-0a2c8209c6d4a158.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  94. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  95. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  110. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-c219f2ed171131be.js} +1 -1
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/page-04d00ae9b0890349.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +7 -3
  279. package/graphs/context/nightly-condense.yaml +1 -0
  280. package/graphs/implement-loop.yaml +5 -0
  281. package/graphs/intake/intake-daily.yaml +8 -1
  282. package/graphs/intake/recipes.yaml +5 -0
  283. package/graphs/lecture/lecture-note.yaml +2 -2
  284. package/graphs/ops/harness-gc.yaml +1 -0
  285. package/graphs/release/recipes.yaml +3 -0
  286. package/graphs/release/release-loop.yaml +9 -5
  287. package/graphs/units/recipes.yaml +3 -0
  288. package/graphs/units/release-gate-recheck.yaml +15 -0
  289. package/package.json +2 -1
  290. package/scripts/check-native-tool-wiring.ts +3 -2
  291. package/scripts/ci-android-unit-tests.ts +16 -0
  292. package/scripts/ci-typecheck-changed.ts +63 -10
  293. package/scripts/coord-channel-watch.sh +22 -16
  294. package/scripts/coord-role-pack.ts +81 -2
  295. package/scripts/cron-run.ts +96 -3
  296. package/scripts/detect-test-interference.ts +38 -5
  297. package/scripts/gate-pr-cache.ts +65 -0
  298. package/scripts/gh-surface/capture.ts +126 -0
  299. package/scripts/gh-surface/gh +40 -0
  300. package/scripts/import-graph-scc.ts +38 -0
  301. package/scripts/install.ps1 +19 -0
  302. package/scripts/intake-social.ts +181 -0
  303. package/scripts/lecture-note/node.ts +71 -4
  304. package/scripts/lib/android-toolchain.ts +32 -0
  305. package/scripts/lib/deterministic-env.ts +62 -0
  306. package/scripts/lib/gate-test-env.ts +19 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/measure-si-task-cpu.ts +143 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +255 -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-closure.ts +12 -8
  317. package/scripts/release-loop/gate-diff.ts +1 -1
  318. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  319. package/scripts/release-loop/gate-node.ts +523 -75
  320. package/scripts/release-loop/gate-partial.ts +106 -9
  321. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  322. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  323. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  324. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  325. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  326. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  327. package/scripts/release-loop/import-graph-scc.ts +215 -0
  328. package/scripts/release-loop/node-verdict.ts +2 -0
  329. package/scripts/release-loop/prepare-node.ts +102 -4
  330. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  331. package/scripts/release-loop/resume-release.ts +33 -4
  332. package/scripts/release-loop/resume.ts +13 -5
  333. package/scripts/release-loop/spawn-lane.ts +2 -19
  334. package/scripts/release-loop/tui-sim-node.ts +3 -2
  335. package/scripts/release-loop/unattended-release.ts +16 -0
  336. package/scripts/test-deterministic.ts +5 -61
  337. package/scripts/train-reach-grouping.ts +48 -0
  338. package/scripts/tsc-incremental-cache.ts +86 -0
  339. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  340. package/scripts/tsc-main-safety-net.ts +2 -2
  341. package/src/acp/client.ts +4 -1
  342. package/src/acp/core-turn-bridge.ts +65 -8
  343. package/src/acp/elanous-extensions.ts +3 -0
  344. package/src/acp/server.ts +3 -0
  345. package/src/acp/tool-trace.ts +186 -11
  346. package/src/ad-pipeline/run.ts +4 -2
  347. package/src/agent/runner.ts +169 -3
  348. package/src/agent/self-ambient-cache.ts +156 -0
  349. package/src/agent/self-ambient.ts +8 -1
  350. package/src/agent/subagent-callable.ts +3 -2
  351. package/src/agent/task-notification.ts +5 -0
  352. package/src/agent-mission/review-loop.ts +6 -3
  353. package/src/agent-substrate/acp-implementer.ts +14 -2
  354. package/src/agent-substrate/pr-reviewer.ts +14 -0
  355. package/src/agent-substrate/self-review-cli.ts +30 -4
  356. package/src/ask-user-question/tool.ts +22 -0
  357. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  358. package/src/autopilot/pr-manager.ts +80 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/capture/frame-state-detect.ts +39 -0
  361. package/src/capture/tui-self-report.ts +149 -6
  362. package/src/chat/chat-cli.ts +10 -2
  363. package/src/chat/index.ts +138 -26
  364. package/src/chat/input-control-key.ts +5 -3
  365. package/src/chat/pickers/modal-runtime.ts +6 -0
  366. package/src/chat/pickers/modals.ts +8 -2
  367. package/src/chat/tool-interrupt-behavior.ts +38 -0
  368. package/src/chat/tool-render/dispatch.ts +5 -1
  369. package/src/chat/turn-typeahead.ts +75 -20
  370. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  371. package/src/cli/agent-cli.ts +41 -13
  372. package/src/cli/ask-bare.ts +1 -0
  373. package/src/cli/config-audit.ts +123 -0
  374. package/src/cli/decisions-cli.ts +80 -6
  375. package/src/cli/import-cli.ts +12 -0
  376. package/src/cli/log-event-names.ts +17 -0
  377. package/src/cli/mcp-login.ts +21 -5
  378. package/src/cli/msg-cli.ts +89 -0
  379. package/src/cli/pod-cli.ts +14 -3
  380. package/src/cli/pr-cli.ts +273 -81
  381. package/src/cli/pr-land-base-read.ts +34 -0
  382. package/src/cli/pr-land-heavy-remote.ts +82 -26
  383. package/src/cli/pr-land-overlap-evidence.ts +109 -11
  384. package/src/cli/pr-land-pod-shadow-job.ts +106 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-refusal.ts +20 -5
  387. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  388. package/src/cli/pty-takeover-cli.ts +88 -14
  389. package/src/cli/release-cli.ts +80 -14
  390. package/src/cli/seat-cli.ts +138 -3
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/sim-cli.ts +18 -0
  393. package/src/cli/tasks-cli.ts +97 -19
  394. package/src/context-bus/context-first.ts +13 -0
  395. package/src/context-bus/context-now.ts +13 -2
  396. package/src/context-bus/ops-events.ts +79 -0
  397. package/src/control-plane/lease-holder.ts +12 -8
  398. package/src/control-plane/ledger.ts +163 -4
  399. package/src/control-plane/server.ts +91 -11
  400. package/src/core-turn/run-core-turn.ts +2 -0
  401. package/src/core-turn/run-goal-loop.ts +243 -3
  402. package/src/core-turn/seat-turn-cap.ts +79 -0
  403. package/src/core-turn/short-question.ts +38 -6
  404. package/src/core-turn/types.ts +6 -0
  405. package/src/dashboard/acp-active-model.ts +42 -1
  406. package/src/dashboard/acp-boot.ts +3 -0
  407. package/src/dashboard/background-jobs-status.ts +66 -0
  408. package/src/dashboard/index.ts +339 -657
  409. package/src/dashboard/input/agent-wake.ts +242 -0
  410. package/src/dashboard/input/chat-main-entry-runtime.ts +6 -1
  411. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  412. package/src/dashboard/input/chat-main-session.ts +8 -1
  413. package/src/dashboard/input/chat-main-turn.ts +12 -3
  414. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  415. package/src/dashboard/input/external-input-host.ts +49 -9
  416. package/src/dashboard/input/internal-turn.ts +261 -0
  417. package/src/dashboard/input/mouse-wiring.ts +108 -11
  418. package/src/dashboard/input/seat-autowake.ts +318 -0
  419. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  420. package/src/dashboard/log-click-runtime.ts +118 -2
  421. package/src/dashboard/loop-scheduler.ts +72 -0
  422. package/src/dashboard/seat-boot-preamble.ts +18 -0
  423. package/src/dashboard/skill-runtime.ts +2 -0
  424. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  425. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  426. package/src/dashboard/slash-runtime/index.ts +13 -0
  427. package/src/dashboard/turn-busy-teardown.ts +50 -0
  428. package/src/dashboard/turn-preamble.ts +116 -40
  429. package/src/dashboard/turn-session-layers.ts +4 -2
  430. package/src/dashboard/turn-start-segments.ts +222 -0
  431. package/src/decisions/decision-ledger.ts +45 -4
  432. package/src/discord-self-message.ts +4 -4
  433. package/src/display/prompt-row-owner.ts +146 -0
  434. package/src/display/resize-listener.ts +33 -2
  435. package/src/domains/release-tool.ts +18 -1
  436. package/src/field-note/transcribe.ts +17 -0
  437. package/src/fold-stack.ts +4 -2
  438. package/src/git-fs/index.ts +263 -36
  439. package/src/github/remote-call.ts +81 -0
  440. package/src/goals/registry.ts +46 -6
  441. package/src/goals/types.ts +7 -1
  442. package/src/graph-runner/runner.ts +1 -0
  443. package/src/grok/credential.ts +26 -0
  444. package/src/harness/gate-reserve.ts +87 -0
  445. package/src/harness/harness-clean.ts +2 -1
  446. package/src/harness/harness-cli-command.ts +52 -5
  447. package/src/harness/harness-gc.ts +2 -1
  448. package/src/harness/harness-incidents.ts +70 -20
  449. package/src/harness/harness-pod-dispatch.ts +87 -10
  450. package/src/harness/harness-queue.ts +68 -4
  451. package/src/harness/harness-stop.ts +4 -3
  452. package/src/harness/harness-substrate-default.ts +78 -7
  453. package/src/harness/harness-worktree-auto.ts +2 -1
  454. package/src/harness/harness-worktrees.ts +3 -2
  455. package/src/hooks/dispatch.ts +2 -1
  456. package/src/index.ts +156 -27
  457. package/src/input/external-input-queue.ts +64 -7
  458. package/src/intake-plane/slash.ts +14 -3
  459. package/src/keybindings.ts +4 -1
  460. package/src/llm/route-decision.ts +36 -0
  461. package/src/llm/tool-loop-steered-rejection.ts +41 -0
  462. package/src/llm-request-shape.ts +209 -0
  463. package/src/llm.ts +301 -283
  464. package/src/loops/consensus.ts +348 -0
  465. package/src/loops/msg-wake.ts +206 -4
  466. package/src/loops/observe.ts +19 -3
  467. package/src/loops/orchestrator/tick.ts +88 -12
  468. package/src/loops/orchestrator/traffic.ts +64 -1
  469. package/src/loops/registry.ts +30 -0
  470. package/src/market/signed-index.ts +14 -0
  471. package/src/maturity/feature-maturity.ts +1 -1
  472. package/src/mcp/mcp-oauth.ts +54 -5
  473. package/src/models/prompts.ts +28 -0
  474. package/src/msg/msg-sse-client.ts +223 -0
  475. package/src/msg/msg-store.ts +86 -2
  476. package/src/mss/logging/log-store.ts +225 -1
  477. package/src/mss/logging/render-categories.ts +5 -0
  478. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  479. package/src/nexus/api/http-server.ts +54 -15
  480. package/src/nexus/api/loop-resources.ts +19 -3
  481. package/src/nexus/api/ops-api.ts +11 -0
  482. package/src/nexus/daemon-thin-inventory.md +37 -0
  483. package/src/nexus/index.ts +70 -0
  484. package/src/nexus/state/state.ts +1 -0
  485. package/src/oauth/store.ts +32 -7
  486. package/src/onboarding/first-run.ts +28 -3
  487. package/src/ops/overview-cache.ts +16 -4
  488. package/src/ops/overview.ts +59 -2
  489. package/src/ops/resources.ts +82 -0
  490. package/src/plugins/maker/connector-maker.ts +41 -0
  491. package/src/plugins/maker/skill-maker.ts +42 -0
  492. package/src/pr-tool/census.ts +303 -0
  493. package/src/pr-tool/inflight-registry.ts +143 -0
  494. package/src/prompt-library/chat-conciseness.ts +13 -0
  495. package/src/prompt-library/universal-preamble.ts +10 -5
  496. package/src/pty-shell/pty-manifest.ts +12 -3
  497. package/src/pty-shell/tui-run-state.ts +34 -3
  498. package/src/release-loop/gate-host-reservation.ts +97 -0
  499. package/src/release-loop/landing-freeze.ts +5 -0
  500. package/src/release-loop/light-rc.ts +5 -2
  501. package/src/release-loop/placement.ts +92 -1
  502. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  503. package/src/release-loop/rehearsal.ts +73 -17
  504. package/src/repl/index.ts +20 -2
  505. package/src/seat-loop/seat-knowhow.ts +282 -0
  506. package/src/seat-loop/seat-loop.ts +41 -2
  507. package/src/seat-loop/traffic-signal.ts +5 -1
  508. package/src/self-dev/ask-launch-flow.ts +37 -3
  509. package/src/self-dev/decompose-compose-graph.ts +28 -27
  510. package/src/self-dev/decompose-proposal.ts +53 -38
  511. package/src/self-dev/decompose.ts +17 -0
  512. package/src/self-dev/dev-pipeline.ts +31 -2
  513. package/src/self-dev/draft-residue.ts +267 -33
  514. package/src/self-dev/draft-sweep.ts +59 -4
  515. package/src/self-dev/external-call-zero.ts +77 -0
  516. package/src/self-dev/launch-preflight-text.ts +6 -0
  517. package/src/self-dev/launch-preflight.ts +25 -3
  518. package/src/self-dev/local-supervisor-judge.ts +185 -0
  519. package/src/self-dev/run-supervisor.ts +229 -19
  520. package/src/self-dev/run-types.ts +20 -0
  521. package/src/self-dev/shard-aggregate.ts +13 -2
  522. package/src/self-dev/shard-plan.ts +56 -1
  523. package/src/self-dev/shard-run.ts +207 -12
  524. package/src/self-dev/spawn-lane-files.ts +19 -0
  525. package/src/self-implement/app-api-budget.ts +51 -11
  526. package/src/self-implement/config-gate.ts +2 -1
  527. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  528. package/src/self-implement/expose-gate.ts +2 -1
  529. package/src/self-implement/follow-up-placement.ts +79 -0
  530. package/src/self-implement/gate-artifacts.ts +416 -0
  531. package/src/self-implement/gate-baseline.ts +96 -5
  532. package/src/self-implement/gate-cli.ts +207 -17
  533. package/src/self-implement/gate-remote.ts +136 -26
  534. package/src/self-implement/gate-scenario.ts +85 -0
  535. package/src/self-implement/goal-author.ts +160 -8
  536. package/src/self-implement/graph-authority.ts +38 -6
  537. package/src/self-implement/graph-overlay-condition.ts +92 -1
  538. package/src/self-implement/heal-triage.ts +79 -0
  539. package/src/self-implement/host-regate.ts +97 -7
  540. package/src/self-implement/orchestrator.ts +115 -134
  541. package/src/self-implement/pr-title.ts +123 -0
  542. package/src/self-implement/run-checkpoint.ts +235 -0
  543. package/src/self-implement/run-ledger.ts +162 -15
  544. package/src/self-implement/run-stop.ts +4 -3
  545. package/src/self-implement/run-ttl.ts +28 -4
  546. package/src/self-implement/seams.ts +2 -0
  547. package/src/self-implement/shadow-stage.ts +7 -6
  548. package/src/self-implement/stop-autoheal.ts +2 -1
  549. package/src/self-implement/train-gate-remote.ts +37 -8
  550. package/src/self-implement/train-reach-grouping.ts +157 -0
  551. package/src/self-implement/train-scenario-layers.ts +133 -0
  552. package/src/self-implement/uncommitted-work.ts +2 -0
  553. package/src/session/pending-input.ts +19 -0
  554. package/src/session/session-start.ts +224 -0
  555. package/src/session-runtime/index.ts +22 -267
  556. package/src/session-runtime/parallel-dispatch.ts +22 -5
  557. package/src/shell-runner/background-surface.ts +15 -5
  558. package/src/skills/tools/agent.ts +39 -6
  559. package/src/skills/tools/dev-harness.ts +6 -4
  560. package/src/skills/tools/list-dir.ts +11 -0
  561. package/src/skills/tools/schedule-wakeup.ts +408 -0
  562. package/src/skills/tools/shell.ts +246 -4
  563. package/src/status/bar.ts +26 -0
  564. package/src/steward/digest-delivery.ts +118 -0
  565. package/src/steward/hold-hygiene.ts +120 -0
  566. package/src/steward/resync-tick.ts +114 -23
  567. package/src/steward/ta-repair-event-collect.ts +158 -0
  568. package/src/steward/triage.ts +10 -0
  569. package/src/surface/shell-runner-boot.ts +5 -2
  570. package/src/task-agent/card-evidence.ts +25 -1
  571. package/src/task-agent/green-sweep.ts +8 -3
  572. package/src/task-agent/judge.ts +76 -0
  573. package/src/task-agent/land-queue.ts +79 -0
  574. package/src/task-agent/live-moves.ts +30 -9
  575. package/src/task-agent/postland-card.ts +5 -0
  576. package/src/task-agent/prelaunch-already-done.ts +98 -0
  577. package/src/task-agent/real-launch-guard.ts +37 -0
  578. package/src/task-agent/rejudge-on-head.ts +89 -12
  579. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  580. package/src/task-agent/repair-cycle.ts +45 -7
  581. package/src/task-agent/repair-worker.ts +7 -0
  582. package/src/task-agent/run-identity.ts +200 -0
  583. package/src/task-agent/shadow.ts +50 -3
  584. package/src/task-agent/task-hand.ts +182 -5
  585. package/src/task-agent/train-landing.ts +77 -0
  586. package/src/task-agent/work-order.ts +104 -0
  587. package/src/task-orchestrator/surfaces/pod-command-job.ts +151 -37
  588. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  589. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  590. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  591. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  592. package/src/task-orchestrator/surfaces/pod-lease.ts +118 -6
  593. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  594. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  595. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  596. package/src/task-orchestrator/surfaces/pod-pool.ts +3 -1
  597. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  598. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +67 -0
  599. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  600. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  601. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  602. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +525 -0
  603. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  604. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  605. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +362 -0
  606. package/src/task-orchestrator/surfaces/self-implement-pod.ts +138 -19
  607. package/src/telegram.ts +2 -4
  608. package/src/tui/chat/execution-badge.ts +5 -1
  609. package/src/tui/input/pickers.ts +732 -0
  610. package/src/tui/input-lag-probe.ts +230 -0
  611. package/src/tui/slash/mission.ts +492 -0
  612. package/src/tui/slash/term.ts +877 -0
  613. package/src/tui-client/dashboard-session.ts +9 -0
  614. package/src/tui.ts +52 -0
  615. package/src/user-config/gemini-server-tools.ts +9 -0
  616. package/src/user-config.ts +53 -16
  617. package/src/util/spawn-sync-output.ts +7 -0
  618. package/src/ux-sim/fake-bin.ts +154 -0
  619. package/src/ux-sim/fake-clock.ts +36 -0
  620. package/src/ux-sim/headless-tui.ts +72 -0
  621. package/src/ux-sim/in-process-cli.ts +2 -1
  622. package/src/ux-sim/scenario.ts +255 -0
  623. package/src/ux-sim/temp-git-remote.ts +82 -0
  624. package/src/version/packed-revision.json +1 -1
  625. package/src/video-pipeline/recipes/vlog.ts +25 -7
  626. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  630. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  632. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  635. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  636. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  639. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  641. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  647. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  651. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  662. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  668. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  671. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  672. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  673. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  676. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  678. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  679. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  680. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  682. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  688. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  695. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  698. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  703. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  705. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  768. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  774. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +0 -1
  775. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_ssgManifest.js +0 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * INFLIGHT-REGISTRY — 비행 중 등록부(대표 10-17 «출발 때 맥락 남기고 머지 때 참조 · 착지하면 지움 · 폭증 막기»).
3
+ *
4
+ * 발사하는 런이 runId·칸·한 줄 의도·대상 파일을 한 줄 등록하고, 머지 순간(스마트 머지 LLM)에 같은 파일을
5
+ * 만지는 줄들의 의도를 읽는다. 착지하면 지운다. 정본은 PR 본문이고 이것은 «색인»이다 — 못 읽으면 빈 목록
6
+ * (머지는 종전 그대로 간다), 못 쓰면 발사·착지를 막지 않는다(호출부가 fail-soft).
7
+ *
8
+ * 폭증 막기: 런당 1줄(같은 칸 재발사는 덮어씀) · 의도 ≤300자 · 파일 ≤20 · 48h 지난 줄은 읽을 때 거르고 쓸 때 걷는다.
9
+ */
10
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
+ import { dirname, join } from 'node:path';
12
+ import { debug } from '../debug/log.js';
13
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
14
+ import { withFileLockSync } from '../storage/file-lock.js';
15
+
16
+ export const INFLIGHT_INTENT_MAX_CHARS = 300;
17
+ export const INFLIGHT_FILES_MAX = 20;
18
+ export const INFLIGHT_TTL_MS = 48 * 60 * 60 * 1000;
19
+ export const INFLIGHT_REGISTRY_FILE = 'inflight-registry.json';
20
+
21
+ export interface InflightEntry {
22
+ runId: string;
23
+ /** 칸 id(없으면 카드 id) — 같은 칸 재발사는 이 키로 덮어쓴다. */
24
+ cell: string;
25
+ intent: string;
26
+ files: string[];
27
+ registeredAt: string;
28
+ cardId?: string;
29
+ }
30
+
31
+ export interface InflightOptions {
32
+ path?: string;
33
+ now?: () => Date;
34
+ }
35
+
36
+ /** 기본 자리 — 과제 카드 상태(`task-agent-actions.json`)와 같은 우주 뿌리. */
37
+ export function inflightRegistryPath(): string {
38
+ return join(effectiveInstanceRoot(), INFLIGHT_REGISTRY_FILE);
39
+ }
40
+
41
+ function readEntries(path: string): InflightEntry[] {
42
+ if (!existsSync(path)) return [];
43
+ try {
44
+ const parsed = JSON.parse(readFileSync(path, 'utf8')) as { entries?: unknown };
45
+ return Array.isArray(parsed.entries) ? parsed.entries.filter(isEntry) : [];
46
+ } catch { return []; }
47
+ }
48
+
49
+ function isEntry(value: unknown): value is InflightEntry {
50
+ const entry = value as Partial<InflightEntry> | null;
51
+ return !!entry && typeof entry.runId === 'string' && typeof entry.cell === 'string' && typeof entry.intent === 'string'
52
+ && Array.isArray(entry.files) && typeof entry.registeredAt === 'string';
53
+ }
54
+
55
+ function isExpired(entry: InflightEntry, now: Date): boolean {
56
+ const at = Date.parse(entry.registeredAt);
57
+ return !Number.isFinite(at) || now.getTime() - at > INFLIGHT_TTL_MS;
58
+ }
59
+
60
+ /** 잠금 안에서 읽고 고쳐 쓴다 — 48h 지난 줄은 쓸 때 걷는다(`expire` 관측). */
61
+ function mutate(opts: InflightOptions, update: (entries: InflightEntry[]) => InflightEntry[]): void {
62
+ const path = opts.path ?? inflightRegistryPath();
63
+ const now = (opts.now ?? (() => new Date()))();
64
+ withFileLockSync(`${path}.lock`, () => {
65
+ const all = readEntries(path);
66
+ const live = all.filter((entry) => !isExpired(entry, now));
67
+ if (live.length < all.length) {
68
+ try { debug.log('pr-tool.inflight', 'expire', { phase: 'write', runIds: all.filter((entry) => isExpired(entry, now)).map((entry) => entry.runId) }); } catch { /* fail-soft */ }
69
+ }
70
+ mkdirSync(dirname(path), { recursive: true });
71
+ writeFileSync(path, JSON.stringify({ entries: update(live) }));
72
+ });
73
+ }
74
+
75
+ /** 한 줄 등록 — 같은 runId 또는 같은 칸의 옛 줄을 덮어쓴다. 의도·파일은 상한에서 자른다. */
76
+ export function registerInflight(input: { runId: string; cell: string; intent: string; files: readonly string[]; cardId?: string }, opts: InflightOptions = {}): InflightEntry {
77
+ const now = (opts.now ?? (() => new Date()))();
78
+ const files = [...new Set(input.files.map((file) => file.trim()).filter(Boolean))];
79
+ // 한 줄 칸만 — 줄바꿈·제어 문자는 공백으로(머지 프롬프트 인용 블록을 깨지 못하게 · 프롬프트 쪽도 따로 무력화한다).
80
+ const oneLine = (value: string) => value.replace(/[\p{Cc}\s]+/gu, ' ').trim();
81
+ const entry: InflightEntry = {
82
+ runId: oneLine(input.runId),
83
+ cell: oneLine(input.cell),
84
+ intent: oneLine(input.intent).slice(0, INFLIGHT_INTENT_MAX_CHARS),
85
+ files: files.slice(0, INFLIGHT_FILES_MAX),
86
+ registeredAt: now.toISOString(),
87
+ ...(input.cardId ? { cardId: input.cardId } : {}),
88
+ };
89
+ let replaced: string[] = [];
90
+ mutate(opts, (entries) => {
91
+ replaced = entries.filter((old) => old.runId === entry.runId || old.cell === entry.cell).map((old) => old.runId);
92
+ return [...entries.filter((old) => old.runId !== entry.runId && old.cell !== entry.cell), entry];
93
+ });
94
+ try { debug.log('pr-tool.inflight', 'register', { runId: entry.runId, cell: entry.cell, files: entry.files.length, filesDropped: files.length - entry.files.length, intentChars: entry.intent.length, replaced }); } catch { /* fail-soft */ }
95
+ return entry;
96
+ }
97
+
98
+ /** 줄을 지운다 — runId 또는 카드 id 로. 지운 수를 돌려준다(0 = 그런 줄 없음). */
99
+ export function removeInflight(key: { runId: string } | { cardId: string }, reason: string, opts: InflightOptions = {}): number {
100
+ let removed: string[] = [];
101
+ const matches = (entry: InflightEntry): boolean => 'runId' in key ? entry.runId === key.runId : entry.cardId === key.cardId;
102
+ mutate(opts, (entries) => {
103
+ removed = entries.filter(matches).map((entry) => entry.runId);
104
+ return entries.filter((entry) => !matches(entry));
105
+ });
106
+ try { debug.log('pr-tool.inflight', 'remove', { ...key, reason, removed }); } catch { /* fail-soft */ }
107
+ return removed.length;
108
+ }
109
+
110
+ /** 살아 있는 줄 — `files` 를 주면 그중 하나라도 만지는 줄만. 48h 지난 줄은 거른다(읽기는 쓰지 않는다). */
111
+ export function listInflight(filter: { files?: readonly string[] } = {}, opts: InflightOptions = {}): InflightEntry[] {
112
+ const now = (opts.now ?? (() => new Date()))();
113
+ const all = readEntries(opts.path ?? inflightRegistryPath());
114
+ const live = all.filter((entry) => !isExpired(entry, now));
115
+ if (live.length < all.length) {
116
+ try { debug.log('pr-tool.inflight', 'expire', { phase: 'read', count: all.length - live.length }); } catch { /* fail-soft */ }
117
+ }
118
+ if (!filter.files) return live;
119
+ const wanted = new Set(filter.files);
120
+ return live.filter((entry) => entry.files.some((file) => wanted.has(file)));
121
+ }
122
+
123
+ /**
124
+ * 착지한 PR 의 줄을 지운다 — 그 PR 을 연 과제 카드(`card.pr`)의 카드 id·runId 로 찾는다.
125
+ * 카드가 없으면 디스크를 건드리지 않는다(사람 PR · 다른 우주 카드 = 지울 줄 없음).
126
+ */
127
+ export function removeInflightForPr(
128
+ pr: number,
129
+ cards: Iterable<{ id: string; runId?: string; pr?: number | { number: number } }>,
130
+ opts: InflightOptions = {},
131
+ ): number {
132
+ const owners = [...cards].filter((card) => (typeof card.pr === 'number' ? card.pr : card.pr?.number) === pr);
133
+ if (owners.length === 0) {
134
+ try { debug.log('pr-tool.inflight', 'remove', { pr, reason: 'pr-landed', removed: [], cards: 0 }); } catch { /* fail-soft */ }
135
+ return 0;
136
+ }
137
+ let removed = 0;
138
+ for (const card of owners) {
139
+ removed += removeInflight({ cardId: card.id }, `pr-landed:${pr}`, opts);
140
+ if (card.runId) removed += removeInflight({ runId: card.runId }, `pr-landed:${pr}`, opts);
141
+ }
142
+ return removed;
143
+ }
@@ -39,6 +39,19 @@ useful answers instead of narrated progress.
39
39
  - Group related actions into one short preamble instead of emitting
40
40
  a new status line before every command.
41
41
 
42
+ ## Initiative
43
+
44
+ - Act first: when looking (repo, logs, tools) can answer or advance the
45
+ request, do that before asking, and answer with what you found or did.
46
+ - Ambiguous request: take the most plausible reading, proceed, and state
47
+ the assumption in one line. Ask first only when a wrong guess would be
48
+ costly or hard to undo.
49
+ - Finish forward: end with up to 3 concrete next steps. When one is
50
+ obvious, cheap and inside the request, continue and do it instead of
51
+ offering it.
52
+ - A stop always comes with a path: when you decline or cannot finish, say
53
+ what you will do instead or what would unblock it.
54
+
42
55
  ## Terminal formatting
43
56
 
44
57
  - Use monospace CommonMark for commands, paths, env vars, and code ids.
@@ -104,10 +104,13 @@ execute the next stage; your tool calls are the audit trail.
104
104
 
105
105
  ## Analysis (분석) — find → read → organize
106
106
  When a user's analysis question identifies a concrete, user-fixable code or
107
- configuration defect, end the organized answer with a clear next-action CTA:
108
- ask whether they want the discovered fix implemented (for example,
109
- \`수정할까요?\`). Do not ask this when no actionable defect was found, and do
110
- not claim a change was made before it is implemented and verified.
107
+ configuration defect: if the fix is small, low-risk and inside what the user
108
+ asked about, make it — switch to the Implementation pipeline, verify it, then
109
+ report what changed. Otherwise end the organized answer with 1-3 concrete
110
+ next actions and ask only the one decision that is really the user's (for
111
+ example, \`이 세 곳을 고칠까요?\` / \`수정할까요?\`). Do not ask when no actionable
112
+ defect was found, and do not claim a change was made before it is implemented
113
+ and verified.
111
114
  1. **find**: ONE batch of search tools (Grep / Glob / ListDir / AstGrep
112
115
  in parallel) to locate candidate files. Do not run a second \`find\`
113
116
  batch unless the first returned ZERO useful candidates — if it
@@ -144,7 +147,9 @@ not claim a change was made before it is implemented and verified.
144
147
  produces candidate paths. Do not issue a second \`find\` batch
145
148
  searching the SAME paths/globs with different keywords — the
146
149
  candidates are already on the table; advance to \`read\`.
147
- - For Analysis: stop at \`organize\`. Don't drift into edit/exec.
150
+ - For Analysis: end at \`organize\` unless a small, low-risk fix inside the
151
+ request is ready — then switch to Implementation (edit → verify). Larger or
152
+ out-of-scope changes stay a proposal.
148
153
  - For Implementation/Debugging: \`verify\` is mandatory. "I made the
149
154
  change" without verification is incomplete output.
150
155
  - Pick a pipeline ONLY when you actually need to use it. Pure conversational
@@ -277,6 +277,9 @@ export function upsertPtyManifest(row: {
277
277
  };
278
278
  }): void {
279
279
  try {
280
+ // 행을 (다시) 세우면 snapshot·frame 칸이 비워진다 — 같은 프로세스의 쓰기 스로틀도 비워 다음 쓰기가 바로 닿게 한다.
281
+ _lastSnapshotAt.delete(row.id);
282
+ _lastFrameAt.delete(row.id);
280
283
  const d = db(); if (!d) return;
281
284
  const runId = getHarnessRunId(process.env);
282
285
  const runIdSource = getHarnessRunIdSource();
@@ -800,12 +803,18 @@ export function listPtyManifestByRun(runId: string): PtyManifestRow[] {
800
803
  }
801
804
  }
802
805
 
803
- export function getPtyManifest(id: string): PtyManifestRow | null {
806
+ /** `strict` — 조회 실패(db 못 엶·질의 오류)를 «행 없음»(null)과 가르도록 던진다. 기본은 둘 다 null(fail-soft). */
807
+ export function getPtyManifest(id: string, opts: { readonly strict?: boolean } = {}): PtyManifestRow | null {
804
808
  try {
805
- const d = db(); if (!d) return null;
809
+ const d = db();
810
+ if (!d) {
811
+ if (opts.strict) throw new Error('pty-manifest-db-unavailable');
812
+ return null;
813
+ }
806
814
  const row = d.query('SELECT * FROM pty_manifest WHERE id=?').get(id) as Record<string, unknown> | null;
807
815
  return row ? mapRow(row) : null;
808
- } catch {
816
+ } catch (error) {
817
+ if (opts.strict) throw error;
809
818
  return null;
810
819
  }
811
820
  }
@@ -176,10 +176,9 @@ export function describePtyRunState(
176
176
  ...(checkoutHead ? { checkoutHead } : {}),
177
177
  ...(row && row.kind === 'tui' ? { startedAt: row.startedAt } : {}),
178
178
  });
179
- const turn: PtyTurnView = row?.alive && row.turnState ? row.turnState : 'unknown';
179
+ const turnView = ptyTurnViewOfRow(row);
180
180
  return {
181
- turn,
182
- ...(turn !== 'unknown' && row?.turnAt ? { turnAt: row.turnAt } : {}),
181
+ ...turnView,
183
182
  build: build ?? null,
184
183
  installed: installed.sha ?? null,
185
184
  stale: staleness.stale,
@@ -191,6 +190,38 @@ export function shortSha(sha: string | null | undefined): string {
191
190
  return sha ? sha.slice(0, 7) : '-';
192
191
  }
193
192
 
193
+ /** 행의 자기보고 턴만 — 설치본·git 판독과 «무관»하다(판독이 실패해도 기록된 턴은 그대로 읽힌다). 죽은 행·기록 없음 = unknown. */
194
+ export function ptyTurnViewOfRow(row: Pick<PtyManifestRow, 'alive' | 'turnState' | 'turnAt'> | null | undefined): Pick<PtyRunStateView, 'turn' | 'turnAt'> {
195
+ const turn: PtyTurnView = row?.alive && row.turnState ? row.turnState : 'unknown';
196
+ return { turn, ...(turn !== 'unknown' && row?.turnAt ? { turnAt: row.turnAt } : {}) };
197
+ }
198
+
199
+ // ── 턴 칸(H10 · `pty list` 가 화면 긁기 없이 «지금 턴 중인가·얼마나 됐나»를 낸다) ──
200
+
201
+ export interface PtyTurnCell {
202
+ readonly state: PtyTurnView;
203
+ /** 지금 턴 상태로 바뀐 시각(epoch ms) — 모르면 null. */
204
+ readonly at: number | null;
205
+ /** 지금 턴 상태에 머문 초(busy 면 «이 턴 경과»). ⛔ 모르면 null — 「0초」와 「못 잼」은 다른 값이다. */
206
+ readonly sinceSec: number | null;
207
+ }
208
+
209
+ export const UNKNOWN_TURN_CELL: PtyTurnCell = { state: 'unknown', at: null, sinceSec: null };
210
+
211
+ /** `turnAt` 은 턴 값이 «바뀔 때만» 적힌다(`reportTuiTurn` 이 같은 값을 거른다) ⇒ now−turnAt = 그 상태의 경과. */
212
+ export function describeTurnCell(view: Pick<PtyRunStateView, 'turn' | 'turnAt'>, now: number): PtyTurnCell {
213
+ if (view.turn === 'unknown' || view.turnAt === undefined || !Number.isFinite(view.turnAt) || view.turnAt <= 0) {
214
+ return { state: view.turn, at: null, sinceSec: null };
215
+ }
216
+ return { state: view.turn, at: view.turnAt, sinceSec: Math.max(0, Math.floor((now - view.turnAt) / 1000)) };
217
+ }
218
+
219
+ /** 표 한 칸 값: `busy,42s` · `idle,300s` · 시각 모름 `busy,?s` · 턴 모름 `?`. */
220
+ export function formatTurnCell(cell: PtyTurnCell): string {
221
+ if (cell.state === 'unknown') return '?';
222
+ return `${cell.state},${cell.sinceSec === null ? '?' : cell.sinceSec}s`;
223
+ }
224
+
194
225
  // ── 기록(TUI) ──
195
226
 
196
227
  export interface TuiRunStateRecorderDeps {
@@ -0,0 +1,97 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { psProcessStartMs } from '../harness/harness-stop.js';
5
+ import { debug } from '../debug/log.js';
6
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
7
+
8
+ interface GateHostClaim {
9
+ token: string;
10
+ runId: string;
11
+ hosts: string[];
12
+ pid: number;
13
+ pidStartedAt: number | null;
14
+ }
15
+
16
+ export type GateHostReservation =
17
+ | { status: 'free' }
18
+ | { status: 'reserved' | 'unknown'; reason: string; runId?: string };
19
+
20
+ const hostName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
21
+ const claimsDir = (root: string) => join(root, 'release', 'gate-host-reservations');
22
+
23
+ /** The release graph's pinned child state and the self gate CLI's selected universe resolve through this same entry. */
24
+ export function gateHostReservationRoot(): string { return effectiveInstanceRoot(); }
25
+
26
+ function claimAlive(claim: GateHostClaim): 'alive' | 'dead' | 'unknown' {
27
+ try { process.kill(claim.pid, 0); }
28
+ catch (error) {
29
+ return (error as NodeJS.ErrnoException).code === 'ESRCH' ? 'dead' : 'unknown';
30
+ }
31
+ if (claim.pidStartedAt === null) return 'unknown';
32
+ const current = psProcessStartMs(claim.pid);
33
+ if (current === null) return 'unknown';
34
+ return Math.abs(current - claim.pidStartedAt) <= 2_000 ? 'alive' : 'dead';
35
+ }
36
+
37
+ /** A gate owns its host until its node exits. A crashed owner's claim is removed on the next read. */
38
+ export function reserveReleaseGateHosts(root: string, runId: string, hosts: readonly string[]): () => void {
39
+ const unique = [...new Set(hosts)];
40
+ if (!runId || unique.some(host => host !== '*' && !hostName.test(host))) throw new Error('invalid release gate reservation');
41
+ if (!unique.length) return () => undefined;
42
+ const dir = claimsDir(root);
43
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
44
+ const token = randomUUID();
45
+ const pidStartedAt = psProcessStartMs(process.pid);
46
+ if (pidStartedAt === null) throw new Error('release gate owner start time unmeasured');
47
+ const claim: GateHostClaim = { token, runId, hosts: unique, pid: process.pid, pidStartedAt };
48
+ const path = join(dir, `${token}.json`);
49
+ const temp = join(dir, `.${token}.tmp`);
50
+ try {
51
+ writeFileSync(temp, JSON.stringify(claim) + '\n', { mode: 0o600, flag: 'wx' });
52
+ renameSync(temp, path);
53
+ } finally { if (existsSync(temp)) rmSync(temp); }
54
+ debug.log('release-loop.gate', 'host-reserved', { runId, hosts: unique, pid: process.pid, path });
55
+ return () => {
56
+ try {
57
+ const current = JSON.parse(readFileSync(path, 'utf8')) as Partial<GateHostClaim>;
58
+ if (current.token === token) rmSync(path);
59
+ debug.log('release-loop.gate', 'host-released', { runId, hosts: unique, path });
60
+ } catch (error) {
61
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT')
62
+ debug.log('release-loop.gate', 'host-release-unmeasured', { runId, path, error: String(error) });
63
+ }
64
+ };
65
+ }
66
+
67
+ /** An unreadable claim is a reservation, never permission to enter a gate host. */
68
+ export function inspectReleaseGateHost(root: string, host: string): GateHostReservation {
69
+ const dir = claimsDir(root);
70
+ let names: string[];
71
+ try { names = readdirSync(dir).filter(name => name.endsWith('.json')); }
72
+ catch (error) {
73
+ return { status: 'unknown', reason: `reservation directory unreadable: ${String(error)}` };
74
+ }
75
+ for (const name of names) {
76
+ const path = join(dir, name);
77
+ let claim: GateHostClaim;
78
+ try {
79
+ claim = JSON.parse(readFileSync(path, 'utf8')) as GateHostClaim;
80
+ if (!claim || !Array.isArray(claim.hosts) || claim.hosts.length === 0
81
+ || !claim.hosts.every(item => typeof item === 'string' && (item === '*' || hostName.test(item)))
82
+ || !Number.isSafeInteger(claim.pid) || claim.pid <= 0 || typeof claim.token !== 'string'
83
+ || typeof claim.runId !== 'string' || !claim.runId
84
+ || (claim.pidStartedAt !== null && (!Number.isSafeInteger(claim.pidStartedAt)
85
+ || claim.pidStartedAt <= 0 || claim.pidStartedAt > Date.now()))) throw new Error('invalid claim');
86
+ } catch (error) { return { status: 'unknown', reason: `reservation unreadable: ${name}: ${String(error)}` }; }
87
+ const live = claimAlive(claim);
88
+ if (live === 'dead') {
89
+ try { rmSync(path); } catch { /* a confirmed dead process cannot still own the host */ }
90
+ debug.log('release-loop.gate', 'host-claim-reclaimed', { runId: claim.runId, hosts: claim.hosts, path });
91
+ continue;
92
+ }
93
+ if (!claim.hosts.includes(host) && !claim.hosts.includes('*')) continue;
94
+ return { status: live === 'unknown' ? 'unknown' : 'reserved', reason: `release gate ${claim.runId} holds ${host}`, runId: claim.runId };
95
+ }
96
+ return { status: 'free' };
97
+ }
@@ -36,6 +36,11 @@ export function readLandingFreeze(root = effectiveInstanceRoot(), now = new Date
36
36
  return { ...freeze, holdLaunches: freeze.holdLaunches ?? false } as LandingFreeze;
37
37
  }
38
38
 
39
+ /** Interpret a validated, expiry-aware read without reading the freeze file twice. */
40
+ export function landingFreezeState(freeze: LandingFreeze | null): 'on' | 'off' {
41
+ return freeze === null ? 'off' : 'on';
42
+ }
43
+
39
44
  export function enableLandingFreeze(opts: { reason?: string; until?: string; by?: string; holdLaunches?: boolean }, root = effectiveInstanceRoot(), now = new Date()): LandingFreeze {
40
45
  const until = opts.until === undefined ? null : opts.until;
41
46
  if (until !== null && (!/^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d+)?)?(?:Z|[+-]\d\d:\d\d)$/.test(until) || !Number.isFinite(Date.parse(until)) || Date.parse(until) <= now.getTime())) {
@@ -29,6 +29,9 @@ export interface LightRcOptions {
29
29
  /** Run on this machine (the remote child is re-invoked with it). */
30
30
  local?: boolean;
31
31
  shards?: number;
32
+ /** OP FU — pass `--fixed-shard-distribution` to self gate (sorted round-robin into `shards`, no RSS pre-measurement).
33
+ * Opt-in; absent = the measured planner, unchanged. Also carried to the remote child. */
34
+ fixedShardDistribution?: boolean;
32
35
  /** Release ledger root for the previous-version lookup (release run's deps.ledgerRoot). */
33
36
  ledgerRoot?: string;
34
37
  log?: (line: string) => void;
@@ -192,7 +195,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
192
195
  try {
193
196
  const dir = checkout?.dir ?? cwd;
194
197
  if (checkout) alwaysInclude = readList(dir);
195
- local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, alwaysInclude, includeImporterTests: true });
198
+ local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), alwaysInclude, includeImporterTests: true });
196
199
  if (opts.rehearsalTui) {
197
200
  const command = async (cmd: string, args: string[], tree: string, limitMs?: number) => {
198
201
  const run = spawnSync(cmd, args, { cwd: tree, encoding: 'utf8', timeout: limitMs });
@@ -208,7 +211,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
208
211
  const rc = await (deps.dispatch ?? dispatchHeavyCheck)({
209
212
  tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
210
213
  // The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
211
- remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
214
+ remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), ...(opts.fixedShardDistribution ? ['--fixed-shard-distribution'] : []), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
212
215
  flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
213
216
  runLocal,
214
217
  }, {
@@ -6,7 +6,7 @@ import { resolveRepositoryName } from '../harness/repository-name.js';
6
6
  import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
7
7
  import { effectiveInstanceRoot } from '../instance/resolve.js';
8
8
  import { userConfigPath } from '../user-config.js';
9
- import { addItem, checklistHistory, listChecklist, ownerMatches, parseOwner, setItem, validateCeoLoad, type ChecklistItem } from './checklist.js';
9
+ import { addItem, checklistHistory, inspectChecklistTargetPaths, listChecklist, ownerMatches, parseOwner, setItem, validateCeoLoad, type ChecklistItem } from './checklist.js';
10
10
  import { assignedVersions, move, releasedVersion } from './feature-store.js';
11
11
  import { debug } from '../debug/log.js';
12
12
  import { kstDay, listSchedules, type ReleaseSchedule } from './release-schedule.js';
@@ -110,6 +110,12 @@ function validCeoCap(cap: number): number {
110
110
 
111
111
  export function placementCeoDailyCap(): number { return validCeoCap(placementConfig().ceoDailyCap ?? 30); }
112
112
 
113
+ /** One configuration snapshot for the read-only pull-forward caller. */
114
+ export function pullForwardPlacementConfig(): { seatCap: Record<string, number>; ceoDailyCap: number; ceoCalendar: CeoCalendar } {
115
+ const config = placementConfig();
116
+ return { seatCap: config.seatCap ?? {}, ceoDailyCap: validCeoCap(config.ceoDailyCap ?? 30), ceoCalendar: config.ceoCalendar ?? {} };
117
+ }
118
+
113
119
  function validDay(day: string): boolean {
114
120
  return typeof day === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(day) && Number.isFinite(Date.parse(`${day}T00:00:00Z`))
115
121
  && new Date(`${day}T00:00:00Z`).toISOString().slice(0, 10) === day;
@@ -406,6 +412,91 @@ export function rebalance(version: string, deps: PlacementDeps = {}): RebalanceR
406
412
  return result;
407
413
  }
408
414
 
415
+ export interface PullForwardDeps {
416
+ now: Date;
417
+ schedules: readonly ReleaseSchedule[];
418
+ checklists: ReadonlyMap<string, readonly ChecklistItem[]>;
419
+ released: string;
420
+ merged24h: number;
421
+ seatCap: Record<string, number>;
422
+ ceoDailyCap: number;
423
+ ceoCalendar: CeoCalendar;
424
+ signal: { order?: readonly string[]; hold?: readonly string[] };
425
+ targetPathExists: (path: string) => boolean;
426
+ backlog?: readonly string[];
427
+ }
428
+
429
+ /** Read-only plan: every operational input is supplied by the caller. */
430
+ export function planPullForward(deps: PullForwardDeps): RebalanceResult {
431
+ if (typeof deps.targetPathExists !== 'function') throw new CliUserError('대상 저장소 경로 판정기가 필요하다');
432
+ const rows = [...deps.schedules].sort((a, b) => versionOrder(a.version, b.version));
433
+ const now = deps.now.getTime();
434
+ const backlog = deps.backlog ?? BACKLOG_VERSIONS;
435
+ const released = deps.released;
436
+ const open = rows.filter((row) => (!released || versionOrder(row.version, released) > 0) && available(row, now, backlog));
437
+ const target = open[0];
438
+ if (!target) throw new CliUserError('당겨올 판이 없다 — 착지 마감이 안 지난 판이 필요하다');
439
+ const result: RebalanceResult = { decisions: [], blocked: [] };
440
+ const source = rows.find((row) => versionOrder(row.version, target.version) > 0 && !backlog.includes(row.version));
441
+ if (!source || !available(source, now, backlog)) return result;
442
+ const sources = [...new Set([...rows.map((row) => row.version), ...deps.checklists.keys(), ...backlog])];
443
+ const snapshots = new Map(sources.map((version) => [version, [...(deps.checklists.get(version) ?? [])]]));
444
+ const remainingP0 = snapshots.get(target.version)!.filter((item) => item.priority === 'P0' && item.status !== 'green' && item.status !== 'done').length;
445
+ const hold = new Set(deps.signal?.hold ?? []);
446
+ const rank = new Map<string, number>();
447
+ for (const [index, id] of (deps.signal?.order ?? []).entries()) if (!rank.has(id)) rank.set(id, index);
448
+ // Untyped legacy cells are fail-closed on human-action words in either language. These
449
+ // conservative markers may exclude code about approvals, but must never move a manual gate.
450
+ const human = /\uD83D\uDC51|실기기|실기 |사람|대표|손|라이브 1회|녹화|세미나|수동|승인|검토|결정|HITL|manual|human|approval|sign.off|review|operator|ceo/i;
451
+ const complete = new Set<string>();
452
+ const incomplete = new Set<string>();
453
+ for (const items of snapshots.values()) for (const item of items) {
454
+ if (item.status === 'green' || item.status === 'done') complete.add(item.id);
455
+ else incomplete.add(item.id);
456
+ }
457
+ const targetPathsReady = (title: string): boolean => {
458
+ const check = inspectChecklistTargetPaths({ title }, { existsAtMain: deps.targetPathExists });
459
+ return check.targets.length > 0 && check.warnings.length === 0;
460
+ };
461
+ const candidates = snapshots.get(source.version)!.filter((item) =>
462
+ (item.priority === 'P0' || item.priority === 'P1') && item.status !== 'green' && item.status !== 'done'
463
+ && !hold.has(item.id) && !human.test(item.title) && (!item.dispatchKind || item.dispatchKind === 'code')
464
+ && (item.ceoMinutes === undefined || item.ceoMinutes === 0)
465
+ && targetPathsReady(item.title)
466
+ && (item.predecessors ?? []).every((id) => complete.has(id) && !incomplete.has(id)))
467
+ .map((item, index) => ({ item, index }))
468
+ .sort((a, b) => (rank.get(a.item.id) ?? Infinity) - (rank.get(b.item.id) ?? Infinity)
469
+ || (a.item.priority === 'P0' ? 0 : 1) - (b.item.priority === 'P0' ? 0 : 1) || a.index - b.index);
470
+ if (!candidates.length) return result;
471
+ if (Date.parse(target.landBy ?? target.cutAt) - now < 4 * 60 * 60 * 1000) {
472
+ for (const { item } of candidates)
473
+ result.blocked.push({ id: item.id, from: source.version, to: target.version, reason: `지금 판 ${target.version} 착지 마감까지 4시간 미만 — 당겨오기 보류` });
474
+ return result;
475
+ }
476
+ if (remainingP0 > 3) {
477
+ for (const { item } of candidates)
478
+ result.blocked.push({ id: item.id, from: source.version, to: target.version, reason: `지금 판 ${target.version} 남은 P0 ${remainingP0} > 3 — 당겨오기 보류` });
479
+ return result;
480
+ }
481
+ const rate = deps.merged24h;
482
+ if (!Number.isInteger(rate) || rate < 0) throw new CliUserError('24시간 병합 PR 수가 잘못됐다');
483
+ const caps = deps.seatCap;
484
+ const ceoCap = validCeoCap(deps.ceoDailyCap);
485
+ const calendar = deps.ceoCalendar;
486
+ for (const { item } of candidates) {
487
+ if (result.decisions.length >= 5) break;
488
+ const from = source.version;
489
+ // The pull-forward contract uses the schedule's cutAt only when landBy is absent.
490
+ const destination = { ...target, landBy: target.landBy ?? target.cutAt };
491
+ const violation = moveConstraint(item, destination, backlog, snapshots, now, rate, caps, rows, ceoCap, calendar, released);
492
+ if (violation) { result.blocked.push({ id: item.id, from, to: target.version, reason: violation }); continue; }
493
+ result.decisions.push({ id: item.id, from, version: target.version, reason: `다음 판 ${from} → 지금 판 ${target.version} 당겨오기 · 남은 P0 ${remainingP0} ≤ 3 · 착지 마감 ≥ 4h`, displaced: [] });
494
+ snapshots.set(from, snapshots.get(from)!.filter((cell) => cell.id !== item.id));
495
+ snapshots.get(target.version)!.push(item);
496
+ }
497
+ return result;
498
+ }
499
+
409
500
  /** Reasons that justify a second forward rollover of the same cell (대표 10-10 «계속 이월되지 않게»). */
410
501
  const SECOND_ROLLOVER_REASON_PREFIXES: readonly string[] = ['쪼개기:', '닫기:', '\u{1F451}:'];
411
502