elanous 0.2.28 → 0.2.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (818) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +23 -0
  15. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +41 -0
  18. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 2213.2ccbada92c33ea0f.js} +3 -3
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2940-619bfd8ef337c611.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{3143.257997a5f1ed79df.js → 3902.e1e71aaac850a045.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/{1146.80d15ea7c6e6ee95.js → 4111.2bfedbb233ad206b.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{9938.b23e4d4dfa0114cd.js → 4999.c064a4000c2a9e94.js} +2 -2
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{1157.f08bf2b70915e176.js → 5304.04d24756f242a094.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{7752.5cbdd0b433c54af9.js → 5307.60f2209e809bd627.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{3309.364573ceedbdfd5f.js → 6323.8672b4817a306928.js} +1 -1
  74. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 6433.fc573af22bbc9ab7.js} +4 -4
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{949.1e7d45ccb71580aa.js → 6517.4147878ac06d584d.js} +2 -2
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/{2528.3868070ef1be69f9.js → 6767.ea607cf0c20a25af.js} +2 -2
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  93. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  94. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 7862.30a8d6482bb238eb.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2697.76ca2ac3efef6f3b.js → 8018.a32663f04a6fc5f9.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  109. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 9279-d28c5b7754d010ae.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9398-6aed28f0a96d0d6f.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/997ce8a5-2ad501927003b41b.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 9989.3694300e5f000b14.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-fa46d4588e8442c2.js → page-2ebb8fd59b9461f9.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/{page-ced0bcfc6542b3fc.js → page-349f2752d8cd37ad.js} +1 -1
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-cb249e81ed339318.js → page-0a07363b130182a1.js} +1 -1
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{e87d89b9.2e71c0ae475d28a1.js → e5012ffe.f727e23c231f4342.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{e117f801.e92bf10242653497.js → ebc7d829.264a0bcb6c750b50.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  183. package/apps/pwa/out/_next/static/css/{72becfd42807b50d.css → 3f5fc6f96e2cf7b2.css} +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/bin/elanous.mjs +7 -3
  278. package/graphs/context/nightly-condense.yaml +1 -0
  279. package/graphs/intake/intake-daily.yaml +8 -1
  280. package/graphs/intake/recipes.yaml +5 -0
  281. package/graphs/lecture/lecture-note.yaml +2 -2
  282. package/graphs/ops/harness-gc.yaml +1 -0
  283. package/graphs/release/recipes.yaml +3 -0
  284. package/graphs/release/release-loop.yaml +15 -7
  285. package/graphs/units/recipes.yaml +3 -0
  286. package/graphs/units/release-gate-recheck.yaml +15 -0
  287. package/package.json +2 -1
  288. package/plugins/agent-team/agents/research.md +1 -0
  289. package/scripts/check-native-tool-wiring.ts +3 -2
  290. package/scripts/ci-android-unit-tests.ts +16 -0
  291. package/scripts/ci-typecheck-changed.ts +40 -11
  292. package/scripts/coord-channel-watch.sh +45 -19
  293. package/scripts/coord-role-pack.ts +222 -0
  294. package/scripts/cron-run.ts +96 -3
  295. package/scripts/detect-test-interference.ts +38 -5
  296. package/scripts/gate-pr-cache.ts +65 -0
  297. package/scripts/gh-surface/capture.ts +126 -0
  298. package/scripts/gh-surface/gh +40 -0
  299. package/scripts/import-graph-scc.ts +38 -0
  300. package/scripts/install.ps1 +19 -0
  301. package/scripts/intake-social.ts +181 -0
  302. package/scripts/lecture-note/node.ts +71 -4
  303. package/scripts/lib/android-toolchain.ts +32 -0
  304. package/scripts/lib/deterministic-env.ts +62 -0
  305. package/scripts/lib/gate-test-env.ts +19 -0
  306. package/scripts/lib/morning-report-options.ts +41 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  310. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  311. package/scripts/release-loop/cut-branch.ts +4 -3
  312. package/scripts/release-loop/export-check-node.ts +0 -1
  313. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  314. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  315. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  316. package/scripts/release-loop/gate-batch-safe.ts +23 -0
  317. package/scripts/release-loop/gate-closure.ts +12 -8
  318. package/scripts/release-loop/gate-diff.ts +1 -1
  319. package/scripts/release-loop/gate-history.ts +422 -0
  320. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  321. package/scripts/release-loop/gate-node.ts +806 -94
  322. package/scripts/release-loop/gate-partial.ts +106 -9
  323. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  324. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  325. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  326. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  327. package/scripts/release-loop/gate-triage-node.ts +190 -0
  328. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  329. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  330. package/scripts/release-loop/import-graph-scc.ts +215 -0
  331. package/scripts/release-loop/node-verdict.ts +2 -0
  332. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  333. package/scripts/release-loop/resume-release.ts +33 -4
  334. package/scripts/release-loop/resume.ts +13 -5
  335. package/scripts/release-loop/spawn-lane.ts +51 -0
  336. package/scripts/release-loop/tui-node-checks.ts +23 -0
  337. package/scripts/release-loop/tui-sim-node.ts +3 -2
  338. package/scripts/release-loop/unattended-release.ts +16 -0
  339. package/scripts/release-loop/version-node.ts +62 -4
  340. package/scripts/test-deterministic.ts +46 -73
  341. package/scripts/train-reach-grouping.ts +48 -0
  342. package/scripts/tsc-incremental-cache.ts +86 -0
  343. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  344. package/scripts/tsc-main-safety-net.ts +2 -2
  345. package/scripts/usage-rollup.ts +11 -3
  346. package/src/acp/client.ts +4 -1
  347. package/src/acp/core-turn-bridge.ts +145 -24
  348. package/src/acp/elanous-extensions.ts +2 -0
  349. package/src/acp/server.ts +2 -0
  350. package/src/ad-pipeline/run.ts +4 -2
  351. package/src/agent/ref-grounding.ts +18 -0
  352. package/src/agent/runner.ts +169 -3
  353. package/src/agent/subagent-callable.ts +3 -2
  354. package/src/agent-mission/review-loop.ts +6 -3
  355. package/src/agent-substrate/acp-implementer.ts +14 -2
  356. package/src/agent-substrate/pr-reviewer.ts +41 -21
  357. package/src/agent-substrate/self-review-cli.ts +30 -4
  358. package/src/autopilot/pr-manager.ts +62 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/budget/pty-usage-reemit.ts +7 -0
  361. package/src/budget/run-usage-rollup.ts +9 -0
  362. package/src/budget/usage-daily-store.ts +98 -0
  363. package/src/capture/tui-self-report.ts +37 -4
  364. package/src/chat/chat-cli.ts +10 -2
  365. package/src/chat/index.ts +107 -20
  366. package/src/chat/input-control-key.ts +5 -3
  367. package/src/chat/pickers/modal-runtime.ts +1 -0
  368. package/src/chat/pickers/modals.ts +3 -1
  369. package/src/chat/tool-interrupt-behavior.ts +38 -0
  370. package/src/chat/tool-render/dispatch.ts +5 -1
  371. package/src/chat/turn-typeahead.ts +191 -29
  372. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  373. package/src/cli/agent-cli.ts +41 -13
  374. package/src/cli/config-audit.ts +123 -0
  375. package/src/cli/dashboard-name-flag.ts +48 -0
  376. package/src/cli/decisions-cli.ts +80 -6
  377. package/src/cli/doctor-cli.ts +80 -0
  378. package/src/cli/log-event-names.ts +19 -0
  379. package/src/cli/mcp-login.ts +21 -5
  380. package/src/cli/msg-cli.ts +133 -2
  381. package/src/cli/pr-cli.ts +546 -112
  382. package/src/cli/pr-land-heavy-remote.ts +233 -0
  383. package/src/cli/pr-land-overlap-evidence.ts +167 -14
  384. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  387. package/src/cli/pty-takeover-cli.ts +125 -16
  388. package/src/cli/release-cli.ts +122 -14
  389. package/src/cli/remote-resolve.ts +2 -1
  390. package/src/cli/seat-cli.ts +164 -19
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/tasks-cli.ts +105 -21
  393. package/src/cli/usage-cli.ts +146 -12
  394. package/src/cli/usage-daily-cli.ts +84 -0
  395. package/src/context-bus/context-first.ts +13 -0
  396. package/src/context-bus/context-now.ts +95 -7
  397. package/src/context-bus/ops-events.ts +75 -0
  398. package/src/control-plane/lease-holder.ts +12 -8
  399. package/src/control-plane/ledger.ts +163 -4
  400. package/src/control-plane/server.ts +91 -11
  401. package/src/core-turn/auth-rejected-notice.ts +41 -0
  402. package/src/core-turn/run-core-turn.ts +14 -2
  403. package/src/core-turn/run-goal-loop.ts +239 -4
  404. package/src/core-turn/seat-turn-cap.ts +79 -0
  405. package/src/core-turn/short-question.ts +78 -13
  406. package/src/core-turn/types.ts +10 -0
  407. package/src/dashboard/acp-active-model.ts +40 -0
  408. package/src/dashboard/acp-boot.ts +3 -0
  409. package/src/dashboard/auto-compact-runtime.ts +2 -0
  410. package/src/dashboard/boot-banner.ts +80 -0
  411. package/src/dashboard/dashboard-status-lines.ts +11 -0
  412. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  413. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  414. package/src/dashboard/goal-loop-thinking.ts +16 -0
  415. package/src/dashboard/hitl-boot.ts +9 -4
  416. package/src/dashboard/index.ts +448 -998
  417. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  418. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  419. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  420. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +176 -4
  421. package/src/dashboard/input/chat-main-session.ts +14 -3
  422. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  423. package/src/dashboard/input/chat-main-turn.ts +14 -4
  424. package/src/dashboard/input/compact-prepass-recovery.ts +130 -0
  425. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  426. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  427. package/src/dashboard/input/external-input-host.ts +71 -0
  428. package/src/dashboard/input/internal-turn.ts +261 -0
  429. package/src/dashboard/input/log-fold-binding.ts +18 -0
  430. package/src/dashboard/input/mouse-wiring.ts +17 -4
  431. package/src/dashboard/input/seat-autowake.ts +318 -0
  432. package/src/dashboard/input/turn-steer-bridge.ts +164 -0
  433. package/src/dashboard/log-click-runtime.ts +5 -3
  434. package/src/dashboard/loop-scheduler.ts +72 -0
  435. package/src/dashboard/running-build-status.ts +74 -0
  436. package/src/dashboard/seat-boot-preamble.ts +131 -0
  437. package/src/dashboard/seat-local-instructions.ts +305 -0
  438. package/src/dashboard/skill-runtime.ts +2 -0
  439. package/src/dashboard/slash-runtime/dashboard-handlers.ts +220 -1203
  440. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  441. package/src/dashboard/slash-runtime/index.ts +13 -0
  442. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  443. package/src/dashboard/term-slash-runtime.ts +15 -0
  444. package/src/dashboard/turn-busy-teardown.ts +50 -0
  445. package/src/dashboard/turn-preamble.ts +30 -2
  446. package/src/dashboard/turn-session-layers.ts +176 -0
  447. package/src/dashboard/turn-stream-formatter.ts +14 -6
  448. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  449. package/src/decisions/decision-ledger.ts +45 -4
  450. package/src/discord-self-message.ts +4 -4
  451. package/src/domains/release-tool.ts +26 -10
  452. package/src/domains/surface-events.ts +4 -1
  453. package/src/domains/watch-default-scheduler.ts +8 -9
  454. package/src/field-note/transcribe.ts +17 -0
  455. package/src/fold-stack.ts +24 -1
  456. package/src/git-fs/dirty.ts +32 -4
  457. package/src/git-fs/index.ts +43 -1
  458. package/src/github/remote-call.ts +81 -0
  459. package/src/goals/registry.ts +46 -6
  460. package/src/goals/types.ts +7 -1
  461. package/src/graph-runner/runner.ts +2 -0
  462. package/src/grok/credential.ts +26 -0
  463. package/src/harness/harness-clean.ts +2 -1
  464. package/src/harness/harness-cli-command.ts +52 -5
  465. package/src/harness/harness-gc.ts +34 -6
  466. package/src/harness/harness-incidents.ts +57 -20
  467. package/src/harness/harness-pod-dispatch.ts +87 -10
  468. package/src/harness/harness-queue.ts +53 -4
  469. package/src/harness/harness-stop.ts +4 -3
  470. package/src/harness/harness-substrate-default.ts +78 -7
  471. package/src/harness/harness-worktree-auto.ts +2 -1
  472. package/src/harness/harness-worktrees.ts +3 -2
  473. package/src/hooks/dispatch.ts +2 -1
  474. package/src/index.ts +166 -26
  475. package/src/input/external-input-queue.ts +251 -0
  476. package/src/intake-plane/slash.ts +14 -3
  477. package/src/interactive-terminal-modal.ts +13 -0
  478. package/src/keybindings.ts +4 -1
  479. package/src/llm/route-decision.ts +25 -0
  480. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  481. package/src/llm-stream-retry-display.ts +59 -0
  482. package/src/llm.ts +391 -74
  483. package/src/log-entry.ts +3 -3
  484. package/src/log-pane/search.ts +29 -4
  485. package/src/loops/agent-reply.ts +256 -0
  486. package/src/loops/budget.ts +37 -7
  487. package/src/loops/consensus.ts +348 -0
  488. package/src/loops/loop-cli.ts +3 -2
  489. package/src/loops/msg-address.ts +57 -0
  490. package/src/loops/msg-wake.ts +484 -0
  491. package/src/loops/observe.ts +19 -3
  492. package/src/loops/orchestrator/inbox.ts +60 -3
  493. package/src/loops/orchestrator/tick.ts +80 -6
  494. package/src/loops/orchestrator/traffic.ts +64 -1
  495. package/src/loops/registry.ts +72 -4
  496. package/src/market/signed-index.ts +14 -0
  497. package/src/mcp/mcp-oauth.ts +54 -5
  498. package/src/memory.ts +20 -5
  499. package/src/models/prompts.ts +28 -0
  500. package/src/msg/msg-sse-client.ts +223 -0
  501. package/src/msg/msg-store.ts +86 -2
  502. package/src/mss/logging/log-store.ts +225 -1
  503. package/src/native-tool-catalog.ts +125 -0
  504. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  505. package/src/nexus/api/http-server.ts +59 -15
  506. package/src/nexus/api/loop-resources.ts +19 -3
  507. package/src/nexus/api/ops-api.ts +13 -0
  508. package/src/nexus/api/project-autopsy.ts +127 -0
  509. package/src/nexus/api/terminals.ts +3 -0
  510. package/src/nexus/api/workflow-approvals.ts +2 -0
  511. package/src/nexus/daemon-thin-inventory.md +37 -0
  512. package/src/nexus/index.ts +70 -0
  513. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  514. package/src/nexus/state/state.ts +1 -0
  515. package/src/oauth/codex-account-store.ts +15 -3
  516. package/src/oauth/codex-billing-route.ts +31 -0
  517. package/src/oauth/store.ts +32 -7
  518. package/src/onboarding/first-run.ts +28 -3
  519. package/src/ops/overview-cache.ts +16 -4
  520. package/src/ops/overview-collect.ts +19 -2
  521. package/src/ops/resources.ts +82 -0
  522. package/src/panes/log-pane.ts +67 -8
  523. package/src/persona/presets.ts +44 -0
  524. package/src/plugins/maker/connector-maker.ts +41 -0
  525. package/src/plugins/maker/skill-maker.ts +42 -0
  526. package/src/plugins/maker/wizard-generate.ts +6 -4
  527. package/src/pr-tool/census.ts +288 -0
  528. package/src/preview/terminal.ts +14 -1
  529. package/src/prompt-cache/types.ts +2 -0
  530. package/src/prompt-enhance/enhance.ts +24 -8
  531. package/src/prompt-library/chat-conciseness.ts +13 -0
  532. package/src/prompt-library/universal-preamble.ts +283 -61
  533. package/src/pty-shell/pty-control-ipc.ts +4 -1
  534. package/src/pty-shell/pty-manifest.ts +77 -5
  535. package/src/pty-shell/registry.ts +19 -2
  536. package/src/pty-shell/tui-run-state.ts +253 -0
  537. package/src/release-loop/gate-host-reservation.ts +97 -0
  538. package/src/release-loop/landing-freeze.ts +5 -0
  539. package/src/release-loop/light-rc.ts +32 -4
  540. package/src/release-loop/placement.ts +92 -1
  541. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  542. package/src/release-loop/rehearsal.ts +73 -17
  543. package/src/render.ts +5 -1
  544. package/src/repl/index.ts +20 -2
  545. package/src/seat-loop/seat-knowhow.ts +282 -0
  546. package/src/seat-loop/seat-loop.ts +41 -2
  547. package/src/seat-loop/seat-report.ts +42 -2
  548. package/src/seat-loop/traffic-signal.ts +3 -0
  549. package/src/self-dev/ask-launch-flow.ts +24 -3
  550. package/src/self-dev/decompose-compose-graph.ts +28 -27
  551. package/src/self-dev/decompose-proposal.ts +53 -38
  552. package/src/self-dev/decompose.ts +17 -0
  553. package/src/self-dev/dev-pipeline.ts +31 -2
  554. package/src/self-dev/draft-residue.ts +24 -9
  555. package/src/self-dev/draft-sweep.ts +59 -4
  556. package/src/self-dev/external-call-zero.ts +77 -0
  557. package/src/self-dev/launch-preflight-text.ts +6 -0
  558. package/src/self-dev/launch-preflight.ts +25 -3
  559. package/src/self-dev/local-supervisor-judge.ts +185 -0
  560. package/src/self-dev/run-supervisor.ts +300 -24
  561. package/src/self-dev/run-types.ts +20 -0
  562. package/src/self-dev/shard-aggregate.ts +15 -2
  563. package/src/self-dev/shard-plan.ts +47 -0
  564. package/src/self-dev/shard-run.ts +135 -12
  565. package/src/self-dev/spawn-lane-files.ts +19 -0
  566. package/src/self-health/signatures.ts +132 -0
  567. package/src/self-implement/app-api-budget.ts +51 -11
  568. package/src/self-implement/config-gate.ts +2 -1
  569. package/src/self-implement/doctor-visit.ts +118 -0
  570. package/src/self-implement/expose-gate.ts +2 -1
  571. package/src/self-implement/gate-artifacts.ts +405 -0
  572. package/src/self-implement/gate-cli.ts +212 -18
  573. package/src/self-implement/gate-remote.ts +110 -25
  574. package/src/self-implement/gate-scenario.ts +85 -0
  575. package/src/self-implement/goal-author-decompose.ts +80 -16
  576. package/src/self-implement/goal-author.ts +270 -76
  577. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  578. package/src/self-implement/goal-file-name.ts +65 -0
  579. package/src/self-implement/graph-authority.ts +38 -6
  580. package/src/self-implement/graph-overlay-condition.ts +92 -1
  581. package/src/self-implement/ground-goal.ts +2 -1
  582. package/src/self-implement/heal-triage.ts +79 -0
  583. package/src/self-implement/host-regate.ts +74 -2
  584. package/src/self-implement/orchestrator.ts +14 -123
  585. package/src/self-implement/pr-title.ts +123 -0
  586. package/src/self-implement/review-mustfix-class.ts +115 -0
  587. package/src/self-implement/run-checkpoint.ts +235 -0
  588. package/src/self-implement/run-ledger.ts +266 -17
  589. package/src/self-implement/run-stop.ts +4 -3
  590. package/src/self-implement/run-ttl.ts +28 -4
  591. package/src/self-implement/running-runs.ts +10 -6
  592. package/src/self-implement/seams.ts +2 -0
  593. package/src/self-implement/self-implement-runtime.ts +32 -0
  594. package/src/self-implement/shadow-stage.ts +7 -6
  595. package/src/self-implement/stop-autoheal.ts +2 -1
  596. package/src/self-implement/train-gate-remote.ts +37 -8
  597. package/src/self-implement/train-reach-grouping.ts +157 -0
  598. package/src/self-implement/train-scenario-layers.ts +133 -0
  599. package/src/self-implement/uncommitted-work.ts +2 -0
  600. package/src/session/pending-input.ts +81 -11
  601. package/src/session/session-start.ts +224 -0
  602. package/src/session-runtime/index.ts +7 -1
  603. package/src/session-runtime/parallel-dispatch.ts +22 -5
  604. package/src/skills/tools/dev-harness.ts +6 -4
  605. package/src/skills/tools/ops-ledger.ts +707 -0
  606. package/src/skills/tools/persistent-grounding.ts +47 -7
  607. package/src/skills/tools/shell.ts +117 -1
  608. package/src/status/bar.ts +32 -2
  609. package/src/status/status-provider-info.ts +58 -0
  610. package/src/steward/resync-tick.ts +114 -23
  611. package/src/steward/ta-repair-event-collect.ts +158 -0
  612. package/src/task-agent/card-evidence.ts +25 -1
  613. package/src/task-agent/green-sweep.ts +8 -3
  614. package/src/task-agent/judge.ts +76 -0
  615. package/src/task-agent/land-queue.ts +79 -0
  616. package/src/task-agent/live-moves.ts +30 -9
  617. package/src/task-agent/postland-card.ts +5 -0
  618. package/src/task-agent/prelaunch-already-done.ts +98 -0
  619. package/src/task-agent/real-launch-guard.ts +37 -0
  620. package/src/task-agent/rejudge-on-head.ts +93 -13
  621. package/src/task-agent/remote-rejudge-bind.ts +62 -13
  622. package/src/task-agent/repair-cycle.ts +58 -7
  623. package/src/task-agent/repair-worker.ts +7 -0
  624. package/src/task-agent/run-identity.ts +200 -0
  625. package/src/task-agent/shadow.ts +50 -3
  626. package/src/task-agent/task-hand.ts +158 -5
  627. package/src/task-agent/train-landing.ts +77 -0
  628. package/src/task-agent/work-order.ts +104 -0
  629. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  630. package/src/task-orchestrator/surfaces/pod-command-job.ts +138 -22
  631. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  632. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  633. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  634. package/src/task-orchestrator/surfaces/pod-install-slots.ts +122 -15
  635. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  636. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  637. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +103 -0
  638. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  639. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  640. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  641. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  642. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  643. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  644. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  645. package/src/task-orchestrator/surfaces/self-implement-pod.ts +237 -46
  646. package/src/telegram.ts +2 -4
  647. package/src/terminal/session-registry.ts +6 -0
  648. package/src/thinking-line.ts +12 -3
  649. package/src/tool-runtime/index.ts +4 -0
  650. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  651. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  652. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  653. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  654. package/src/tui/input/pickers.ts +732 -0
  655. package/src/tui/slash/mission.ts +492 -0
  656. package/src/tui/slash/term.ts +877 -0
  657. package/src/tui-client/dashboard-session.ts +9 -0
  658. package/src/tui.ts +53 -0
  659. package/src/user-config/gemini-server-tools.ts +9 -0
  660. package/src/user-config.ts +106 -21
  661. package/src/util/spawn-sync-output.ts +7 -0
  662. package/src/ux-sim/fake-bin.ts +154 -0
  663. package/src/ux-sim/fake-clock.ts +36 -0
  664. package/src/ux-sim/fake-llm.ts +29 -0
  665. package/src/ux-sim/headless-tui.ts +72 -0
  666. package/src/ux-sim/in-process-cli.ts +176 -0
  667. package/src/ux-sim/temp-git-remote.ts +82 -0
  668. package/src/version/packed-revision.json +1 -1
  669. package/src/video-pipeline/recipes/vlog.ts +25 -7
  670. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  675. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  682. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  688. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  693. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  698. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  703. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  706. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  708. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  718. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  722. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  724. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  726. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  734. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  742. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  744. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  745. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  748. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  750. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  751. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  752. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/973cbf1b.3bbcf2b41548eca7.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/ceo/page-66ad46ed0279feb9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/loops/page-646b50f63b6fe732.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/morning/page-6f131b51193a36f9.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
  802. package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
  803. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
  804. package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
  805. package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
  806. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
  807. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  808. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  809. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  810. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  811. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  812. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  813. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  814. package/src/dashboard/bench-slash-runtime.ts +0 -40
  815. package/src/dashboard/input/search-modal-router.ts +0 -9
  816. package/src/dashboard/modals/pane-key-router.ts +0 -27
  817. package/src/dashboard/view-slash-runtime.ts +0 -48
  818. /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -201,6 +201,7 @@ export class DashboardSession {
201
201
  dispatchTool: opts.dispatchTool,
202
202
  ...(opts.onTurnComplete ? { onTurnComplete: opts.onTurnComplete } : {}),
203
203
  ...(opts.resolveModel ? { resolveModel: opts.resolveModel } : {}),
204
+ ...(opts.resolveSeat ? { resolveSeat: opts.resolveSeat } : {}),
204
205
  ...(opts.resolveMaxToolTurns
205
206
  ? { resolveMaxToolTurns: opts.resolveMaxToolTurns }
206
207
  : {}),
@@ -467,6 +468,14 @@ export class DashboardSession {
467
468
  this.sessionId = newSessionId;
468
469
  }
469
470
 
471
+ /** TUI-H8 ② — `/session new` 이 백엔드(ACP) 세션까지 새로 받는다. 같은 연결에서 `session/new` 를 다시 불러
472
+ * 새 id 로 갈아탄다(종전엔 TUI 기록만 비우고 ACP sessionId 가 그대로였다 · #69). 새 id 를 돌려준다. */
473
+ async renew(cwd: string): Promise<string> {
474
+ const { sessionId } = await this.client.newSession({ cwd, mcpServers: [] });
475
+ this.sessionId = sessionId;
476
+ return sessionId;
477
+ }
478
+
470
479
  /** Send a single user prompt and await the turn's stopReason.
471
480
  * Streaming text deltas and tool / usage events are delivered via
472
481
  * the optional callbacks on `req`. */
package/src/tui.ts CHANGED
@@ -523,6 +523,12 @@ const _keyQueue: Key[] = [];
523
523
  export type KeyTraceSource = 'main' | 'stream' | 'input';
524
524
 
525
525
  let _keyTracer: ((key: Key, source: KeyTraceSource) => void) | null = null;
526
+ let _lastHumanKeyAt = 0;
527
+
528
+ /** 마지막으로 배달된 사람 키 시각(ms · 0 = 아직 없음) — 내부 턴 문(H2)의 조용창 판정에 쓴다. */
529
+ export function lastHumanKeyAt(): number {
530
+ return _lastHumanKeyAt;
531
+ }
526
532
 
527
533
  /** Install a tracer invoked with every dispatched Key. Set to null to
528
534
  * detach. Exceptions thrown by the tracer are swallowed so a broken
@@ -534,6 +540,8 @@ export function setKeyTracer(fn: ((key: Key, source: KeyTraceSource) => void) |
534
540
  /** Call the installed tracer, if any. Safe to invoke unconditionally —
535
541
  * becomes a noop when no tracer is registered. */
536
542
  export function traceKey(key: Key, source: KeyTraceSource): void {
543
+ // H2 내부 턴 문 — «마지막 사람 키» 시각. 빈 이름(readKey 취소·빈 깨움)·리스너 표지는 사람 키가 아니다.
544
+ if (key.name && !key.name.startsWith('listener-')) _lastHumanKeyAt = Date.now();
537
545
  if (!_keyTracer) return;
538
546
  try { _keyTracer(key, source); } catch { /* swallow — never break input */ }
539
547
  }
@@ -956,6 +964,7 @@ export function readKey(source: KeyTraceSource = 'main'): Promise<Key> {
956
964
  export function injectKey(key: Key): boolean {
957
965
  if (!_raw) return false;
958
966
  _keyQueue.push(key);
967
+ _injectedKeys.add(key);
959
968
  // Wake any in-flight readKey awaiting on stdin by emitting an empty
960
969
  // chunk. The handler's queue-drain branch picks up the injected key
961
970
  // immediately.
@@ -965,6 +974,43 @@ export function injectKey(key: Key): boolean {
965
974
  return true;
966
975
  }
967
976
 
977
+ /** `injectKey` 로 들어온 키 표지 — `takeInjectedKeys` 가 stdin 잔여 키(readKey 몫)는 두고 주입 키만 꺼낸다. */
978
+ const _injectedKeys = new WeakSet<Key>();
979
+
980
+ /** ⭐ TUI-ESC-ABORT-TOOLS (2026-10-15) — 턴 중 스트리밍 리스너(`attachStreamingKeys`)가
981
+ * 바깥에서 주입된 키(`pty key` · 제어 IPC input-key → `injectKey`)를 받게 큐에서 꺼낸다.
982
+ * ⛔ readKey 가 걸려 있으면(`_cancelReadKey`) 큐는 그 readKey 의 몫이다 — 빈 배열을 돌려준다.
983
+ * ⛔ stdin 청크 잔여 키(readKey 가 넣은 것)는 건드리지 않는다. readKey 의 drain 동작은 그대로다. */
984
+ export function takeInjectedKeys(): Key[] {
985
+ if (_cancelReadKey || _keyQueue.length === 0) return [];
986
+ const taken: Key[] = [];
987
+ for (let i = 0; i < _keyQueue.length; ) {
988
+ const k = _keyQueue[i]!;
989
+ if (_injectedKeys.has(k)) {
990
+ taken.push(k);
991
+ _keyQueue.splice(i, 1);
992
+ } else {
993
+ i += 1;
994
+ }
995
+ }
996
+ // 같은 Key 객체가 두 번 주입될 수 있으므로 표지는 다 꺼낸 «뒤에» 지운다.
997
+ for (const k of taken) _injectedKeys.delete(k);
998
+ return taken;
999
+ }
1000
+
1001
+ /** ⭐ H2 내부 턴 문 — 걸려 있는 readKey 를 «빈 키»로 깨운다(키를 만들지도 큐에 넣지도 않는다).
1002
+ * stdin 에 남은 바이트는 그대로 다음 readKey 몫이다. 걸린 readKey 가 없으면 false. */
1003
+ export function cancelPendingReadKey(): boolean {
1004
+ if (!_cancelReadKey) return false;
1005
+ _cancelReadKey();
1006
+ return true;
1007
+ }
1008
+
1009
+ /** 아직 readKey 가 소비하지 않은 키 수 — 외부 입력 대기열이 «사용자 키보다 앞서» 끼어들지 않게 본다. */
1010
+ export function pendingKeyCount(): number {
1011
+ return _keyQueue.length;
1012
+ }
1013
+
968
1014
  export function termSize(): { rows: number; cols: number } {
969
1015
  return { rows: process.stdout.rows || 24, cols: process.stdout.columns || 80 };
970
1016
  }
@@ -992,6 +1038,13 @@ export function resetRenderCache(): void {
992
1038
  _lastFrameCols = 0;
993
1039
  }
994
1040
 
1041
+ /** True when the frame cache says `row` (0-based) currently shows
1042
+ * exactly `text` — a direct writer can skip repainting it. Invalidated
1043
+ * rows hold a sentinel that never matches. */
1044
+ export function renderCacheRowIs(row: number, text: string): boolean {
1045
+ return row >= 0 && row < _lastFrameLines.length && _lastFrameLines[row] === text;
1046
+ }
1047
+
995
1048
  /** Invalidate a specific row in the frame cache without nuking the
996
1049
  * whole thing. Callers that do direct stdout writes to a narrow
997
1050
  * band (input prompt, cursor moves) use this instead of
@@ -0,0 +1,9 @@
1
+ export function parseGeminiServerTools(raw: unknown): { googleSearch?: boolean; codeExecution?: boolean; urlContext?: boolean } | undefined {
2
+ if (!raw || typeof raw !== 'object') return undefined;
3
+ const obj = raw as Record<string, unknown>;
4
+ const out: { googleSearch?: boolean; codeExecution?: boolean; urlContext?: boolean } = {};
5
+ if (obj.googleSearch === true) out.googleSearch = true;
6
+ if (obj.codeExecution === true) out.codeExecution = true;
7
+ if (obj.urlContext === true) out.urlContext = true;
8
+ return (Object.keys(out).length > 0) ? out : undefined;
9
+ }
@@ -71,6 +71,7 @@ import { migrateLegacyXdgUserConfig } from './storage/legacy-elanous-config-migr
71
71
  import { withFileLockSync } from './storage/file-lock.js';
72
72
  import { debug } from './debug/log.js';
73
73
  import { setConfigTimeZoneSource } from './time/format.js';
74
+ import { parseGeminiServerTools } from './user-config/gemini-server-tools.js';
74
75
  import type { FoldMode } from './log-entry.js';
75
76
  import {
76
77
  CLAUDE_PACKAGE_MISSING,
@@ -85,6 +86,7 @@ import {
85
86
  parseGroundingSources,
86
87
  type GroundingConfig,
87
88
  } from './grounding/sources.js';
89
+ import { parseSeatTurnCapConfig, type SeatTurnCapConfig } from './core-turn/seat-turn-cap.js';
88
90
 
89
91
  // ── SkillRouter (existing) ───────────────────────────────────────────
90
92
 
@@ -1544,6 +1546,8 @@ export function parseErrorReportsConfig(raw: unknown): ErrorReportsConfig | unde
1544
1546
 
1545
1547
  export interface ChatConfig {
1546
1548
  factQuestion: { maxToolTurns: number };
1549
+ /** TUI-SEAT-TURN-CAP — 자리 TUI goal loop 한정 core 턴 상한 덮어쓰기(기본값 = core-turn/seat-turn-cap.ts). 설정했을 때만 있다. */
1550
+ seatTurnCap?: Partial<SeatTurnCapConfig>;
1547
1551
  /** Short questions may receive a tool-free first reply. Default true. */
1548
1552
  fastPath: boolean;
1549
1553
  conciseness: ChatConcisenessConfig;
@@ -1659,6 +1663,10 @@ export interface DashboardConfig {
1659
1663
  * Defaults off so optional pane/window controls do not occupy keys
1660
1664
  * required by essential input, reading, and escape controls. */
1661
1665
  enableSupplementalGlobalKeys: boolean;
1666
+ /** First-screen boot banner. Absent = `minimal`: only failures and first-run
1667
+ * guidance reach the transcript; healthy daemon/PWA/hitl-port rows move to
1668
+ * `/status`. `full` restores the historical band. */
1669
+ bootBanner?: 'minimal' | 'full';
1662
1670
  }
1663
1671
 
1664
1672
  export interface DashboardPromptBankConfig {
@@ -3337,7 +3345,8 @@ export interface AutoReviewConfig {
3337
3345
  };
3338
3346
  }
3339
3347
 
3340
- export type ModelRole = 'implement' | 'review' | 'research' | 'planning' | 'audit' | 'classify' | 'graph-grow';
3348
+ export type ModelRole = 'implement' | 'review' | 'research' | 'planning' | 'audit' | 'classify' | 'graph-grow' | 'coordinator' | 'guardian';
3349
+ export type AgentModelRole = 'coordinator' | 'guardian';
3341
3350
 
3342
3351
  export interface RoleModelConfig {
3343
3352
  implement?: string;
@@ -3347,6 +3356,8 @@ export interface RoleModelConfig {
3347
3356
  audit?: string;
3348
3357
  classify?: string;
3349
3358
  'graph-grow'?: string;
3359
+ coordinator?: string;
3360
+ guardian?: string;
3350
3361
  }
3351
3362
 
3352
3363
  /** Sparse provider-agnostic model tier preferences by execution role. */
@@ -3429,6 +3440,10 @@ export const ROLE_MODEL_DEFAULTS: Record<ModelRole, { environment: string; tier:
3429
3440
  audit: { environment: 'ELANOUS_MEMORY_JUDGE_MODEL', tier: 'better' },
3430
3441
  classify: { environment: 'ELANOUS_ACTION_CLASSIFIER_MODEL', tier: 'budget' },
3431
3442
  'graph-grow': { environment: 'ELANOUS_GRAPH_GROW_MODEL', tier: 'better' },
3443
+ // 이 티어는 provider 만 명시했을 때 쓰인다. 에이전트 기동은
3444
+ // resolveConfiguredAgentRoleLlm 이 명시 설정을 먼저 요구한다.
3445
+ coordinator: { environment: 'ELANOUS_COORDINATOR_MODEL', tier: 'balanced' },
3446
+ guardian: { environment: 'ELANOUS_GUARDIAN_MODEL', tier: 'balanced' },
3432
3447
  };
3433
3448
 
3434
3449
  /** Resolve `auto` through the same runtime provider selector that dispatches LLM calls.
@@ -3583,6 +3598,24 @@ export function resolveRoleLlm(role: ModelRole, opts: RoleLlmResolveOptions = {}
3583
3598
  return baseline;
3584
3599
  }
3585
3600
 
3601
+ /** 조율자·수호자는 사용자 선택이 없으면 기동하지 않는다.
3602
+ * 일반 역할의 기본 모델 사다리와 구분해, 발사 인자·env pin·roleLlm 설정 중
3603
+ * 실제 모델 선택(provider/tier/model)이 있을 때만 해석한다. effort 단독은 선택이 아니다. */
3604
+ export function resolveConfiguredAgentRoleLlm(
3605
+ role: AgentModelRole,
3606
+ opts: RoleLlmResolveOptions = {},
3607
+ ): RoleLlmResolution | undefined {
3608
+ const config = opts.config ?? getUserConfig();
3609
+ const hasSelection = (spec: RoleLlmSpec | undefined): boolean =>
3610
+ Boolean(spec?.provider || spec?.tier || spec?.model?.trim());
3611
+ const configured = [
3612
+ (opts.overrides ?? launchRoleLlmOverrides)?.[role],
3613
+ roleLlmEnvPin(role, opts.env ?? process.env),
3614
+ config.roleLlm?.[role],
3615
+ ].some(hasSelection);
3616
+ return configured ? resolveRoleLlm(role, { ...opts, config }) : undefined;
3617
+ }
3618
+
3586
3619
  /** POD-ROLE-LLM — 역할 고정을 «프로세스 env» 로 받는 칸. `ELANOUS_ROLE_LLM_<ROLE>` = RoleLlmSpec JSON
3587
3620
  * (예 `{"provider":"openai-codex","tier":"best","model":"gpt-6-sol"}`).
3588
3621
  * ⭐ 왜 env 인가: `--role-llm` 은 부모 프로세스 메모리 값이고 Pod 안엔 운영 config 가 없다 —
@@ -3627,6 +3660,8 @@ export interface OrchestratorLoopConfig {
3627
3660
  seatCaps: Record<OrchestratorSeat, number>;
3628
3661
  /** Max new delegations per tick; absent means no limit. */
3629
3662
  maxDelegatePerTick?: number;
3663
+ /** Dispatch placement preference and local concurrency lane. Defaults preserve the existing Pod preference and one local lane. */
3664
+ dispatch: { podTarget: number; localLane: number };
3630
3665
  /** Per-seat release gate; absent seats retain the spawn-budget default. */
3631
3666
  releaseGate?: Partial<Record<OrchestratorSeat, number>>;
3632
3667
  trafficMode: 'shadow' | 'live';
@@ -3644,7 +3679,7 @@ export interface OrchestratorLoopConfig {
3644
3679
  }
3645
3680
 
3646
3681
  export const ORCHESTRATOR_DEFAULTS: OrchestratorLoopConfig = {
3647
- mode: 'shadow', seatTrees: {}, seatCaps: { TC: 8, UX: 6, MK: 6, OP: 4 }, trafficMode: 'shadow', idleRequest: 'shadow', finishGate: 'shadow',
3682
+ mode: 'shadow', seatTrees: {}, seatCaps: { TC: 8, UX: 6, MK: 6, OP: 4 }, dispatch: { podTarget: 18, localLane: 1 }, trafficMode: 'shadow', idleRequest: 'shadow', finishGate: 'shadow',
3648
3683
  };
3649
3684
 
3650
3685
  export function parseOrchestratorLoopConfig(raw: unknown): OrchestratorLoopConfig {
@@ -3667,7 +3702,14 @@ export function parseOrchestratorLoopConfig(raw: unknown): OrchestratorLoopConfi
3667
3702
  }
3668
3703
  const mode = value.mode === 'off' || value.mode === 'live' ? value.mode : 'shadow';
3669
3704
  const maxDelegatePerTick = value.maxDelegatePerTick;
3670
- return { mode, seatTrees, seatCaps,
3705
+ const rawDispatch = value.dispatch && typeof value.dispatch === 'object' && !Array.isArray(value.dispatch)
3706
+ ? value.dispatch as Record<string, unknown> : {};
3707
+ const dispatch = { ...ORCHESTRATOR_DEFAULTS.dispatch };
3708
+ for (const field of ['podTarget', 'localLane'] as const) {
3709
+ const setting = rawDispatch[field];
3710
+ if (typeof setting === 'number' && Number.isSafeInteger(setting) && setting >= 0) dispatch[field] = setting;
3711
+ }
3712
+ return { mode, seatTrees, seatCaps, dispatch,
3671
3713
  ...(typeof maxDelegatePerTick === 'number' && Number.isSafeInteger(maxDelegatePerTick) && maxDelegatePerTick >= 0 ? { maxDelegatePerTick } : {}),
3672
3714
  ...(Object.keys(releaseGate).length ? { releaseGate } : {}),
3673
3715
  trafficMode: value.trafficMode === 'live' ? 'live' : 'shadow',
@@ -3763,8 +3805,10 @@ export interface GateRemoteConfig {
3763
3805
  host?: string;
3764
3806
  /** Local 1-min load average above which checks go remote (default 20). */
3765
3807
  loadThreshold?: number;
3766
- /** Concurrent heavy checks per remote host (default and ceiling 2 — config may only lower it). */
3808
+ /** Legacy default cap for hosts without an entry in hostCaps (1..2, default 2). */
3767
3809
  hostCap?: number;
3810
+ /** Per SSH host concurrent heavy-check slots (1..8); overrides hostCap for that host. */
3811
+ hostCaps?: Record<string, number>;
3768
3812
  /** Bare mirror on the host (default ~/mirror/elanous-agent.git — shared with the release gate). */
3769
3813
  mirror?: string;
3770
3814
  /** Seconds to wait for a free host slot before running locally (default 600). */
@@ -3782,6 +3826,12 @@ export function parseGateRemoteConfig(raw: unknown): GateRemoteConfig | undefine
3782
3826
  if (typeof v === 'number' && Number.isFinite(v) && v >= 0) out[key] = v;
3783
3827
  }
3784
3828
  if (typeof r.hostCap === 'number' && Number.isSafeInteger(r.hostCap) && r.hostCap > 0 && r.hostCap <= 2) out.hostCap = r.hostCap;
3829
+ if (r.hostCaps && typeof r.hostCaps === 'object' && !Array.isArray(r.hostCaps)) {
3830
+ const caps = Object.fromEntries(Object.entries(r.hostCaps).filter(([host, cap]) =>
3831
+ /^(?:[\w.-]+@)?[\w.-]+$/.test(host) && !host.startsWith('-') &&
3832
+ typeof cap === 'number' && Number.isSafeInteger(cap) && cap >= 1 && cap <= 8)) as Record<string, number>;
3833
+ if (Object.keys(caps).length) out.hostCaps = caps;
3834
+ }
3785
3835
  return Object.keys(out).length ? out : undefined;
3786
3836
  }
3787
3837
 
@@ -3840,9 +3890,9 @@ export interface UserConfig {
3840
3890
  /** GUARD-ONE-a: omitted means shadow. `live` is parsed for the later cutover, but `elanous guardian tick`
3841
3891
  * refuses it until a human-confirmed operational change (GUARD-ONE-a ships shadow only). */
3842
3892
  guardian?: { mode?: 'shadow' | 'live'; /** Orphan CLI GC on the guardian tick: off = no ps collection, shadow (default) = evidence only, on = evidence then SIGTERM. */ orphanGc?: 'off' | 'shadow' | 'on' };
3843
- /** TA-JUDGE-LIVE-SAFE: task-agent judge moves executed for real. Only `review` · `propose-green` are honoured
3844
- * (`src/task-agent/live-moves.ts` drops anything else with a warning). Absent = env ELANOUS_TASK_AGENT_LIVE_MOVES, else none (pure shadow). */
3845
- taskAgent?: { liveMoves?: string[]; /** TA-REJUDGE-PERIODIC — steward tick runs `tasks rejudge --all` every N minutes (absent/0 = off). */ rejudgeEveryMinutes?: number; /** 1-minute load average above which that tick is skipped (default 60). */ rejudgeMaxLoad?: number; parentHost?: { host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number } | Array<{ host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number }> };
3893
+ /** Task-agent live move allow-list (`src/task-agent/live-moves.ts` validates its vocabulary).
3894
+ * Absent = env ELANOUS_TASK_AGENT_LIVE_MOVES, else none (pure shadow). */
3895
+ taskAgent?: { liveMoves?: string[]; /** TA-REJUDGE-PERIODIC — steward tick runs `tasks rejudge --all` every N minutes (absent/0 = off). */ rejudgeEveryMinutes?: number; /** 1-minute load average above which that tick is skipped (default 60). */ rejudgeMaxLoad?: number; /** TA-REPAIR-TICK-CAP — new repair launches per `tasks rejudge --all` (default 3, 0 = none). */ repairMaxPerTick?: number; /** TA-LAND-AFTER-REVIEW — opt-in external queue adapter, never a direct merge command. */ landQueue?: { command: string; remote: string }; parentHost?: { host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number } | Array<{ host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number }> };
3846
3896
  events?: EventsConfig;
3847
3897
  /** GATE-REMOTE — see GateRemoteConfig. Absent = defaults (auto on · node-b · load 20 · cap 2). */
3848
3898
  gateRemote?: GateRemoteConfig;
@@ -3878,7 +3928,7 @@ export interface UserConfig {
3878
3928
  followUp?: 'shadow' | 'live';
3879
3929
  };
3880
3930
  /** ☸️ Pod 실행 칸 — `pool` = 기존 기본 풀(`컨텍스트[@ssh호스트][:상한][#k3d-레지스트리:포트]` 쉼표 · 앞이 우선). harness 실행은 인자·ELANOUS_POD_POOL·harness.podPool 다음으로 읽는다. */
3881
- pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string; /** 읽기 전용 Pod lease 권장에 쓰는 계정별 동시 수. */ lease?: { perAccount?: number }; /** 실측 권고를 Pod 발사 기본값으로 쓸지 (기본 off). */ memory?: { adviseDefaults?: boolean }; /** 명령 Job 자식 로그(child.log) 상한 바이트. 양의 정수만. 넘으면 끝부분 우선. */ childLogMaxBytes?: number };
3931
+ pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string; /** 읽기 전용 Pod lease 권장에 쓰는 계정별 동시 수. */ lease?: { perAccount?: number }; /** 실측 권고를 Pod 발사 기본값으로 쓸지 (기본 off). */ memory?: { adviseDefaults?: boolean }; /** 명령 Job 자식 로그(child.log) 상한 바이트. 양의 정수만. 넘으면 끝부분 우선. */ childLogMaxBytes?: number; /** warm Pod 재사용 실전 손잡이(소비자별 · 기본 off · 문자 그대로 true 만). 판정 = pod-warm-switch.ts `decideWarmReuse` — 증거가 모자라면 flag 가 켜져도 off. */ warmReuse?: { gateRecheck?: boolean; land?: boolean; ta?: boolean; /** 연속 일치 표본 하한(양의 정수 · 기본 3). */ minMatchSamples?: number } };
3882
3932
  skillRouter: SkillRouterConfig;
3883
3933
  llm: LLMConfig;
3884
3934
  skills: SkillsConfig;
@@ -4046,7 +4096,7 @@ export function parseRoleLlmEntry(raw: unknown): { ok: true; spec: RoleLlmSpec }
4046
4096
  return { ok: true, spec };
4047
4097
  }
4048
4098
 
4049
- export const MODEL_ROLES: readonly ModelRole[] = ['implement', 'review', 'research', 'planning', 'audit', 'classify', 'graph-grow'];
4099
+ export const MODEL_ROLES: readonly ModelRole[] = ['implement', 'review', 'research', 'planning', 'audit', 'classify', 'graph-grow', 'coordinator', 'guardian'];
4050
4100
 
4051
4101
  export function isModelRole(v: unknown): v is ModelRole {
4052
4102
  return typeof v === 'string' && (MODEL_ROLES as readonly string[]).includes(v);
@@ -4154,14 +4204,33 @@ function parseTaskAgentConfig(raw: unknown): UserConfig['taskAgent'] {
4154
4204
  }
4155
4205
  const parentHost = parseTaskAgentParentHost((raw as Record<string, unknown>).parentHost);
4156
4206
  // TA-REJUDGE-PERIODIC — 음이 아닌 유한수만 산다(0 = 끔). 그 밖은 경고하고 버린다(= 끔 · 기본 부하 상한).
4157
- const rejudge: { rejudgeEveryMinutes?: number; rejudgeMaxLoad?: number } = {};
4207
+ const rejudge: { rejudgeEveryMinutes?: number; rejudgeMaxLoad?: number; repairMaxPerTick?: number } = {};
4158
4208
  for (const key of ['rejudgeEveryMinutes', 'rejudgeMaxLoad'] as const) {
4159
4209
  const value = (raw as Record<string, unknown>)[key];
4160
4210
  if (value === undefined) continue;
4161
4211
  if (typeof value === 'number' && Number.isFinite(value) && value >= 0) rejudge[key] = value;
4162
4212
  else warnUserConfigDrop(`taskAgent.${key}`, `음이 아닌 수가 아니다(${JSON.stringify(value)}) — 버림`);
4163
4213
  }
4164
- const extras = { ...rejudge, ...(parentHost ? { parentHost } : {}) };
4214
+ const repairMaxPerTick = (raw as Record<string, unknown>).repairMaxPerTick;
4215
+ if (repairMaxPerTick !== undefined) {
4216
+ if (Number.isSafeInteger(repairMaxPerTick) && (repairMaxPerTick as number) >= 0) rejudge.repairMaxPerTick = repairMaxPerTick as number;
4217
+ else warnUserConfigDrop('taskAgent.repairMaxPerTick', `음이 아닌 정수가 아니다(${JSON.stringify(repairMaxPerTick)}) — 기본 3`);
4218
+ }
4219
+ const queueRaw = (raw as Record<string, unknown>).landQueue;
4220
+ let landQueue: { command: string; remote: string } | undefined;
4221
+ if (queueRaw !== undefined) {
4222
+ if (queueRaw && typeof queueRaw === 'object' && !Array.isArray(queueRaw)
4223
+ && typeof (queueRaw as Record<string, unknown>).command === 'string'
4224
+ && isAbsolute((queueRaw as Record<string, string>).command)
4225
+ && typeof (queueRaw as Record<string, unknown>).remote === 'string'
4226
+ && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test((queueRaw as Record<string, string>).remote)) {
4227
+ landQueue = { command: (queueRaw as Record<string, string>).command, remote: (queueRaw as Record<string, string>).remote };
4228
+ } else {
4229
+ warnUserConfigDrop('taskAgent.landQueue', '절대 command 경로와 유효한 remote 호스트가 필요 — 착지 fail-closed');
4230
+ landQueue = { command: '', remote: '' };
4231
+ }
4232
+ }
4233
+ const extras = { ...rejudge, ...(parentHost ? { parentHost } : {}), ...(landQueue ? { landQueue } : {}) };
4165
4234
  const liveMoves = (raw as Record<string, unknown>).liveMoves;
4166
4235
  if (liveMoves === undefined) return Object.keys(extras).length ? extras : undefined;
4167
4236
  // 설정이 «있으면» 환경 변수로 내려가지 않는다 — 배열이 아니면 빈 목록(fail-closed), 문자열 밖 항목은 글자로 바꿔 넘겨
@@ -4261,6 +4330,10 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
4261
4330
  if (effort === 'low' || effort === 'medium' || effort === 'high') spec.effort = effort;
4262
4331
  else warnUserConfigDrop(`roleLlm.${role}.effort`, `low|medium|high 가 아니다(${JSON.stringify(effort)}) — 버림`);
4263
4332
  }
4333
+ if ((role === 'coordinator' || role === 'guardian') && !spec.provider && !spec.tier && !spec.model) {
4334
+ dropped.push({ role, reason: 'provider·tier·model 중 하나는 있어야 한다 (effort 단독은 기동 설정이 아니다)' });
4335
+ continue;
4336
+ }
4264
4337
  if (Object.keys(spec).length > 0) parsed[role] = spec;
4265
4338
  } else {
4266
4339
  const entry = parseRoleLlmEntry(rawEntry);
@@ -4275,6 +4348,11 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
4275
4348
  // 사용자는 「왜 내 설정이 안 먹지」를 영영 못 푼다(CLI 는 이름을 대며 거부하는데 여기만 조용했다).
4276
4349
  // ⇒ 버린 것을 «이름과 이유»로 남긴다. 로딩 자체는 계속한다.
4277
4350
  if (dropped.length > 0) {
4351
+ for (const { role, reason } of dropped) {
4352
+ if (role === 'coordinator' || role === 'guardian') {
4353
+ warnUserConfigDrop(`roleLlm.${role}`, `${reason} — 버림; 명시 모델 없이는 에이전트 기동 거부`);
4354
+ }
4355
+ }
4278
4356
  try {
4279
4357
  // eslint-disable-next-line @typescript-eslint/no-require-imports
4280
4358
  const { debug } = require('./debug/log.js') as typeof import('./debug/log.js');
@@ -5040,6 +5118,17 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
5040
5118
  return typeof lease.perAccount === 'number' && Number.isSafeInteger(lease.perAccount) && lease.perAccount > 0
5041
5119
  ? lease.perAccount : 4;
5042
5120
  })() },
5121
+ warmReuse: (() => {
5122
+ const warm = legacyPod.warmReuse && typeof legacyPod.warmReuse === 'object' && !Array.isArray(legacyPod.warmReuse)
5123
+ ? (legacyPod.warmReuse as Record<string, unknown>) : {};
5124
+ return {
5125
+ gateRecheck: warm.gateRecheck === true,
5126
+ land: warm.land === true,
5127
+ ta: warm.ta === true,
5128
+ minMatchSamples: typeof warm.minMatchSamples === 'number' && Number.isSafeInteger(warm.minMatchSamples) && warm.minMatchSamples > 0
5129
+ ? warm.minMatchSamples : 3,
5130
+ };
5131
+ })(),
5043
5132
  },
5044
5133
  harness: {
5045
5134
  edgeRail: (() => {
@@ -5409,6 +5498,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
5409
5498
  && Number.isSafeInteger(chatFactQuestion.maxToolTurns) && chatFactQuestion.maxToolTurns > 0
5410
5499
  ? chatFactQuestion.maxToolTurns : CHAT_DEFAULTS.factQuestion.maxToolTurns,
5411
5500
  },
5501
+ ...((): { seatTurnCap?: Partial<SeatTurnCapConfig> } => { const c = parseSeatTurnCapConfig(chat.seatTurnCap); return c ? { seatTurnCap: c } : {}; })(),
5412
5502
  fastPath: chat.fastPath === false || chat.fastPath === 'false' ? false : CHAT_DEFAULTS.fastPath,
5413
5503
  conciseness: {
5414
5504
  enabled: chatConciseness.enabled === false ? false : CHAT_CONCISENESS_DEFAULTS.enabled,
@@ -5722,6 +5812,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
5722
5812
  ? dash.foldMode
5723
5813
  : 'task-unit',
5724
5814
  benchmark: dash.benchmark === true ? true : undefined,
5815
+ bootBanner: dash.bootBanner === 'minimal' || dash.bootBanner === 'full' ? dash.bootBanner : undefined,
5725
5816
  enableVirtualWindowSwitchKeys: dash.enableVirtualWindowSwitchKeys === true,
5726
5817
  enableSupplementalGlobalKeys: dash.enableSupplementalGlobalKeys === true,
5727
5818
  promptBank: {
@@ -6535,6 +6626,9 @@ export function saveUserConfig(
6535
6626
  answerPriority: cfg.llm.answerPriority,
6536
6627
  maxTurns: cfg.llm.maxTurns,
6537
6628
  missionRouting: cfg.llm.missionRouting,
6629
+ // ⛔ 로드(parseLlmRoutePolicy)만 있고 저장이 없으면 `config set llm.routePolicy` 가 «조용히» 떨어진다
6630
+ // (10-14 OP 실측 — set 뒤 get 이 undefined · TUI-MODEL-SESSION-SCOPE ①).
6631
+ routePolicy: cfg.llm.routePolicy,
6538
6632
  }),
6539
6633
  skills: stripUndef({
6540
6634
  activeSet: cfg.skills.activeSet,
@@ -6698,6 +6792,7 @@ export function saveUserConfig(
6698
6792
  promptBank: cfg.dashboard.promptBank,
6699
6793
  foldMode: cfg.dashboard.foldMode,
6700
6794
  benchmark: cfg.dashboard.benchmark,
6795
+ bootBanner: cfg.dashboard.bootBanner,
6701
6796
  enableVirtualWindowSwitchKeys: cfg.dashboard.enableVirtualWindowSwitchKeys,
6702
6797
  enableSupplementalGlobalKeys: cfg.dashboard.enableSupplementalGlobalKeys,
6703
6798
  }),
@@ -7030,16 +7125,6 @@ function parseMemoryJudge(raw: unknown): { enabled?: boolean; model?: string; cr
7030
7125
  return (out.enabled !== undefined || out.model !== undefined || out.crossRecall !== undefined) ? out : undefined;
7031
7126
  }
7032
7127
 
7033
- function parseGeminiServerTools(raw: unknown): { googleSearch?: boolean; codeExecution?: boolean; urlContext?: boolean } | undefined {
7034
- if (!raw || typeof raw !== 'object') return undefined;
7035
- const obj = raw as Record<string, unknown>;
7036
- const out: { googleSearch?: boolean; codeExecution?: boolean; urlContext?: boolean } = {};
7037
- if (obj.googleSearch === true) out.googleSearch = true;
7038
- if (obj.codeExecution === true) out.codeExecution = true;
7039
- if (obj.urlContext === true) out.urlContext = true;
7040
- return (Object.keys(out).length > 0) ? out : undefined;
7041
- }
7042
-
7043
7128
  function parseAnswerPriority(raw: unknown): 'cost' | 'balanced' | 'quality' | 'exhaustive' | undefined {
7044
7129
  return raw === 'cost' || raw === 'balanced' || raw === 'quality' || raw === 'exhaustive'
7045
7130
  ? raw
@@ -1,5 +1,12 @@
1
1
  import { spawnSync, type SpawnSyncOptionsWithStringEncoding } from 'node:child_process';
2
2
 
3
+ /**
4
+ * Default maxBuffer for harness · Pod · gate `spawnSync` calls that read child output.
5
+ * Node's 1 MiB default truncated `git ls-files` (1.54 MiB in W2b · 0.2.30 HARD #3) — same value as #28476.
6
+ * The ratchet `test/spawn-sync-max-buffer.test.ts` keeps new readers in those trees on an explicit maxBuffer.
7
+ */
8
+ export const SPAWN_SYNC_MAX_BUFFER = 16 * 1024 * 1024;
9
+
3
10
  /** Read command text completely or fail closed; never return a partial stdout. */
4
11
  export function spawnSyncText(
5
12
  cmd: string,
@@ -0,0 +1,154 @@
1
+ // Fake executables on PATH for tests whose code under test spawns an external CLI
2
+ // (grok · magick · tesseract · …) that a gate Pod does not have.
3
+ //
4
+ // The industry-standard shape is a «PATH shim»: a tiny shell script with the real
5
+ // name, placed first on PATH. This module only makes that shape shared, so tests
6
+ // stop hand-writing `writeFileSync + chmodSync` (MOCK-REVIEW R6 · MOCK-DEVICES-2 ⓑ).
7
+ //
8
+ // Bun resolves a child's executable from the PATH the process STARTED with when the
9
+ // call passes no `env`; `test/preload-child-env.ts` makes a later PATH change visible
10
+ // to such calls. Code that passes its own `env` must receive `fakeBins.env` (or a
11
+ // PATH built from `fakeBins.path()`).
12
+ //
13
+ // ⛔ This is not a simulator of the real tool: a spec only fixes stdout · stderr ·
14
+ // exit code · lifetime, and records argv. Behaviour of the real tool stays with
15
+ // tests that run where the tool exists.
16
+ import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
17
+ import { tmpdir } from 'node:os';
18
+ import { delimiter, join } from 'node:path';
19
+
20
+ export interface FakeBinSpec {
21
+ readonly stdout?: string;
22
+ readonly stderr?: string;
23
+ /** Exit code (default 0). */
24
+ readonly exitCode?: number;
25
+ /** Stay alive this long before exiting — for long-running daemons a test kills. */
26
+ readonly sleepSeconds?: number;
27
+ }
28
+
29
+ export interface FakeBinCall {
30
+ readonly name: string;
31
+ readonly argv: readonly string[];
32
+ }
33
+
34
+ export interface FakeBins {
35
+ /** Directory holding the fake executables. */
36
+ readonly dir: string;
37
+ /** Absolute path of one fake executable. */
38
+ bin(name: string): string;
39
+ /** PATH with the fake directory first (default base: the current PATH). */
40
+ path(base?: string): string;
41
+ /** `process.env` with the fake PATH, for code that passes its own `env`. */
42
+ readonly env: NodeJS.ProcessEnv;
43
+ /** Every recorded invocation, in order. */
44
+ calls(): FakeBinCall[];
45
+ /** Resolve once at least `count` invocations are recorded (a spawned child records asynchronously). */
46
+ waitForCalls(count: number, timeoutMs?: number): Promise<FakeBinCall[]>;
47
+ cleanup(): void;
48
+ }
49
+
50
+ const NAME = /^[A-Za-z0-9._+-]+$/;
51
+
52
+ function shellQuote(value: string): string {
53
+ return `'${value.replace(/'/g, `'\\''`)}'`;
54
+ }
55
+
56
+ function script(name: string, spec: FakeBinSpec, dataDir: string, logPath: string): string {
57
+ const lines = ['#!/bin/sh'];
58
+ // One record per call: name and each argv entry NUL-terminated (one printf), then an ASCII record
59
+ // separator \x1e (a second printf). `calls()` drops the unterminated tail, so a reader never sees half a record.
60
+ lines.push(`{ printf '%s\\0' ${shellQuote(name)} "$@"; printf '\\036'; } >> ${shellQuote(logPath)}`);
61
+ if (spec.stdout !== undefined) {
62
+ const file = join(dataDir, `${name}.stdout`);
63
+ writeFileSync(file, spec.stdout);
64
+ lines.push(`cat ${shellQuote(file)}`);
65
+ }
66
+ if (spec.stderr !== undefined) {
67
+ const file = join(dataDir, `${name}.stderr`);
68
+ writeFileSync(file, spec.stderr);
69
+ lines.push(`cat ${shellQuote(file)} >&2`);
70
+ }
71
+ const exitCode = spec.exitCode ?? 0;
72
+ if (spec.sleepSeconds !== undefined && spec.sleepSeconds > 0) {
73
+ const seconds = Math.ceil(spec.sleepSeconds);
74
+ // exit 0: `exec` so killing the fake kills the sleep itself. Any other code needs the shell to
75
+ // outlive the sleep; a fake killed mid-sleep then leaves `sleep` until `sleepSeconds` ends.
76
+ if (exitCode === 0) lines.push(`exec sleep ${seconds}`);
77
+ else lines.push(`sleep ${seconds}`);
78
+ }
79
+ lines.push(`exit ${exitCode}`);
80
+ return `${lines.join('\n')}\n`;
81
+ }
82
+
83
+ export function createFakeBins(specs: Readonly<Record<string, FakeBinSpec>>): FakeBins {
84
+ for (const name of Object.keys(specs)) {
85
+ if (!NAME.test(name) || name === '.' || name === '..') throw new Error(`fake-bin: invalid executable name ${JSON.stringify(name)}`);
86
+ }
87
+ const root = mkdtempSync(join(tmpdir(), 'ux-sim-fake-bin-'));
88
+ const dir = join(root, 'bin');
89
+ const dataDir = join(root, 'data');
90
+ const logPath = join(root, 'calls.log');
91
+ try {
92
+ mkdirSync(dir);
93
+ mkdirSync(dataDir);
94
+ writeFileSync(logPath, '');
95
+ for (const [name, spec] of Object.entries(specs)) {
96
+ const file = join(dir, name);
97
+ writeFileSync(file, script(name, spec, dataDir, logPath));
98
+ chmodSync(file, 0o755);
99
+ }
100
+ } catch (error) {
101
+ rmSync(root, { recursive: true, force: true });
102
+ throw error;
103
+ }
104
+ const path = (base = process.env.PATH ?? '') => (base ? `${dir}${delimiter}${base}` : dir);
105
+ return {
106
+ dir,
107
+ bin: (name) => join(dir, name),
108
+ path,
109
+ get env() {
110
+ return { ...process.env, PATH: path() };
111
+ },
112
+ calls() {
113
+ if (!existsSync(logPath)) return [];
114
+ // The segment after the last separator is either empty or a record still being written — never count it.
115
+ return readFileSync(logPath, 'utf8')
116
+ .split('\x1e')
117
+ .slice(0, -1)
118
+ .map((record) => {
119
+ const [name = '', ...argv] = record.split('\0').slice(0, -1);
120
+ return { name, argv };
121
+ });
122
+ },
123
+ async waitForCalls(count, timeoutMs = 5_000) {
124
+ const deadline = Date.now() + timeoutMs;
125
+ for (;;) {
126
+ const recorded = this.calls();
127
+ if (recorded.length >= count) return recorded;
128
+ if (Date.now() >= deadline) throw new Error(`fake-bin: expected ${count} call(s) within ${timeoutMs}ms, saw ${recorded.length}`);
129
+ await new Promise((resolve) => setTimeout(resolve, 20));
130
+ }
131
+ },
132
+ cleanup: () => rmSync(root, { recursive: true, force: true }),
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Put fake executables first on `process.env.PATH` for the duration of `run`,
138
+ * then restore PATH and remove the files — also when `run` throws.
139
+ */
140
+ export async function withFakeBins<T>(
141
+ specs: Readonly<Record<string, FakeBinSpec>>,
142
+ run: (fakeBins: FakeBins) => T | Promise<T>,
143
+ ): Promise<T> {
144
+ const fakeBins = createFakeBins(specs);
145
+ const previousPath = process.env.PATH;
146
+ process.env.PATH = fakeBins.path(previousPath ?? '');
147
+ try {
148
+ return await run(fakeBins);
149
+ } finally {
150
+ if (previousPath === undefined) delete process.env.PATH;
151
+ else process.env.PATH = previousPath;
152
+ fakeBins.cleanup();
153
+ }
154
+ }
@@ -0,0 +1,36 @@
1
+ // Bun's real test timer implementation, scoped so exceptions cannot leave
2
+ // Date or timers mocked for the next test. Use only in serial tests: timer
3
+ // replacement is process-global and does not affect child processes.
4
+ import { jest } from 'bun:test';
5
+
6
+ export interface SimClock {
7
+ tick(ms: number): void;
8
+ setTime(now: number | Date): void;
9
+ now(): number;
10
+ pendingTimers(): number;
11
+ }
12
+
13
+ let active = false;
14
+
15
+ export async function withSimClock<T>(now: number | Date, run: (clock: SimClock) => Promise<T> | T): Promise<T> {
16
+ if (active) throw new Error('sim clock is process-global; run scenarios serially');
17
+ active = true;
18
+ try {
19
+ jest.useFakeTimers({ now });
20
+ const clock: SimClock = {
21
+ tick(ms) {
22
+ if (!Number.isFinite(ms) || ms < 0) throw new Error('sim clock tick must be a nonnegative finite number');
23
+ jest.advanceTimersByTime(ms);
24
+ },
25
+ setTime(value) { jest.setSystemTime(value); },
26
+ now() { return Date.now(); },
27
+ pendingTimers() { return jest.getTimerCount(); },
28
+ };
29
+ return await run(clock);
30
+ }
31
+ finally {
32
+ jest.clearAllTimers();
33
+ jest.useRealTimers();
34
+ active = false;
35
+ }
36
+ }