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,149 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { availableParallelism, cpus as hostCpus, freemem, totalmem } from 'node:os';
3
+ import { existsSync, readFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { selectGateTestFiles } from '../self-implement/gate-cli.js';
6
+ import { readFileMemory } from '../../scripts/release-loop/shard-plan.js';
7
+ import { gateShardsPath, readGateShards } from './gate-shards.js';
8
+ import { LIGHT_RC_ALWAYS_FILE, LIGHT_RC_DEFAULT_SHARDS, parseAlwaysIncludeList, previousCutBase } from './light-rc.js';
9
+
10
+ const FILE_MEMORY_SOURCE = 'docs/measurements/td1-whole-gate-mechanical-2026-10-01.tsv';
11
+
12
+ export interface RehearsalShardPlan {
13
+ shards: number;
14
+ testFiles: number | null;
15
+ /** Observed on the tick host, not necessarily the remote gate host. */
16
+ resources: { cpus: number; freeBytes: number; totalBytes: number };
17
+ gatePlanShards: number | null;
18
+ /** Local preflight budget, not a measured remote peak-RSS or a workload-specific guarantee. */
19
+ capacity?: { reserveBytes: number; bytesPerShard: number; memoryShards: number | null; requiredBytes: number; measuredFiles: number; peakFileBytes: number | null };
20
+ unmeasured: string | null;
21
+ /** The remote host's capacity is checked by the actual RC, after this preflight. */
22
+ remoteCapacityPending?: boolean;
23
+ rssRevisionPending?: boolean;
24
+ planningGaps?: string[];
25
+ remoteCapacityVerifiedBy?: string;
26
+ }
27
+
28
+ export interface RehearsalShardPlanDeps {
29
+ /** Rehearsal light RC dispatches remotely; local CPU/memory is evidence only, not a gate-host limit. */
30
+ remoteGate?: boolean;
31
+ select?: (checkout: string, options: { base: string; alwaysInclude: string[]; includeImporterTests: true }) => { testFiles: string[]; alwaysIncludeMissing?: readonly string[]; lookupFailed?: string | null; unrunImporterTotal?: number | null; skipTestStep?: boolean; routeLookupFailures?: readonly unknown[]; unverified?: readonly string[]; callerTestsOverflow?: readonly unknown[] };
32
+ resources?: () => RehearsalShardPlan['resources'];
33
+ board?: typeof readGateShards;
34
+ readAlways?: (path: string) => string;
35
+ resolveBase?: (version: string, checkout: string, root: string) => string;
36
+ fileMemory?: (path: string) => Map<string, number>;
37
+ }
38
+
39
+ /** Preflight only: the gate still performs its own selection at execution time. The local budget uses measured
40
+ * selected-file peak RSS with a 2 GiB floor per shard and reserves 1 GiB for the host. The RC result is the
41
+ * authority for whether execution on its actual gate host succeeded. */
42
+ const GIB = 1024 ** 3;
43
+ const RESERVE_BYTES = GIB;
44
+ const BYTES_PER_SHARD = 2 * GIB;
45
+
46
+ /** The dated TSV has no dependency graph/revision. Require the whole checkout to match its source commit;
47
+ * otherwise RSS is provisional until a completed RC measures this actual checkout on its gate host. */
48
+ function measurementMatchesCheckout(checkout: string): boolean {
49
+ const source = spawnSync('git', ['log', '-1', '--format=%H', '--', FILE_MEMORY_SOURCE], { cwd: checkout, encoding: 'utf8' });
50
+ const commit = source.stdout?.trim();
51
+ if (source.status !== 0 || !/^[0-9a-f]{40}$/.test(commit ?? '')) return false;
52
+ const diff = spawnSync('git', ['diff', '--quiet', commit!, 'HEAD', '--', '.'], { cwd: checkout, encoding: 'utf8' });
53
+ if (diff.status !== 0) return false;
54
+ const working = spawnSync('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: checkout, encoding: 'utf8' });
55
+ return working.status === 0 && !working.stdout?.trim();
56
+ }
57
+
58
+ /** OS free memory can describe the entire host rather than the tick's container; bound it by cgroup headroom. */
59
+ export function rehearsalHostResources(read: (path: string) => string = (path) => readFileSync(path, 'utf8')): RehearsalShardPlan['resources'] {
60
+ const cpus = Math.max(1, Number(availableParallelism?.() ?? hostCpus()?.length ?? 1) || 1);
61
+ let freeBytes = freemem(), totalBytes = totalmem();
62
+ for (const [limitPath, usagePath] of [
63
+ ['/sys/fs/cgroup/memory.max', '/sys/fs/cgroup/memory.current'],
64
+ ['/sys/fs/cgroup/memory/memory.limit_in_bytes', '/sys/fs/cgroup/memory/memory.usage_in_bytes'],
65
+ ]) {
66
+ try {
67
+ const limit = Number(read(limitPath).trim()), usage = Number(read(usagePath).trim());
68
+ if (Number.isSafeInteger(limit) && limit > 0 && limit < totalBytes && Number.isSafeInteger(usage) && usage >= 0) {
69
+ totalBytes = limit;
70
+ freeBytes = Math.min(freeBytes, Math.max(0, limit - usage));
71
+ break;
72
+ }
73
+ } catch { /* not running inside this cgroup version */ }
74
+ }
75
+ return { cpus, freeBytes, totalBytes };
76
+ }
77
+
78
+ export function planRehearsalShards(version: string, root: string, checkout: string, deps: RehearsalShardPlanDeps = {}): RehearsalShardPlan {
79
+ const reasons: string[] = [];
80
+ let rssRevisionPending = false;
81
+ let resources: RehearsalShardPlan['resources'];
82
+ try { resources = (deps.resources ?? rehearsalHostResources)(); }
83
+ catch (error) {
84
+ resources = { cpus: 0, freeBytes: 0, totalBytes: 0 };
85
+ reasons.push(`host resource probe failed: ${error instanceof Error ? error.message : String(error)}`);
86
+ }
87
+ let gatePlanShards: number | null = null;
88
+ try {
89
+ const board = (deps.board ?? readGateShards)(gateShardsPath(version, root));
90
+ gatePlanShards = board?.version === version && board.shards.length && new Set(board.shards.map(shard => shard.id)).size === board.shards.length ? board.shards.length : null;
91
+ } catch (error) { reasons.push(`persisted gate shard plan unreadable: ${error instanceof Error ? error.message : String(error)}`); }
92
+ let testFiles: number | null = null;
93
+ let measuredFiles = 0;
94
+ let peakFileBytes: number | null = null;
95
+ try {
96
+ const path = join(checkout, LIGHT_RC_ALWAYS_FILE);
97
+ const text = deps.readAlways ? deps.readAlways(path) : existsSync(path) ? readFileSync(path, 'utf8') : undefined;
98
+ if (text === undefined) throw new Error(`${LIGHT_RC_ALWAYS_FILE} missing`);
99
+ const base = (deps.resolveBase ?? ((v, cwd, ledgerRoot) => previousCutBase(v, { cwd, ledgerRoot })))(version, checkout, root);
100
+ const selection = (deps.select ?? ((cwd, opts) => selectGateTestFiles(cwd, opts)))(checkout, { base, alwaysInclude: parseAlwaysIncludeList(text), includeImporterTests: true });
101
+ const files = [...new Set(selection.testFiles)];
102
+ testFiles = files.length;
103
+ try {
104
+ const memory = (deps.fileMemory ?? readFileMemory)(join(checkout, FILE_MEMORY_SOURCE));
105
+ const peaks = files.map(file => memory.get(file)).filter((value): value is number => value !== undefined && Number.isFinite(value) && value > 0);
106
+ measuredFiles = peaks.length;
107
+ if (peaks.length) peakFileBytes = Math.ceil(peaks.reduce((largest, value) => Math.max(largest, value), 0) * 1_000_000);
108
+ if (measuredFiles !== testFiles) reasons.push(`selected file memory not measured: ${testFiles - measuredFiles}/${testFiles}`);
109
+ if (!deps.fileMemory && files.length && !measurementMatchesCheckout(checkout)) {
110
+ if (deps.remoteGate) rssRevisionPending = true;
111
+ else reasons.push('selected file RSS measurement revision not verified against checkout');
112
+ }
113
+ } catch (error) { reasons.push(`selected file memory unavailable: ${error instanceof Error ? error.message : String(error)}`); }
114
+ if (selection.alwaysIncludeMissing?.length) reasons.push(`always-include missing: ${selection.alwaysIncludeMissing.join(', ')}`);
115
+ if (selection.lookupFailed) reasons.push(`importer lookup failed: ${selection.lookupFailed}`);
116
+ if (selection.unrunImporterTotal === undefined) reasons.push('importer coverage not reported');
117
+ if (selection.unrunImporterTotal === null || (selection.unrunImporterTotal ?? 0) > 0) reasons.push(`importer tests not run: ${selection.unrunImporterTotal ?? 'unknown'}`);
118
+ if (selection.routeLookupFailures?.length) reasons.push(`route lookup failed: ${selection.routeLookupFailures.length}`);
119
+ if (selection.unverified?.length) reasons.push(`unverified scope: ${selection.unverified.length}`);
120
+ if (selection.callerTestsOverflow?.length) reasons.push(`caller tests overflow: ${selection.callerTestsOverflow.length}`);
121
+ if (selection.skipTestStep) reasons.push('gate test step skipped');
122
+ if (!testFiles) reasons.push('selected test files empty');
123
+ } catch (error) { reasons.push(`test selection unavailable: ${error instanceof Error ? error.message : String(error)}`); }
124
+ if (gatePlanShards === null) reasons.push('persisted gate shard plan unavailable');
125
+ const cpuValid = Number.isSafeInteger(resources.cpus) && resources.cpus > 0;
126
+ const memoryValid = Number.isFinite(resources.freeBytes) && resources.freeBytes >= 0 && Number.isFinite(resources.totalBytes) && resources.totalBytes > 0 && resources.freeBytes <= resources.totalBytes;
127
+ if (!deps.remoteGate && (!cpuValid || !memoryValid)) reasons.push('host resources unavailable');
128
+ const bytesPerShard = Math.max(BYTES_PER_SHARD, peakFileBytes ?? 0);
129
+ const memoryShards = memoryValid ? Math.max(0, Math.floor((resources.freeBytes - RESERVE_BYTES) / bytesPerShard)) : null;
130
+ const candidate = Math.max(1, Math.min(gatePlanShards ?? LIGHT_RC_DEFAULT_SHARDS, testFiles ?? LIGHT_RC_DEFAULT_SHARDS, deps.remoteGate ? Number.MAX_SAFE_INTEGER : cpuValid ? resources.cpus : LIGHT_RC_DEFAULT_SHARDS));
131
+ if (!deps.remoteGate && peakFileBytes !== null && memoryValid && resources.freeBytes < RESERVE_BYTES + peakFileBytes) {
132
+ reasons.push(`selected file peak exceeds host memory: peak ${peakFileBytes}, free ${resources.freeBytes}, reserve ${RESERVE_BYTES} bytes`);
133
+ }
134
+ // Never treat a 0-slot host as sufficient for one shard. The caller must leave an unrun step retryable.
135
+ const shards = deps.remoteGate || memoryShards === null ? candidate : Math.max(1, Math.min(candidate, memoryShards));
136
+ const capacity = { reserveBytes: RESERVE_BYTES, bytesPerShard, memoryShards, requiredBytes: RESERVE_BYTES + shards * bytesPerShard, measuredFiles, peakFileBytes };
137
+ if (!deps.remoteGate && memoryShards === 0) reasons.push(`host memory insufficient: free ${resources.freeBytes} < required ${capacity.requiredBytes} bytes for 1 shard`);
138
+ // The exported local planner has no local RC caller to validate aggregate workload capacity. A prior board's
139
+ // shard count and individual file peaks cannot prove that hundreds of tests fit one shard.
140
+ if (!deps.remoteGate) reasons.push('local gate shard workload sufficiency not measured');
141
+ // A complete selected-file measurement plus the persisted shard count and a valid host budget is enough to
142
+ // select a candidate. Execution on another host is judged by the RC result, not by a permanent preflight warning.
143
+ const remoteCapacityReason = 'remote gate host resources unmeasured before RC';
144
+ const rssRevisionReason = 'selected file RSS measurement revision not verified before RC';
145
+ return { shards, testFiles, resources, gatePlanShards, capacity,
146
+ ...(deps.remoteGate ? { remoteCapacityPending: true, rssRevisionPending, planningGaps: reasons } : {}),
147
+ unmeasured: reasons.length || deps.remoteGate ? [...reasons, ...(rssRevisionPending ? [rssRevisionReason] : []), ...(deps.remoteGate ? [remoteCapacityReason] : [])].join('; ') : null,
148
+ };
149
+ }
@@ -1,11 +1,14 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { randomUUID } from 'node:crypto';
3
- import { existsSync, linkSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { existsSync, linkSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
4
5
  import { dirname, join } from 'node:path';
5
6
  import { debug } from '../debug/log.js';
6
7
  import { sendOutbound } from '../domains/outbound-alert.js';
7
8
  import { releaseLedgerRoot } from '../instance/resolve.js';
8
- import { runLightRc, type LightRcResult } from './light-rc.js';
9
+ import { isValidGateHost } from '../self-implement/gate-remote.js';
10
+ import { LIGHT_RC_UNKNOWN_HOST, runLightRc, type LightRcResult } from './light-rc.js';
11
+ import { planRehearsalShards, type RehearsalShardPlan, type RehearsalShardPlanDeps } from './rehearsal-shard-plan.js';
9
12
  import { listSchedules, type ReleaseSchedule } from './release-schedule.js';
10
13
 
11
14
  export type StepId = 'rc-7h' | 'rc-150m';
@@ -50,6 +53,9 @@ export interface RehearsalStamp {
50
53
  summary?: string;
51
54
  regressionFiles?: string[];
52
55
  result?: LightRcResult;
56
+ shardPlan?: RehearsalShardPlan;
57
+ leakCheck?: { outcome: 'ok' | 'fail'; sha: string; exitCode: number | null };
58
+ selection?: { shards?: number; remote?: string };
53
59
  notifiedAt?: string;
54
60
  ownerPid?: number;
55
61
  }
@@ -58,14 +64,19 @@ export interface RehearsalOptions {
58
64
  apply?: boolean;
59
65
  checkout?: string;
60
66
  ledgerRoot?: string;
67
+ shards?: number;
68
+ remote?: string;
61
69
  }
62
70
 
63
71
  export interface RehearsalDeps {
64
72
  now?: () => Date;
65
73
  schedules?: (root: string) => ReleaseSchedule[];
66
- lightRc?: (version: string, checkout: string) => Promise<LightRcResult>;
74
+ lightRc?: (version: string, checkout: string, selection: { shards?: number; remote?: string }) => Promise<LightRcResult>;
75
+ shardPlan?: typeof planRehearsalShards;
76
+ shardPlanDeps?: RehearsalShardPlanDeps;
67
77
  notify?: (text: string) => void | boolean | Promise<void | boolean>;
68
78
  git?: (args: string[], cwd: string) => { rc: number | null; stdout: string; stderr?: string };
79
+ leakCheck?: (checkout: string) => { status: number | null };
69
80
  }
70
81
 
71
82
  export type RehearsalTickResult = RehearsalPlan & { applied?: boolean; stamps?: RehearsalStamp[]; notificationFailures?: number };
@@ -86,6 +97,17 @@ function gitResult(git: NonNullable<RehearsalDeps['git']>, args: string[], check
86
97
  return result.stdout.trim();
87
98
  }
88
99
 
100
+ /** Public export checks the pinned rehearsal checkout before any remote RC work. Its output is private and ephemeral. */
101
+ function runRehearsalLeakCheck(checkout: string): { status: number | null } {
102
+ const out = mkdtempSync(join(tmpdir(), 'elanous-rehearsal-export-'));
103
+ try {
104
+ const result = spawnSync('bun', ['scripts/public-export.ts', '--out', join(out, 'export')], {
105
+ cwd: checkout, encoding: 'utf8', timeout: 1_800_000, maxBuffer: 64 * 1024 * 1024,
106
+ });
107
+ return { status: result.status };
108
+ } finally { rmSync(out, { recursive: true, force: true }); }
109
+ }
110
+
89
111
  function oneLine(text: string): string { return text.replace(/\s+/g, ' ').trim(); }
90
112
 
91
113
  function outcomeLine(stamp: RehearsalStamp): string {
@@ -95,7 +117,11 @@ function outcomeLine(stamp: RehearsalStamp): string {
95
117
  if (!stamp.result) return `${head}${stamp.summary ? ` · ${stamp.summary}` : ''}`;
96
118
  const result = stamp.result;
97
119
  const duration = Math.max(0, Math.round((Date.parse(stamp.endedAt!) - Date.parse(stamp.startedAt)) / minute));
98
- return `${head} · 새 회귀 ${result.introduced ?? '못 쟀다'} · 기존 ${result.preexisting ?? '못 쟀다'} · 미분류 ${result.unclassified ?? '못 쟀다'} · ${result.remote ?? 'local'} · ${duration}분${stamp.outcome === 'error' ? ` · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}` : ''}${stamp.regressionFiles?.length ? ` · 파일 ${stamp.regressionFiles.slice(0, 3).join(', ')}` : ''}`;
120
+ const planningGap = stamp.shardPlan?.unmeasured
121
+ || (stamp.selection?.shards !== undefined && result.shards !== stamp.selection.shards)
122
+ || (stamp.selection?.remote !== undefined && result.remote !== stamp.selection.remote);
123
+ const detail = stamp.summary && (stamp.outcome === 'unmeasured' || stamp.outcome === 'error' && planningGap) ? ` · ${stamp.summary}` : '';
124
+ return `${head} · 새 회귀 ${result.introduced ?? '못 쟀다'} · 기존 ${result.preexisting ?? '못 쟀다'} · 미분류 ${result.unclassified ?? '못 쟀다'} · ${result.remote ?? 'local'} · ${duration}분${stamp.outcome === 'error' ? ` · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}` : ''}${stamp.regressionFiles?.length ? ` · 파일 ${stamp.regressionFiles.slice(0, 3).join(', ')}` : ''}${detail}`;
99
125
  }
100
126
 
101
127
  function persistStamp(path: string, stamp: RehearsalStamp): void {
@@ -207,6 +233,12 @@ function interruptStamp(path: string, saved: RehearsalStamp, now: Date): Rehears
207
233
 
208
234
  /** wx claim is permanent per version/step; a crashed run is reported as interrupted without running RC twice. */
209
235
  export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: RehearsalDeps = {}): Promise<RehearsalTickResult> {
236
+ if (opts.shards !== undefined && (!Number.isSafeInteger(opts.shards) || opts.shards < 1)) {
237
+ throw new Error(`release rehearsal tick: invalid --shards count: ${opts.shards}`);
238
+ }
239
+ if (opts.remote !== undefined && !isValidGateHost(opts.remote)) {
240
+ throw new Error(`release rehearsal tick: invalid --remote host: ${opts.remote}`);
241
+ }
210
242
  const root = opts.ledgerRoot ?? releaseLedgerRoot();
211
243
  const now = (deps.now ?? (() => new Date()))();
212
244
  const schedules = (deps.schedules ?? listSchedules)(root);
@@ -289,26 +321,50 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
289
321
  gitResult(git, ['checkout', '-q', '--detach', 'origin/main'], checkout);
290
322
  stamp.sha = gitResult(git, ['rev-parse', 'HEAD'], checkout);
291
323
  if (!stamp.sha) throw new Error('git rev-parse HEAD returned no sha');
324
+ const leak = (deps.leakCheck ?? runRehearsalLeakCheck)(checkout);
325
+ stamp.leakCheck = { outcome: leak.status === 0 ? 'ok' : 'fail', sha: stamp.sha, exitCode: leak.status };
326
+ if (leak.status !== 0) throw new Error(`public export leak-check failed (rc=${leak.status ?? 'spawn'})`);
292
327
  const regressionFiles: string[] = [];
293
- const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, rehearsalTui: true, log: (line) => {
294
- for (const entry of line.split(/\r?\n/)) {
295
- const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
296
- if (file && regressionFiles.length < 3) regressionFiles.push(file);
297
- }
298
- console.error(line);
299
- } }, { cwd })))(plan.version, checkout);
328
+ const shardPlan = opts.shards === undefined ? (deps.shardPlan ?? planRehearsalShards)(plan.version, root, checkout, { ...deps.shardPlanDeps, remoteGate: true }) : undefined;
329
+ if (shardPlan) stamp.shardPlan = shardPlan;
330
+ const selection = { shards: opts.shards ?? shardPlan?.shards, remote: opts.remote };
331
+ stamp.selection = selection;
332
+ const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, ...selection, rehearsalTui: true, log: (line) => {
333
+ for (const entry of line.split(/\r?\n/)) {
334
+ const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
335
+ if (file && regressionFiles.length < 3) regressionFiles.push(file);
336
+ }
337
+ console.error(line);
338
+ } }, { cwd })))(plan.version, checkout, selection);
300
339
  stamp.result = result;
301
340
  if (regressionFiles.length) stamp.regressionFiles = regressionFiles;
302
- stamp.outcome = result.introduced === null || result.unclassified === null ? 'unmeasured'
303
- : result.introduced > 0 ? 'regression'
304
- : result.unclassified > 0 ? 'unmeasured'
305
- : !result.ok || result.gateExitCode !== 0 ? 'error' : 'ok';
306
- stamp.summary = oneLine(`introduced ${result.introduced} · preexisting ${result.preexisting ?? 'unmeasured'} · unclassified ${result.unclassified} · ${result.remote ?? 'local'} · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}`);
341
+ const shardMismatch = selection.shards !== undefined && result.shards !== selection.shards
342
+ ? `selected shards ${selection.shards} but RC reported ${result.shards}` : null;
343
+ const remoteMismatch = opts.remote && result.remote !== opts.remote
344
+ ? `requested remote ${opts.remote} but RC reported ${result.remote ?? 'local'}` : null;
345
+ if (shardPlan?.remoteCapacityPending && result.remote && result.remote !== LIGHT_RC_UNKNOWN_HOST
346
+ && !remoteMismatch && result.unmeasured === null
347
+ && result.introduced !== null && result.unclassified === 0 && result.ok
348
+ && result.gateExitCode === 0 && !shardMismatch) {
349
+ // Only the completed RC can validate capacity of the actual remote host. Keep independent
350
+ // selection/RSS gaps; clear just the provisional remote-capacity gap.
351
+ stamp.shardPlan = { ...shardPlan, remoteCapacityPending: false, rssRevisionPending: false,
352
+ remoteCapacityVerifiedBy: result.remote,
353
+ unmeasured: shardPlan.planningGaps?.length ? shardPlan.planningGaps.join('; ') : null };
354
+ }
355
+ const planningGap = stamp.shardPlan?.unmeasured || shardMismatch || remoteMismatch;
356
+ const missingEvidence = result.introduced === null || result.unclassified === null
357
+ || result.unmeasured !== null || result.unclassified > 0 || !!planningGap;
358
+ stamp.outcome = result.introduced !== null && result.introduced > 0 ? missingEvidence ? 'unmeasured' : 'regression'
359
+ : result.introduced === null || result.unclassified === null || result.unmeasured !== null || result.unclassified > 0 ? 'unmeasured'
360
+ : result.unmeasured === null && (!result.ok || result.gateExitCode !== 0) ? 'error'
361
+ : planningGap ? 'unmeasured' : 'ok';
362
+ stamp.summary = oneLine(`introduced ${result.introduced} · preexisting ${result.preexisting ?? 'unmeasured'} · unclassified ${result.unclassified} · ${result.remote ?? 'local'} · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}${result.unmeasured !== null ? ` · unmeasured: ${result.unmeasured || 'RC reason empty'}` : ''}${stamp.shardPlan?.unmeasured ? ` · unmeasured: ${stamp.shardPlan.unmeasured}` : ''}${shardMismatch ? ` · unmeasured: ${shardMismatch}` : ''}${remoteMismatch ? ` · unmeasured: ${remoteMismatch}` : ''}`);
307
363
  }
308
364
  }
309
365
  } catch (error) {
310
366
  stamp.outcome = 'error';
311
- stamp.summary = oneLine(String(error instanceof Error ? error.message : error).split(/\r?\n/, 1)[0] ?? 'unknown error');
367
+ stamp.summary = oneLine(`${String(error instanceof Error ? error.message : error).split(/\r?\n/, 1)[0] ?? 'unknown error'}${stamp.shardPlan?.unmeasured ? ` · unmeasured: ${stamp.shardPlan.unmeasured}` : ''}`);
312
368
  }
313
369
  await finish(path, stamp);
314
370
  }
package/src/repl/index.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  import {
31
31
  resolveSessionId,
32
32
  loadSession,
33
+ listSessions,
33
34
  setActiveSessionId,
34
35
  getActiveSessionId,
35
36
  } from '../session/index.js';
@@ -41,6 +42,7 @@ import {
41
42
  } from '../user-config.js';
42
43
  import { setAmbientSessionId, debug } from '../debug/log.js';
43
44
  import { decideSigintAction } from './sigint.js';
45
+ import { decideSessionStart, observeSessionStart } from '../session/session-start.js';
44
46
  import { buildReplayTurnsFromSession } from './replay.js';
45
47
  import type { LLMToolSpec, ContentBlock } from '../llm.js';
46
48
  import { inspectActiveProvider } from '../provider-summary.js';
@@ -58,6 +60,8 @@ export interface ReplOpts {
58
60
  initialSessionId: string | undefined;
59
61
  /** Force a fresh session even if active marker exists. */
60
62
  forceNew: boolean;
63
+ /** `--continue`/`--resume` — 활성 세션 이어하기(명시). 대표 #73: 기본은 새 세션. */
64
+ continueActive?: boolean;
61
65
  /** Enable the tool loop (Read/Grep/Bash/...). Default true — REPL
62
66
  * is the agent surface; users opt out with --no-tools. */
63
67
  enableTools: boolean;
@@ -445,11 +449,25 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
445
449
  return 1;
446
450
  }
447
451
  initialId = id;
448
- } else if (!opts.forceNew) {
449
- initialId = getActiveSessionId() ?? undefined;
450
452
  }
453
+ const startDecision = decideSessionStart({
454
+ ...(initialId ? { explicitSessionId: initialId } : {}),
455
+ continueActive: opts.continueActive === true,
456
+ forceNew: opts.forceNew,
457
+ activeSessionId: () => getActiveSessionId(),
458
+ // TUI-H8-FOLLOW ① — 활성 표지가 사라진 세션이면 최신 세션으로.
459
+ sessionExists: (id) => loadSession(id) !== null,
460
+ latestSessionId: () => listSessions({ limit: 1 })[0]?.id ?? null,
461
+ });
462
+ initialId = startDecision.sessionIdHint;
451
463
  const session = ensureCliSession(cfg, initialId);
452
464
  setActiveSessionId(session.id);
465
+ observeSessionStart({
466
+ surface: 'repl',
467
+ origin: initialId && session.id === initialId ? startDecision.origin : 'new',
468
+ reason: initialId && session.id !== initialId ? 'resume-target-missing' : startDecision.reason,
469
+ sessionId: session.id,
470
+ });
453
471
  setAmbientSessionId(session.id);
454
472
  if (!opts.jsonOutput && (!initialId || session.id !== initialId)) {
455
473
  try {
@@ -0,0 +1,282 @@
1
+ // ── Seat knowhow packs — RFC-seat-knowhow-packs-adaptive-knowledge-2026-10-11.md §A ──
2
+ //
3
+ // Loader for `내부 문서 `KNOWHOW`` v2 items plus the role charter
4
+ // `내부 문서 `<자리>``. Replaces the two duplicate role-file reads inside
5
+ // seat-loop.ts (gatherSeatInputs + inquire) — one loader, no 4,000-char cut
6
+ // on the charter, one overall budget cap instead.
7
+ //
8
+ // Injection rules (§A3 ⊕ review must-fix 1):
9
+ // «사실» = status active ⊕ last verification «참» ⊕ within half-life
10
+ // «참고(검증 안 됨)» = unproven / unverifiable(못잼) / expired half-life
11
+ // dropped = any status outside active/unproven/unverifiable,
12
+ // last verification «거짓»/future/invalid date,
13
+ // 상태 미선언 · 검증 미선언 — a card is injected
14
+ // only with an explicit 상태 AND an explicit 검증 line;
15
+ // a missing 상태 is never assumed to be `active`.
16
+ //
17
+ // Half-life (§A1): fact 14 · warning 30 · heuristic 90 · playbook 60 days,
18
+ // case unlimited; kind defaults to fact when a card does not declare one.
19
+
20
+ import { readFileSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { debug } from '../debug/log.js';
23
+
24
+ export type KnowhowKind = 'fact' | 'warning' | 'heuristic' | 'playbook' | 'case';
25
+
26
+ export const KNOWHOW_HALF_LIFE_DAYS: Record<KnowhowKind, number> = {
27
+ fact: 14,
28
+ warning: 30,
29
+ heuristic: 90,
30
+ playbook: 60,
31
+ case: Number.POSITIVE_INFINITY,
32
+ };
33
+
34
+ /** One overall budget cap for the whole injected pack (RFC §A3 — value
35
+ * unspecified in the ask; 32,000 chars adopted as the documented value for
36
+ * this slice, replacing the old per-chunk 4,000-char cuts).
37
+ *
38
+ * Budget policy (review must-fix 3) — whole items only, `text.slice` is never
39
+ * used: the charter, each block header, and each card enter the pack whole or
40
+ * not at all.
41
+ * 1. The charter is always kept whole and outranks every card.
42
+ * 2. Cards are appended whole in top-k order while the running total stays
43
+ * within this cap; a card that would exceed it is skipped (a later,
44
+ * smaller card may still fit).
45
+ * 3. A charter that alone exceeds the cap is still injected whole and both
46
+ * card blocks are dropped entirely — the seat keeps its charter; slicing
47
+ * the charter mid-way is exactly what this policy abolishes. */
48
+ export const SEAT_PACK_TOTAL_BUDGET_CHARS = 32_000;
49
+ export const DEFAULT_TOP_K = 8;
50
+
51
+ export interface KnowhowItem {
52
+ kind: KnowhowKind;
53
+ /** Declared 상태 — '' when the card states none (never assumed active). */
54
+ status: string;
55
+ verifiedAt: Date | null;
56
+ /** true = 참 · false = 거짓 · null = 못잼/unproven */
57
+ verified: boolean | null;
58
+ text: string;
59
+ }
60
+
61
+ export interface SeatPack {
62
+ charter: string;
63
+ /** Card texts actually injected into `text` — never a superset of it. */
64
+ facts: string[];
65
+ refs: string[];
66
+ /** Cards refused by classification (contradicted·stale·superseded·거짓·
67
+ * 상태/검증 미선언). Cards skipped only by the budget are not counted. */
68
+ dropped: number;
69
+ text: string;
70
+ }
71
+
72
+ export interface SeatPackDeps {
73
+ repo?: string;
74
+ read?: (path: string) => string;
75
+ now?: () => Date;
76
+ topK?: number;
77
+ }
78
+
79
+ // 참/거짓 뒤 경계는 \b 대신 명시적 뒷자리 제한 — \w 가 ASCII 한정이라
80
+ // 참(한글) 뒤에서는 \b 가 경계로 안 센다(실측: verified 가 null 로 흘렀다).
81
+ const VERIFIED_TRUE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*참(?![^\s(·])/;
82
+ const VERIFIED_FALSE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*거짓(?![^\s(·])/;
83
+ const VERIFIED_UNVERIFIABLE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*못잼/;
84
+ const FIELD_RE = /^-([^:]+):\s*(.*)$/;
85
+
86
+ function calendarDate(isoDay: string): Date | null {
87
+ const date = new Date(`${isoDay}T00:00:00Z`);
88
+ return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === isoDay ? date : null;
89
+ }
90
+
91
+ export function parseKnowhowItems(body: string, seat: string): KnowhowItem[] {
92
+ const headerRe = new RegExp(`^##\\s+K-${seat.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}-\\d+`, 'i');
93
+ const items: KnowhowItem[] = [];
94
+ // First section before any card header is the document preamble — drop it.
95
+ const sections = body.split(/^##\s+/m);
96
+ for (const section of sections) {
97
+ const lines = section.split('\n');
98
+ const header = lines[0] ?? '';
99
+ if (!headerRe.test(`## ${header}`)) continue;
100
+ const rest = lines.slice(1).join('\n');
101
+ const fields: Record<string, string> = {};
102
+ let kind: KnowhowKind | null = null;
103
+ let status = '';
104
+ let verifiedAt: Date | null = null;
105
+ let verified: boolean | null = null;
106
+ for (const line of rest.split('\n')) {
107
+ const m = line.match(FIELD_RE);
108
+ if (m) {
109
+ const label = m[1].trim();
110
+ const value = m[2].trim();
111
+ fields[label] = value;
112
+ if (label === '종류' && value in KNOWHOW_HALF_LIFE_DAYS) {
113
+ kind = value as KnowhowKind;
114
+ } else if (label === '상태') {
115
+ status = value;
116
+ } else if (label === '검증') {
117
+ // A later verification line supersedes the earlier one even when
118
+ // malformed; otherwise an old «참» survives a failed new check.
119
+ verified = null;
120
+ verifiedAt = null;
121
+ const t = value.match(VERIFIED_TRUE_RE);
122
+ const f = value.match(VERIFIED_FALSE_RE);
123
+ const u = value.match(VERIFIED_UNVERIFIABLE_RE);
124
+ if (t) {
125
+ verified = true;
126
+ verifiedAt = calendarDate(t[1]);
127
+ } else if (f) {
128
+ verified = false;
129
+ verifiedAt = calendarDate(f[1]);
130
+ } else if (u) {
131
+ verified = null;
132
+ verifiedAt = calendarDate(u[1]);
133
+ }
134
+ }
135
+ }
136
+ }
137
+ // Inline `상태:`/`종류:` inside other fields (e.g. the 출처 line) also count.
138
+ for (const value of Object.values(fields)) {
139
+ if (!status) {
140
+ const s = value.match(/(?:^|·\s*|[·,,;|\s])상태:\s*(\S+)/);
141
+ if (s) status = s[1];
142
+ }
143
+ if (!kind) {
144
+ const k = value.match(/(?:^|·\s*|[·,,;|\s])종류:\s*(\S+)/);
145
+ if (k && k[1] in KNOWHOW_HALF_LIFE_DAYS) kind = k[1] as KnowhowKind;
146
+ }
147
+ }
148
+ items.push({
149
+ kind: kind ?? 'fact',
150
+ // Missing 상태 stays '' — the classifier refuses to inject it; the
151
+ // parser must not default a status-less card to `active` (must-fix 1).
152
+ status,
153
+ verifiedAt,
154
+ verified,
155
+ text: `## ${header}\n${rest}`.trim(),
156
+ });
157
+ }
158
+ return items;
159
+ }
160
+
161
+ function withinHalfLife(item: KnowhowItem, now: Date): boolean {
162
+ if (!item.verifiedAt) return false;
163
+ const ageMs = now.getTime() - item.verifiedAt.getTime();
164
+ if (!Number.isFinite(ageMs) || ageMs < 0) return false;
165
+ const days = KNOWHOW_HALF_LIFE_DAYS[item.kind];
166
+ if (!Number.isFinite(days)) return true;
167
+ return ageMs <= days * 24 * 60 * 60 * 1000;
168
+ }
169
+
170
+ /** «사실» vs «참고(검증 안 됨)» vs dropped(contradicted·stale·superseded·최근
171
+ * 검증 거짓·상태/검증 미선언). Only active/unproven/unverifiable are admitted;
172
+ * a future or invalid verification date is rejected. A card is injected only when it declares an
173
+ * explicit 상태 AND an explicit 검증 line; a card whose most recent
174
+ * verification is «거짓» is contradicted — dropped, never filed as
175
+ * «검증 안 됨» (review must-fix 1). */
176
+ export function splitKnowhow(
177
+ items: KnowhowItem[],
178
+ now: Date,
179
+ ): { facts: KnowhowItem[]; refs: KnowhowItem[]; dropped: number } {
180
+ const facts: KnowhowItem[] = [];
181
+ const refs: KnowhowItem[] = [];
182
+ let dropped = 0;
183
+ for (const item of items) {
184
+ const allowedStatus = item.status === 'active' || item.status === 'unproven' || item.status === 'unverifiable';
185
+ const verifiedAtMs = item.verifiedAt?.getTime();
186
+ const lacksExplicitConditions = !Number.isFinite(verifiedAtMs) || item.verified === false
187
+ || verifiedAtMs! > now.getTime();
188
+ if (!allowedStatus || lacksExplicitConditions) {
189
+ dropped += 1;
190
+ continue;
191
+ }
192
+ if (item.verified === true && item.status === 'active' && withinHalfLife(item, now)) {
193
+ facts.push(item);
194
+ } else {
195
+ refs.push(item);
196
+ }
197
+ }
198
+ return { facts, refs, dropped };
199
+ }
200
+
201
+ function tokenize(text: string): string[] {
202
+ return text
203
+ .toLowerCase()
204
+ .split(/[^\p{L}\p{N}_]+/u)
205
+ .filter((t) => t.length > 0);
206
+ }
207
+
208
+ /** Top-k by word overlap with the query (default k = 8). Ties keep pack order. */
209
+ export function selectTopK(items: KnowhowItem[], query: string, k: number = DEFAULT_TOP_K): KnowhowItem[] {
210
+ const tokens = new Set(tokenize(query));
211
+ const scored = items.map((item, index) => {
212
+ const itemTokens = new Set(tokenize(item.text));
213
+ let score = 0;
214
+ for (const token of itemTokens) if (tokens.has(token)) score += 1;
215
+ return { item, score, index };
216
+ });
217
+ scored.sort((a, b) => b.score - a.score || a.index - b.index);
218
+ return scored.slice(0, Math.max(0, k)).map((s) => s.item);
219
+ }
220
+
221
+ /** Assemble the pack under SEAT_PACK_TOTAL_BUDGET_CHARS at whole-item
222
+ * granularity — see the policy on the constant. The `facts`/`refs` arrays in
223
+ * the result carry exactly the cards that made it into `text`. */
224
+ function assemblePack(
225
+ charter: string,
226
+ rankedItems: KnowhowItem[],
227
+ factSet: ReadonlySet<KnowhowItem>,
228
+ ): { text: string; facts: string[]; refs: string[] } {
229
+ const SEP = '\n\n';
230
+ let used = charter.length;
231
+ const facts: string[] = [];
232
+ const refs: string[] = [];
233
+ // Budget in query rank order; rendering can still group facts before refs.
234
+ for (const item of rankedItems) {
235
+ const isFact = factSet.has(item);
236
+ const out = isFact ? facts : refs;
237
+ const header = isFact ? '### 사실 (검증된 노하우)' : '### 참고 (검증 안 됨)';
238
+ const cost = out.length === 0
239
+ ? (used > 0 ? SEP.length : 0) + header.length + SEP.length + item.text.length
240
+ : SEP.length + item.text.length;
241
+ if (used + cost > SEAT_PACK_TOTAL_BUDGET_CHARS) continue;
242
+ out.push(item.text);
243
+ used += cost;
244
+ }
245
+ let text = charter;
246
+ if (facts.length > 0) text += `${text ? SEP : ''}### 사실 (검증된 노하우)${SEP}${facts.join(SEP)}`;
247
+ if (refs.length > 0) text += `${text ? SEP : ''}### 참고 (검증 안 됨)${SEP}${refs.join(SEP)}`;
248
+ return { text, facts, refs };
249
+ }
250
+
251
+ export function loadSeatPack(seat: string, query = '', deps: SeatPackDeps = {}): SeatPack {
252
+ const repo = deps.repo ?? process.cwd();
253
+ const read = deps.read ?? ((path: string) => readFileSync(path, 'utf8'));
254
+ const now = deps.now ?? (() => new Date());
255
+ const charter = read(join(repo, 'docs', 'roles', `${seat}.md`)).trim();
256
+ const knowhowPath = join(repo, 'docs', 'roles', seat, 'KNOWHOW.md');
257
+ // NOTE: presence is decided by reading through `deps.read`, not existsSync —
258
+ // tests mount a virtual reader; a disk probe would report the virtual path
259
+ // missing and silently drop the whole KNOWHOW pack (observed: facts=0).
260
+ let knowhowBody = '';
261
+ try {
262
+ knowhowBody = read(knowhowPath);
263
+ } catch {
264
+ knowhowBody = '';
265
+ }
266
+ const items = parseKnowhowItems(knowhowBody, seat);
267
+ const { facts, refs, dropped } = splitKnowhow(items, now());
268
+ const topK = deps.topK ?? DEFAULT_TOP_K;
269
+ // One top-k pass over the whole candidate pool (facts ⊕ refs), then the
270
+ // winners are split back into their blocks in score order — applying k per
271
+ // block would inject up to 2k cards (review must-fix 2).
272
+ const selected = selectTopK([...facts, ...refs], query, topK);
273
+ const factSet = new Set(facts);
274
+ const pack = assemblePack(charter, selected, factSet);
275
+ debug.log('seat.loop', 'pack-loaded', {
276
+ seat,
277
+ facts: pack.facts.length,
278
+ refs: pack.refs.length,
279
+ dropped,
280
+ });
281
+ return { charter, facts: pack.facts, refs: pack.refs, dropped, text: pack.text };
282
+ }