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
@@ -39,10 +39,11 @@ import { createTuiScreenMirror } from './tui-screen-mirror.js';
39
39
  import { getChannelBus } from '../terminal-matrix/index.js';
40
40
  import { publishSelfReportFrame } from './self-report-frame.js';
41
41
  import {
42
- upsertPtyManifest, updatePtyManifestFrame, touchLivePtyManifest, markPtyManifestClosed, removePtyManifest,
42
+ upsertPtyManifest, updatePtyManifestFrame, touchLivePtyManifest, markPtyManifestClosed, removePtyManifest, getPtyManifest,
43
+ updatePtyManifestBuild,
43
44
  } from '../pty-shell/pty-manifest.js';
44
45
  import { writeHarnessScreen } from '../harness/harness-screen.js';
45
- import { startTuiRunStateRecorder } from '../pty-shell/tui-run-state.js';
46
+ import { runningBuild, startTuiRunStateRecorder } from '../pty-shell/tui-run-state.js';
46
47
  import { debug } from '../debug/log.js';
47
48
  import { routeExternalInput, type ExternalInputRoute } from '../input/external-input-queue.js';
48
49
 
@@ -185,6 +186,48 @@ export interface TuiSelfReportDeps {
185
186
  reportControlCleanupFailure?: (stage: TuiControlCleanupStage, error: unknown) => void;
186
187
  /** 행 등록 직후 실행 판 ⊕ 턴(idle) 기록을 연다 — `elanous pty state` 가 읽는다. 반환 = 정리. */
187
188
  startRunState?: (surfaceId: string) => (() => void);
189
+ /** 미룬 우편 깨움 폴러(TUI-H4)를 연다 — 반환 = 정리. 기본은 실 행 등록과 짝일 때만 늦게 불러온 `startPendingWakePoller`. */
190
+ startWakePoller?: (surfaceId: string) => (() => void);
191
+ /** 박동마다 자기 행을 본다 — 없으면 null · ⛔ 조회 실패는 «던진다»(없다로 읽지 않는다). 기본 = `getPtyManifest(id, { strict })`. */
192
+ lookupRow?: (surfaceId: string) => TuiOwnRowView | null;
193
+ /** 재등록 뒤 실행 판(build) 칸을 다시 적는다 — 기본 = 기동 때 판(`runningBuild`). */
194
+ restoreBuild?: (surfaceId: string) => void;
195
+ /** 박동 스케줄러 — 기본 setInterval(unref). 시험이 박동을 손으로 돌린다. */
196
+ driveHeartbeat?: (tick: () => void, ms: number) => (() => void);
197
+ /** SIGCONT 수신 훅(행 상실 단서) — 반환 = 해제. 기본 = process.on('SIGCONT'). */
198
+ onSigcont?: (fn: () => void) => (() => void);
199
+ /** 행 상실 관측 — 기본 = debug.log('tui.self-report', 'row-missing', data). */
200
+ logRowMissing?: (data: TuiRowMissingEvent) => void;
201
+ }
202
+
203
+ /** 박동이 보는 자기 행 — `PtyManifestRow` 의 부분(재등록 뒤 frame·build 복원 확인에도 쓴다). */
204
+ export interface TuiOwnRowView {
205
+ readonly alive: boolean;
206
+ readonly frameAt?: number;
207
+ readonly build?: unknown;
208
+ }
209
+
210
+ /** `tui.self-report` · `row-missing` 한 줄 — 살아 있는 TUI 의 manifest 행이 사라졌을 때(재등록 시도 결과 ⊕ 원인 단서). */
211
+ export interface TuiRowMissingEvent {
212
+ readonly surfaceId: string;
213
+ readonly pid: number;
214
+ /** 'absent' = 행이 없다 · 'closed' = 행은 있는데 alive=0 · 'lookup-failed' = 조회 자체가 실패(재등록 안 함). */
215
+ readonly state: 'absent' | 'closed' | 'lookup-failed';
216
+ /** 마지막으로 자기 행을 «본» 시각(등록·재등록 포함). */
217
+ readonly lastSeenAt: number;
218
+ readonly sinceMs: number;
219
+ /** 직전 박동과의 간격 — 박동 주기보다 훨씬 크면 그 사이 프로세스가 멈췄다(SIGSTOP·SIGTTIN·이벤트 루프 정체). */
220
+ readonly gapMs: number;
221
+ readonly heartbeatMs: number;
222
+ /** 마지막 SIGCONT 시각(없으면 null) — `lastSeenAt` 뒤면 «정지 → 재개» 사이에 걷혔다는 단서. */
223
+ readonly sigcontAt: number | null;
224
+ readonly sigcontSinceLastSeen: boolean;
225
+ readonly reRegistered: boolean;
226
+ /** 재등록이 비운 frame 칸에 마지막 화면을 다시 적었나(`pty snapshot` 이 바로 닿는다). */
227
+ readonly frameRestored: boolean;
228
+ /** 재등록이 비운 실행 판(build) 칸을 다시 적었나(다시 읽어 확인). */
229
+ readonly buildRestored: boolean;
230
+ readonly error?: string;
188
231
  }
189
232
 
190
233
  export type TuiControlInitStage = 'create-target' | 'register-target' | 'start-poller' | 'publish-manifest';
@@ -263,6 +306,17 @@ export function startTuiSelfReport(deps: TuiSelfReportDeps = {}): () => void {
263
306
  // 행 등록을 갈아 끼운 호출자(시험)는 실 manifest 를 안 건드린다 — 기본 녹음기는 기본 행 등록과 짝일 때만.
264
307
  const startRunState = deps.startRunState ?? (deps.registerRow ? () => () => {} : startTuiRunStateRecorder);
265
308
  try { stopRunState = startRunState(surfaceId); } catch { /* fail-soft — recorder logs its own write failures */ }
309
+ // 미룬 우편 깨움(TUI-H4) — 이 TUI 가 턴 중·5분 창이라 못 받은 깨움을 idle 로 «기록»된 뒤 한 번 다시 두드린다.
310
+ // 실 행 등록과 짝일 때만(시험이 행 등록을 갈아 끼우면 0) · 무거운 모듈은 늦게 불러온다.
311
+ let stopWakePoller: () => void = () => {};
312
+ let wakePollerStopped = false;
313
+ if (deps.startWakePoller) {
314
+ try { stopWakePoller = deps.startWakePoller(surfaceId); } catch { /* fail-soft */ }
315
+ } else if (!deps.registerRow) {
316
+ void import('../loops/msg-wake.js').then(mod => {
317
+ if (!wakePollerStopped) stopWakePoller = mod.startPendingWakePoller(surfaceId);
318
+ }).catch(() => { /* fail-soft — the post-time wake still runs */ });
319
+ }
266
320
  const driveTicks = deps.driveTicks ?? ((tick, ms) => {
267
321
  const t = setInterval(tick, ms);
268
322
  (t as { unref?: () => void }).unref?.();
@@ -279,8 +333,11 @@ export function startTuiSelfReport(deps: TuiSelfReportDeps = {}): () => void {
279
333
  // The manifest row is published only after both input capabilities are
280
334
  // live. A listed TUI therefore always has a registered target and poller.
281
335
 
336
+ // 마지막으로 내보낸 화면 — 재등록이 frame 칸을 비우면 다시 적는다(거울은 바뀐 화면만 내보내 idle 이면 영영 빈 칸).
337
+ let lastEmittedText: string | null = null;
282
338
  const emitText = (text: string, cols: number, rows: number): void => {
283
339
  const at = now();
340
+ lastEmittedText = text;
284
341
  const frame: SelfReportFrame = { surfaceId, instance, kind: 'tui', mode: 'self-report', text, cols, rows, at, ...(runId ? { runId } : {}) };
285
342
  try { publishFrame(frame); } catch { /* fail-soft */ }
286
343
  // `at` is shared with the manifest write → its internal throttle keys
@@ -327,17 +384,103 @@ export function startTuiSelfReport(deps: TuiSelfReportDeps = {}): () => void {
327
384
  }
328
385
 
329
386
  // Heartbeat so a live-but-idle TUI isn't culled by reapStale.
330
- const hb = setInterval(() => { try { heartbeat(surfaceId, now()); } catch { /* fail-soft */ } }, heartbeatMs);
331
- (hb as { unref?: () => void }).unref?.();
332
-
387
+ // ⭐ 박동마다 자기 행을 본다 — 남이 걷어 간 행(정지 중 stale 수거 등)을 같은 박동에서 다시 세운다.
388
+ // 행이 없으면 pty text/key/snapshot·우편 깨움이 이 TUI 에 영영 안 닿는다(#75 · #84).
389
+ // 행 등록을 갈아 끼운 호출자(시험)는 실 manifest 를 안 읽는다 — 기본 조회는 기본 행 등록과 짝일 때만.
390
+ const lookupRow: (id: string) => TuiOwnRowView | null = deps.lookupRow
391
+ ?? (deps.registerRow ? () => ({ alive: true }) : (id: string) => getPtyManifest(id, { strict: true }));
392
+ const restoreBuild = deps.restoreBuild ?? (deps.registerRow ? () => {} : (id: string) => { updatePtyManifestBuild(id, runningBuild()); });
393
+ const logRowMissing = deps.logRowMissing ?? ((data: TuiRowMissingEvent) => debug.log('tui.self-report', 'row-missing', data));
394
+ const rowNickname = deps.nickname?.trim() || undefined;
395
+ let lastSeenAt = now();
396
+ let lastBeatAt = lastSeenAt;
397
+ let sigcontAt: number | null = null;
398
+ let stopSigcont: () => void = () => {};
399
+ try {
400
+ stopSigcont = (deps.onSigcont ?? ((fn) => {
401
+ process.on('SIGCONT', fn);
402
+ return () => { process.off('SIGCONT', fn); };
403
+ }))(() => { sigcontAt = now(); });
404
+ } catch { /* fail-soft — 단서일 뿐 */ }
333
405
  let stopped = false;
406
+ const beat = (): void => {
407
+ if (stopped) return;
408
+ const at = now();
409
+ const prevSeenAt = lastSeenAt;
410
+ const gapMs = at - lastBeatAt;
411
+ lastBeatAt = at;
412
+ let state: TuiRowMissingEvent['state'] | null = null;
413
+ let error: string | undefined;
414
+ try {
415
+ const row = lookupRow(surfaceId);
416
+ if (!row) state = 'absent';
417
+ else if (!row.alive) state = 'closed';
418
+ } catch (e) {
419
+ state = 'lookup-failed';
420
+ error = e instanceof Error ? e.message : String(e);
421
+ }
422
+ if (state === null) {
423
+ lastSeenAt = at;
424
+ try { heartbeat(surfaceId, at); } catch { /* fail-soft */ }
425
+ return;
426
+ }
427
+ let reRegistered = false;
428
+ let frameRestored = false;
429
+ let buildRestored = false;
430
+ if (state === 'lookup-failed') {
431
+ // ⛔ 실패를 «없다»로 읽지 않는다 — 재등록 없이 평소 박동만.
432
+ try { heartbeat(surfaceId, at); } catch { /* fail-soft */ }
433
+ } else {
434
+ try {
435
+ registerRow(surfaceId, at, rowNickname);
436
+ // 기본 행 등록은 fail-soft(조용히 삼킨다) — «다시 세웠다» 는 다시 읽어서만 말한다.
437
+ reRegistered = lookupRow(surfaceId)?.alive === true;
438
+ if (!reRegistered) throw new Error('row-still-missing-after-register');
439
+ lastSeenAt = at;
440
+ // 재등록은 실행 판·턴 칸을 비운다 — 판은 기동 때 값으로 다시 적는다. 턴은 비운 채(unknown) 둔다:
441
+ // 녹음기를 다시 열면 «idle» 을 적는데, 턴 도중이면 거짓 idle 이 깨움을 끼어들게 한다. 다음 턴 변화가 채운다.
442
+ const restoreErrors: string[] = [];
443
+ try { restoreBuild(surfaceId); } catch (e) { restoreErrors.push(`build: ${e instanceof Error ? e.message : String(e)}`); }
444
+ if (lastEmittedText !== null) {
445
+ try { writeFrame(surfaceId, lastEmittedText, at); } catch (e) { restoreErrors.push(`frame: ${e instanceof Error ? e.message : String(e)}`); }
446
+ }
447
+ // 기본 쓰기도 fail-soft — «복원했다» 는 다시 읽어서만 말한다.
448
+ try {
449
+ const after = lookupRow(surfaceId);
450
+ frameRestored = lastEmittedText !== null && (after?.frameAt ?? 0) >= at;
451
+ buildRestored = after?.build != null;
452
+ } catch (e) { restoreErrors.push(`verify: ${e instanceof Error ? e.message : String(e)}`); }
453
+ if (restoreErrors.length) error = restoreErrors.join('; ');
454
+ } catch (e) {
455
+ error = e instanceof Error ? e.message : String(e);
456
+ }
457
+ }
458
+ try {
459
+ logRowMissing({
460
+ surfaceId, pid: process.pid, state, lastSeenAt: prevSeenAt, sinceMs: at - prevSeenAt, gapMs, heartbeatMs,
461
+ sigcontAt, sigcontSinceLastSeen: sigcontAt !== null && sigcontAt >= prevSeenAt,
462
+ reRegistered, frameRestored, buildRestored, ...(error ? { error } : {}),
463
+ });
464
+ } catch { /* fail-soft diagnostic */ }
465
+ };
466
+ const stopHeartbeat = (deps.driveHeartbeat ?? ((tick, ms) => {
467
+ // setImmediate 로 한 칸 미룬다 — 정지(SIGSTOP·SIGTTIN)에서 풀리면 밀린 타이머가 SIGCONT 처리기보다 «먼저» 돈다
468
+ // (WSL bun 실측). 미뤄야 같은 박동의 row-missing 이 sigcontAt 을 본다.
469
+ const t = setInterval(() => { setImmediate(tick); }, ms);
470
+ (t as { unref?: () => void }).unref?.();
471
+ return () => clearInterval(t);
472
+ }))(beat, heartbeatMs);
473
+
334
474
  const stop = (): void => {
335
475
  if (stopped) return;
336
476
  stopped = true;
337
477
  try { stopSource(); } catch { /* fail-soft — unregisters observer / clears tick timer */ }
338
478
  try { mirror?.stop(); } catch { /* fail-soft — restores stdout.write */ }
339
- clearInterval(hb);
479
+ try { stopHeartbeat(); } catch { /* fail-soft */ }
480
+ try { stopSigcont(); } catch { /* fail-soft */ }
340
481
  try { stopRunState(); } catch { /* fail-soft */ }
482
+ wakePollerStopped = true;
483
+ try { stopWakePoller(); } catch { /* fail-soft */ }
341
484
  try { markClosed(surfaceId, now()); } catch { /* fail-soft */ }
342
485
  try { activeControlTarget?.deactivate(); } catch { /* fail-soft */ }
343
486
  try { stopControlPoller(); } catch { /* fail-soft */ }
@@ -17,6 +17,10 @@ import type { DevChatOpts } from '../self-dev/dev-pipeline.js';
17
17
  export interface ChatCliOpts {
18
18
  session?: string;
19
19
  new?: boolean;
20
+ /** `--continue` — 활성 세션 이어하기(명시). 대표 #73: 기본은 새 세션. */
21
+ continue?: boolean;
22
+ /** `--resume [id]` — id 면 그 세션, 값 없이(true) 면 활성 세션. */
23
+ resume?: string | boolean;
20
24
  json?: boolean;
21
25
  tools?: boolean;
22
26
  goalLoop?: boolean;
@@ -29,13 +33,17 @@ export interface ChatCliDeps {
29
33
  runDevPipeline?: typeof runDevPipeline;
30
34
  }
31
35
 
32
- /** CLI 옵션 → DevChatOpts(--new→forceNew·나머지 boolean 정규화). reuseActive 는 dispatch 클로저에서 !forceNew 파생.
36
+ /** CLI 옵션 → DevChatOpts(--new→forceNew·--continue/--resume→continueActive·나머지 boolean 정규화).
37
+ * 대표 #73 — reuseActive 는 dispatch 클로저에서 continueActive 로만 켠다(인자 없음 = 새 세션).
33
38
  * session 은 `!== undefined` 로 통과(원 액션 explicitSessionId:opts.session 과 정확 등가 — 빈 문자열도 그대로,
34
39
  * runChatTurnCli 가 falsy 처리해 결과는 동일하나 중간값까지 무손실 유지). */
35
40
  export function toDevChatOpts(opts: ChatCliOpts): DevChatOpts {
36
41
  return {
37
- ...(opts.session !== undefined ? { session: opts.session } : {}),
42
+ ...(opts.session !== undefined
43
+ ? { session: opts.session }
44
+ : typeof opts.resume === 'string' ? { session: opts.resume } : {}),
38
45
  forceNew: opts.new === true,
46
+ continueActive: opts.continue === true || opts.resume === true,
39
47
  json: opts.json === true,
40
48
  enableTools: opts.tools === true,
41
49
  goalLoop: opts.goalLoop === true,
package/src/chat/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  // Integrates into the dashboard log pane as an inline chat
3
3
 
4
4
  import { getGrokApiKey, GROK_MODEL, GROK_API_URL } from '../config.js';
5
- import { C, ansi, KeyStreamParser, readKey, traceKey, traceKeyListener, termSize, pad, visibleWidth, stripAnsi, truncate, render, hLine, closeTui, resetRenderCache, invalidateRenderCacheFromRow, injectKey } from '../tui.js';
5
+ import { C, ansi, KeyStreamParser, readKey, traceKey, traceKeyListener, termSize, pad, visibleWidth, stripAnsi, truncate, render, hLine, closeTui, resetRenderCache, invalidateRenderCacheFromRow, injectKey, takeInjectedKeys, cancelPendingReadKey } from '../tui.js';
6
6
  import { paintCursorMove, paintCursorVisibility, type CursorState } from '../display/cursor-state.js';
7
7
  import { firstVisibleInputLineIdx, inputLineWindow } from '../display/prompt-frame.js';
8
8
  import { createChatPickerFamilySource, createChatPickerFamilySources } from './pickers/modals.js';
@@ -10,6 +10,7 @@ import type { ChatPickerKind } from './pickers/kinds.js';
10
10
  import { createPickerState, type BufferAction, type PickerBufferView } from './pickers/state.js';
11
11
  import { createChatPickerModalRuntime } from './pickers/modal-runtime.js';
12
12
  import type { ModalSurface } from '../display/modal-stack.js';
13
+ import type { PromptRowOwner } from '../display/prompt-row-owner.js';
13
14
  // Type-only import: avoids the runtime circular dep that streamGrok
14
15
  // below sidesteps with a dynamic `await import('../llm.js')`. Keeping
15
16
  // ChatMessage structurally compatible with LLMMessage lets the
@@ -35,6 +36,7 @@ import {
35
36
  } from '../input-core/index.js';
36
37
  import { applyInlineEditorKey } from '../input-core/inline-editor-key.js';
37
38
  import type { InputSourceRef } from '../input/input-source-kind.js';
39
+ import { routeRawPtyStop } from '../input/external-input-queue.js';
38
40
  import {
39
41
  multilineEditorBackspace,
40
42
  multilineEditorInsertLineBreak,
@@ -70,6 +72,7 @@ export interface ModalSink {
70
72
  * DisplayCoordinator that satisfies both. */
71
73
  export interface DisplaySink extends CursorSink, ModalSink {}
72
74
  import type { Key } from '../tui.js';
75
+ import { noteInputLagKey, noteInputLagPaint } from '../tui/input-lag-probe.js';
73
76
  import {
74
77
  createSpinner,
75
78
  createToolLoader,
@@ -173,6 +176,8 @@ function writeTerminal(chunk: string): void {
173
176
  process.stdout.write(chunk);
174
177
  // viaCoordinator=false — this is the bypass path /perf highlights.
175
178
  perf.recordStdoutWrite(chunk.length, false);
179
+ // 입력칸 키 echo 는 render() 가 아니라 이 직접 쓰기로 칠해진다 — 키→칠 관측의 칠 지점.
180
+ noteInputLagPaint();
176
181
  }
177
182
 
178
183
  /** textInput reports the current prompt's top row so writeTerminal
@@ -248,6 +253,8 @@ export interface TextInputRenderActions {
248
253
  repaintUserMutation: () => void;
249
254
  }
250
255
 
256
+ /** Prefix painted in place of the prompt on input continuation rows. */
257
+ const TEXT_INPUT_CONTINUATION_PREFIX = ' \u00B7 ';
251
258
  const TEXT_INPUT_CURSOR_PROTOCOL_ENABLE = '\x1b[>1u\x1b[>4;2m';
252
259
  const TEXT_INPUT_CURSOR_PROTOCOL_DISABLE = '\x1b[<u\x1b[>4;0m';
253
260
  const SYNCHRONIZED_OUTPUT_BEGIN = '\x1b[?2026h';
@@ -322,11 +329,16 @@ export function createTextInputRenderActions(opts: {
322
329
  * coordinator-owned cursor sinks re-show it at the final position. */
323
330
  hideCursorBeforePaint?: boolean;
324
331
  beforePaint?: () => void;
332
+ /** The frame renderer owns the prompt band (TUI-PROMPT-SINGLE-OWNER):
333
+ * `paint` only publishes, so there are no direct writes to wrap in
334
+ * synchronized output. */
335
+ frameOwned?: boolean;
325
336
  modalSink?: ModalSink;
326
337
  shouldRequestModalRender?: () => boolean;
327
338
  }): TextInputRenderActions {
328
- const paintAll = (synchronizedOutput = false) => {
339
+ const paintAll = (requestSynchronizedOutput = false) => {
329
340
  if (opts.shouldPaint?.() === false) return false;
341
+ const synchronizedOutput = requestSynchronizedOutput && !opts.frameOwned;
330
342
  if (synchronizedOutput) writeTerminal(SYNCHRONIZED_OUTPUT_BEGIN);
331
343
  try {
332
344
  if (opts.beforePaint) {
@@ -678,6 +690,20 @@ export interface InputResult {
678
690
  * similar. textInput itself doesn't act on the chord beyond
679
691
  * returning — the host decides. */
680
692
  saved?: boolean;
693
+ /** H2 내부 턴 문 — 입력칸이 «비켜 줬다»(버퍼가 비어 있었다). 텍스트 없음 · 제출 아님. 호스트는
694
+ * 내부 턴 문(`InternalTurnGate.takePending`)에서 실행할 턴을 꺼낸다. */
695
+ yieldedToInternalTurn?: true;
696
+ }
697
+
698
+ /** H2 내부 턴 문이 마운트된 textInput 에 «비켜 달라»를 청하는 자리.
699
+ * ⛔ 입력칸 버퍼·합성 키를 쓰지 않는다 — textInput 은 버퍼가 «비었을 때만» 스스로 물러난다. */
700
+ export interface TextInputInternalTurnYieldPort {
701
+ /** textInput 이 마운트되면 부른다. 넘긴 함수는 버퍼가 비었으면 true(물러남 예약), 아니면 false. */
702
+ attach(requestYield: () => boolean): void;
703
+ /** textInput 이 내려가면 부른다. `yielded` 가 아니면 열린 내부 턴은 거둬진다(사람이 먼저 끝냈다). */
704
+ detach(opts?: { yielded?: boolean }): void;
705
+ /** 물러남을 예약한 뒤 그 사이 사람이 글자를 넣어 «물러나지 않았다». */
706
+ declined?(detail: string): void;
681
707
  }
682
708
 
683
709
  export interface TextInputExternalSubmitRequest {
@@ -821,6 +847,10 @@ export async function textInput(opts: {
821
847
  * input is idle. */
822
848
  insertAtCursor?: (text: string) => void;
823
849
  };
850
+ /** TUI-PROMPT-SINGLE-OWNER — when supplied, the frame renderer owns
851
+ * the prompt band: drawInput publishes its rows/hint/caret here and
852
+ * writes nothing to the prompt rows itself (no direct `\x1b[2K`). */
853
+ promptRowOwner?: PromptRowOwner;
824
854
  /** P2.2.c — sink for cursor placement. When supplied, drawInput
825
855
  * routes its caret-position decision through this instead of
826
856
  * emitting `\\x1b[r;cH` directly. The coordinator owns the
@@ -895,6 +925,8 @@ export async function textInput(opts: {
895
925
  * side-effect boundary instead of a flat callback bag. Legacy
896
926
  * fields above remain supported for compatibility/tests. */
897
927
  host?: TextInputHost;
928
+ /** H2 내부 턴 문 — 버퍼가 비었을 때 입력 루프가 물러나 호스트가 내부 턴을 실행하게 한다. */
929
+ internalTurnYield?: TextInputInternalTurnYieldPort;
898
930
  }): Promise<InputResult> {
899
931
  const { row: initialRow, col, width, maxLines = 5, prompt = '\u276f ', placeholder = '' } = opts;
900
932
  const getWidth = (): number => opts.getWidth?.() ?? width;
@@ -907,7 +939,8 @@ export async function textInput(opts: {
907
939
  setInputPromptStartRow(row);
908
940
  const commands = opts.commands ?? SLASH_COMMANDS;
909
941
  const history = opts.history ?? [];
910
- let lines: string[] = [opts.initialText ?? ''];
942
+ // 턴 중 typeahead 가 Shift+Enter 로 만든 여러 줄 prefill 은 줄 단위로 연다.
943
+ let lines: string[] = (opts.initialText ?? '').split('\n');
911
944
  // Line-count reporting: only fires when the visible count actually
912
945
  // changes, so hosts don't re-render on every keystroke.
913
946
  const resolvedHost = resolveTextInputHost(opts);
@@ -915,8 +948,8 @@ export async function textInput(opts: {
915
948
  const onLinesChangeHandler = resolvedHost.onLinesChange;
916
949
  const dispatchGlobalAction = resolvedHost.dispatchGlobalAction;
917
950
  let lastReportedLines = -1;
918
- let lineIdx = 0; // current line
919
- let colIdx = lines[0]!.length; // cursor at end of initial text
951
+ let lineIdx = lines.length - 1; // current line
952
+ let colIdx = lines[lineIdx]!.length; // cursor at end of initial text
920
953
  let ctrlCArmedAt: number | null = null;
921
954
  let ctrlCHintTimer: ReturnType<typeof setTimeout> | null = null;
922
955
  let ctrlCHint: string | null = null;
@@ -1134,7 +1167,12 @@ export async function textInput(opts: {
1134
1167
  setInputPromptStartRow(row);
1135
1168
  const promptStr = C.accent(prompt);
1136
1169
  const promptW = visibleWidth(prompt);
1137
- const textW = Math.max(0, getWidth() - promptW - 1);
1170
+ // Continuation rows carry a 4-cell ` · ` prefix instead of the prompt,
1171
+ // so each row gets its own text width — sharing the first row's width
1172
+ // let continuation rows overrun the terminal by `contPfxW - promptW` cells.
1173
+ const contPfxW = visibleWidth(TEXT_INPUT_CONTINUATION_PREFIX);
1174
+ const textWFor = (idx: number): number =>
1175
+ Math.max(0, getWidth() - (idx === 0 ? promptW : contPfxW) - 1);
1138
1176
  const numLines = lines.length;
1139
1177
  // Visible window: at most `maxLines` rows on screen, but the buffer
1140
1178
  // (`lines`) may exceed that. `firstVisibleIdx` keeps the cursor's
@@ -1170,6 +1208,8 @@ export async function textInput(opts: {
1170
1208
  // from there as lines accumulate. `startOffset` is how many rows
1171
1209
  // up from `row` we start touching — zero when both current and
1172
1210
  // previous drew only one line.
1211
+ const promptRowOwner = opts.promptRowOwner;
1212
+ const ownedRows: string[] = [];
1173
1213
  for (let i = 0; i < rowsToTouch; i++) {
1174
1214
  const r = row - i; // i=0 → bottom row; i=1 → one row up; etc.
1175
1215
  if (r < 1) continue;
@@ -1177,18 +1217,20 @@ export async function textInput(opts: {
1177
1217
  if (i < visibleLines) {
1178
1218
  const lineIdxInArray = firstVisibleIdx + (visibleLines - 1 - i);
1179
1219
  const lineContent = lines[lineIdxInArray]!;
1180
- const pfx = lineIdxInArray === 0 ? promptStr : C.muted(' ' + '\u00B7' + ' ');
1220
+ const pfx = lineIdxInArray === 0 ? promptStr : C.muted(TEXT_INPUT_CONTINUATION_PREFIX);
1221
+ const rowTextW = textWFor(lineIdxInArray);
1181
1222
  const display = lineIdxInArray === 0 && numLines === 1 && !lineContent
1182
- ? truncate(C.muted(placeholder), Math.max(0, textW))
1223
+ ? truncate(C.muted(placeholder), Math.max(0, rowTextW))
1183
1224
  : inputLineWindow(
1184
1225
  lineContent,
1185
1226
  lineIdxInArray === lineIdx ? colIdx : lineContent.length,
1186
- textW,
1227
+ rowTextW,
1187
1228
  ).display;
1188
1229
 
1189
- const padded = display + ' '.repeat(Math.max(0, textW - visibleWidth(display)));
1190
- writeTerminal(ansi.moveTo(r, col) + '\x1b[2K' + pfx + padded);
1191
- } else {
1230
+ const padded = display + ' '.repeat(Math.max(0, rowTextW - visibleWidth(display)));
1231
+ if (promptRowOwner) ownedRows.unshift(pfx + padded);
1232
+ else writeTerminal(ansi.moveTo(r, col) + '\x1b[2K' + pfx + padded);
1233
+ } else if (!promptRowOwner) {
1192
1234
  // This row had content on the previous paint but doesn't anymore
1193
1235
  // (user deleted a line / shrank the input). Clear it so stale
1194
1236
  // text doesn't linger on what is now part of the log / divider
@@ -1198,7 +1240,9 @@ export async function textInput(opts: {
1198
1240
  }
1199
1241
  prevDrawnLines = visibleLines;
1200
1242
 
1201
- if (ctrlCHint) {
1243
+ if (promptRowOwner) {
1244
+ // The frame renders the hint row from the published paint.
1245
+ } else if (ctrlCHint) {
1202
1246
  writeTerminal(ansi.moveTo(row + 2, col) + '\x1b[2K' + C.muted(truncate(ctrlCHint, getWidth())));
1203
1247
  ctrlCHintPainted = true;
1204
1248
  } else if (ctrlCHintPainted) {
@@ -1216,9 +1260,15 @@ export async function textInput(opts: {
1216
1260
  Math.min(lineIdx - firstVisibleIdx, visibleLines - 1),
1217
1261
  );
1218
1262
  const curR = row - (visibleLines - 1 - cursorScreenLine);
1219
- const pfxW = lineIdx === 0 ? visibleWidth(prompt) : 4;
1220
- const { cursorCol } = inputLineWindow(lines[lineIdx]!, colIdx, textW);
1263
+ const pfxW = lineIdx === 0 ? visibleWidth(prompt) : contPfxW;
1264
+ const { cursorCol } = inputLineWindow(lines[lineIdx]!, colIdx, textWFor(lineIdx));
1221
1265
  const curX = col + pfxW + cursorCol;
1266
+ promptRowOwner?.publish({
1267
+ rows: ownedRows,
1268
+ hint: ctrlCHint ? C.muted(truncate(ctrlCHint, getWidth())) : null,
1269
+ caret: curR >= 1 ? { row: curR, col: curX, visible: true } : null,
1270
+ source: 'text-input',
1271
+ });
1222
1272
  // P2.2.c — coordinator owns the cursor emit when wired; falls
1223
1273
  // back to direct stdout for non-coordinator callers (tests, non-dashboard
1224
1274
  // entry points) so the change is non-breaking.
@@ -1317,19 +1367,28 @@ export async function textInput(opts: {
1317
1367
  const display = prefix + result;
1318
1368
  const padded = display + ' '.repeat(Math.max(0, textW - visibleWidth(display)));
1319
1369
 
1320
- for (let i = 0; i < rowsToTouch; i++) {
1321
- const r = row - i;
1322
- if (r < 1) continue;
1323
- if (i === 0) {
1324
- writeTerminal(ansi.moveTo(searchRow, col) + '\x1b[2K' + promptStr + padded);
1325
- } else {
1326
- writeTerminal(ansi.moveTo(r, col) + '\x1b[2K');
1370
+ const curR = searchRow;
1371
+ const curX = col + promptW + visibleWidth(prefix);
1372
+ if (opts.promptRowOwner) {
1373
+ opts.promptRowOwner.publish({
1374
+ rows: [promptStr + padded],
1375
+ hint: null,
1376
+ caret: { row: curR, col: curX, visible: true },
1377
+ source: 'reverse-search',
1378
+ });
1379
+ } else {
1380
+ for (let i = 0; i < rowsToTouch; i++) {
1381
+ const r = row - i;
1382
+ if (r < 1) continue;
1383
+ if (i === 0) {
1384
+ writeTerminal(ansi.moveTo(searchRow, col) + '\x1b[2K' + promptStr + padded);
1385
+ } else {
1386
+ writeTerminal(ansi.moveTo(r, col) + '\x1b[2K');
1387
+ }
1327
1388
  }
1328
1389
  }
1329
1390
  prevDrawnLines = visibleLines;
1330
1391
 
1331
- const curR = searchRow;
1332
- const curX = col + promptW + visibleWidth(prefix);
1333
1392
  if (opts.cursorSink && (opts.canClaimCursor?.() ?? true)) {
1334
1393
  opts.cursorSink.setCursor({ row: curR, col: curX, visible: true });
1335
1394
  } else if (!opts.cursorSink) {
@@ -1364,11 +1423,16 @@ export async function textInput(opts: {
1364
1423
  syncActivePickerModal();
1365
1424
  drawInput();
1366
1425
  };
1426
+ // A frame-owned prompt band has no direct paint to hide the cursor
1427
+ // for, wrap in synchronized output, or re-assert divider chrome around:
1428
+ // the frame render does all three in its own single write.
1429
+ const frameOwnsPromptBand = opts.promptRowOwner !== undefined;
1367
1430
  const renderActions = createTextInputRenderActions({
1368
1431
  shouldPaint: opts.shouldPaint,
1369
- paintChrome: opts.onPaintChrome,
1432
+ paintChrome: frameOwnsPromptBand ? undefined : opts.onPaintChrome,
1370
1433
  paint: repaintPure,
1371
- beforePaint: () => {
1434
+ frameOwned: frameOwnsPromptBand,
1435
+ beforePaint: frameOwnsPromptBand ? () => {} : () => {
1372
1436
  const chunk = hideTextInputCursor(opts.cursorSink);
1373
1437
  if (chunk) writeTerminal(chunk);
1374
1438
  else if (opts.cursorSink) writeTerminal(paintCursorVisibility(false));
@@ -1382,6 +1446,8 @@ export async function textInput(opts: {
1382
1446
  const finalizeInput = (result: InputResult): InputResult => {
1383
1447
  // 외부 주입 라우터가 «composer 가 안 떠 있다»를 알 수 있게 내린다.
1384
1448
  if (hostControl) hostControl.getBufferText = undefined;
1449
+ opts.promptRowOwner?.clear();
1450
+ detachInternalTurnYield(result.yieldedToInternalTurn === true);
1385
1451
  clearPicker();
1386
1452
  writeTerminal(endTextInputCursor(opts.cursorSink));
1387
1453
  return result;
@@ -1454,9 +1520,34 @@ export async function textInput(opts: {
1454
1520
  };
1455
1521
  }
1456
1522
 
1523
+ // ⭐ H2 내부 턴 문 — 버퍼가 비었을 때만 물러남을 예약하고 걸린 readKey 를 «빈 키»로 깨운다.
1524
+ // ⛔ 버퍼·커서·키 큐는 건드리지 않는다(대표 비침투). 마운트가 끝나면(어느 반환 길이든) 무효다.
1525
+ let internalYieldRequested = false;
1526
+ let internalYieldMounted = true;
1527
+ function detachInternalTurnYield(yielded = false): void {
1528
+ if (!internalYieldMounted) return;
1529
+ internalYieldMounted = false;
1530
+ internalYieldRequested = false;
1531
+ opts.internalTurnYield?.detach({ yielded });
1532
+ }
1533
+ opts.internalTurnYield?.attach(() => {
1534
+ if (!internalYieldMounted || lines.join('\n').length > 0) return false;
1535
+ internalYieldRequested = true;
1536
+ cancelPendingReadKey();
1537
+ return true;
1538
+ });
1539
+
1457
1540
  drawAll();
1458
1541
 
1459
1542
  while (true) {
1543
+ if (internalYieldRequested) {
1544
+ internalYieldRequested = false;
1545
+ if (lines.join('\n').length === 0) {
1546
+ return finalizeInput({ text: '', submitted: false, yieldedToInternalTurn: true });
1547
+ }
1548
+ // 판정과 물러남 사이에 사람이 글자를 넣었다 — 사람이 먼저다.
1549
+ opts.internalTurnYield?.declined?.('buffer');
1550
+ }
1460
1551
  // IDX-F2.5 — picker.onKey may have set pendingSubmit on the
1461
1552
  // previous iteration (the closure can't return from textInput
1462
1553
  // itself). Consume the signal at the top of the loop, tear
@@ -1471,6 +1562,7 @@ export async function textInput(opts: {
1471
1562
  }
1472
1563
 
1473
1564
  const key = await (opts.readKey ?? (() => readKey('input')))();
1565
+ if (internalYieldRequested && !key.name) continue; // H2 — 내부 턴 문이 깨운 빈 키
1474
1566
  traceAfterSubmitKey(key);
1475
1567
 
1476
1568
  // Raw-key trace — diagnoses "modifier bit dropped before global-action
@@ -1671,6 +1763,8 @@ export async function textInput(opts: {
1671
1763
  // input loop exits cleanly and the dashboard's pane dispatcher
1672
1764
  // picks up the keys.
1673
1765
  if (hostControl) hostControl.getBufferText = undefined;
1766
+ opts.promptRowOwner?.clear();
1767
+ detachInternalTurnYield();
1674
1768
  return { text: '', submitted: false, gotoPane: true };
1675
1769
  }
1676
1770
  drawAll();
@@ -2001,9 +2095,24 @@ export function attachStreamingKeys(
2001
2095
  // ⭐ 창 길이는 `readKey` 와 같은 25ms — 두 진입점이 같은 규칙을 쓴다.
2002
2096
  let escapeTimer: ReturnType<typeof setTimeout> | undefined;
2003
2097
  const clearEscapeTimer = () => { if (escapeTimer) { clearTimeout(escapeTimer); escapeTimer = undefined; } };
2098
+ // ⭐ TUI-ESC-ABORT-TOOLS (2026-10-15) — 바깥 키(`pty key` · 제어 IPC input-key)는 stdin 이
2099
+ // 아니라 `injectKey` 큐로 들어오고 빈 청크로 깨울 뿐이다. 이 리스너가 큐를 안 보면 턴 중
2100
+ // Esc 가 escGate 에 닿지 않고 다음 readKey(턴 끝)까지 잠든다. 주입이 먼저 왔으므로 먼저 배달한다.
2101
+ const deliverInjected = () => {
2102
+ const injected = takeInjectedKeys();
2103
+ if (injected.length === 0) return;
2104
+ for (const key of injected) debug.log('tui.input', 'injected-key-stream-delivered', { key: key.name });
2105
+ deliver(injected);
2106
+ };
2004
2107
  const listener = (data: string | Buffer) => {
2005
2108
  clearEscapeTimer();
2109
+ deliverInjected();
2110
+ // ⏹ TUI-STOP-RAW-PTY — 원시 pty 길로 한 청크에 온 `/stop⏎`·`/esc⏎` 는 typeahead 대기열 대신 지금 턴의 escGate 로.
2111
+ // 파서가 이스케이프·붙여넣기·UTF-8 조각을 쥐고 있으면 그 청크는 앞 입력의 이어짐이라 건드리지 않는다.
2112
+ if (!parser.hasPendingEscape() && !parser.hasPendingPaste() && !parser.hasPendingDecoderBytes()
2113
+ && routeRawPtyStop(typeof data === 'string' ? data : data.toString('utf8'))) return;
2006
2114
  const keys = parser.push(data);
2115
+ if (keys.length > 0) noteInputLagKey(keys.length);
2007
2116
  deliver(keys);
2008
2117
  // ⚠️ `unref()` — 이 타이머가 프로세스를 붙잡아 두면 안 된다(입력 대기는 stdin 의 몫).
2009
2118
  if (parser.hasPendingEscape()) {
@@ -2033,6 +2142,9 @@ export function attachStreamingKeys(
2033
2142
  // leaves streaming typeahead and lone Escape with no events at all.
2034
2143
  process.stdin.resume();
2035
2144
  traceKeyListener('attach', 'stream');
2145
+ // 턴 시작 «전»에 주입돼 큐에 남은 키도 배달한다 — 마이크로태스크로 미뤄 호출자가 cleanup 을
2146
+ // 손에 쥔 뒤에 handler 가 불리게 한다.
2147
+ queueMicrotask(() => { if (!cleanedUp) deliverInjected(); });
2036
2148
  return () => {
2037
2149
  if (cleanedUp) return;
2038
2150
  cleanedUp = true;
@@ -16,22 +16,24 @@ export interface TextInputControlState {
16
16
  }
17
17
 
18
18
  export function resolveTextInputControlAction(
19
- key: Pick<Key, 'name' | 'ctrl' | 'shift'>,
19
+ key: Pick<Key, 'name' | 'ctrl' | 'shift'> & { alt?: boolean },
20
20
  state: TextInputControlState,
21
21
  ): TextInputControlAction {
22
22
  const stripTrailingBackslash =
23
23
  key.name === 'enter'
24
24
  && state.cursor > 0
25
25
  && state.currentLine[state.cursor - 1] === '\\';
26
+ // ⭐ Alt+Enter 도 줄바꿈이다 — kitty 프로토콜을 켠 멀티플렉서(herdr)는 바깥의 `ESC CR` 을
27
+ // `CSI 13;3u`(alt) 로 바꿔 넘긴다. 종전엔 그 꼴이 «제출»로 떨어져 대체 키가 죽어 있었다.
26
28
  const isNewline =
27
- (key.name === 'enter' && key.shift)
29
+ (key.name === 'enter' && (key.shift || key.alt === true))
28
30
  || (key.name === 'j' && key.ctrl)
29
31
  || stripTrailingBackslash;
30
32
 
31
33
  if (isNewline) {
32
34
  return { kind: 'newline', stripTrailingBackslash };
33
35
  }
34
- if (key.name === 'enter' && !key.shift) {
36
+ if (key.name === 'enter' && !key.shift && !key.alt) {
35
37
  return { kind: 'submit' };
36
38
  }
37
39
  if (key.name === 'escape') {
@@ -146,6 +146,12 @@ export function createChatPickerModalRuntime(deps: ChatPickerModalRuntimeDeps):
146
146
  getInputZoneHeight: deps.getInputZoneHeight,
147
147
  width: deps.getBounds().width,
148
148
  getWidth: () => deps.getBounds().width,
149
+ // TUI-PICKER-RESIZE-SHRINK — follow the live prompt row, not the
150
+ // row captured when the family was created (stale after resize).
151
+ getAnchor: () => {
152
+ const b = deps.getBounds();
153
+ return { row: b.row, col: b.col };
154
+ },
149
155
  onKey: makePickerOnKey(kind),
150
156
  onRowClick: makePickerOnRowClick(kind),
151
157
  });