elanous 0.2.29 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (775) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  94. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  95. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  110. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-c219f2ed171131be.js} +1 -1
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/page-04d00ae9b0890349.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +7 -3
  279. package/graphs/context/nightly-condense.yaml +1 -0
  280. package/graphs/implement-loop.yaml +5 -0
  281. package/graphs/intake/intake-daily.yaml +8 -1
  282. package/graphs/intake/recipes.yaml +5 -0
  283. package/graphs/lecture/lecture-note.yaml +2 -2
  284. package/graphs/ops/harness-gc.yaml +1 -0
  285. package/graphs/release/recipes.yaml +3 -0
  286. package/graphs/release/release-loop.yaml +9 -5
  287. package/graphs/units/recipes.yaml +3 -0
  288. package/graphs/units/release-gate-recheck.yaml +15 -0
  289. package/package.json +2 -1
  290. package/scripts/check-native-tool-wiring.ts +3 -2
  291. package/scripts/ci-android-unit-tests.ts +16 -0
  292. package/scripts/ci-typecheck-changed.ts +63 -10
  293. package/scripts/coord-channel-watch.sh +22 -16
  294. package/scripts/coord-role-pack.ts +81 -2
  295. package/scripts/cron-run.ts +96 -3
  296. package/scripts/detect-test-interference.ts +38 -5
  297. package/scripts/gate-pr-cache.ts +65 -0
  298. package/scripts/gh-surface/capture.ts +126 -0
  299. package/scripts/gh-surface/gh +40 -0
  300. package/scripts/import-graph-scc.ts +38 -0
  301. package/scripts/install.ps1 +19 -0
  302. package/scripts/intake-social.ts +181 -0
  303. package/scripts/lecture-note/node.ts +71 -4
  304. package/scripts/lib/android-toolchain.ts +32 -0
  305. package/scripts/lib/deterministic-env.ts +62 -0
  306. package/scripts/lib/gate-test-env.ts +19 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/measure-si-task-cpu.ts +143 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +255 -0
  310. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  311. package/scripts/release-loop/cut-branch.ts +4 -3
  312. package/scripts/release-loop/export-check-node.ts +0 -1
  313. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  314. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  315. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  316. package/scripts/release-loop/gate-closure.ts +12 -8
  317. package/scripts/release-loop/gate-diff.ts +1 -1
  318. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  319. package/scripts/release-loop/gate-node.ts +523 -75
  320. package/scripts/release-loop/gate-partial.ts +106 -9
  321. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  322. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  323. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  324. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  325. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  326. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  327. package/scripts/release-loop/import-graph-scc.ts +215 -0
  328. package/scripts/release-loop/node-verdict.ts +2 -0
  329. package/scripts/release-loop/prepare-node.ts +102 -4
  330. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  331. package/scripts/release-loop/resume-release.ts +33 -4
  332. package/scripts/release-loop/resume.ts +13 -5
  333. package/scripts/release-loop/spawn-lane.ts +2 -19
  334. package/scripts/release-loop/tui-sim-node.ts +3 -2
  335. package/scripts/release-loop/unattended-release.ts +16 -0
  336. package/scripts/test-deterministic.ts +5 -61
  337. package/scripts/train-reach-grouping.ts +48 -0
  338. package/scripts/tsc-incremental-cache.ts +86 -0
  339. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  340. package/scripts/tsc-main-safety-net.ts +2 -2
  341. package/src/acp/client.ts +4 -1
  342. package/src/acp/core-turn-bridge.ts +65 -8
  343. package/src/acp/elanous-extensions.ts +3 -0
  344. package/src/acp/server.ts +3 -0
  345. package/src/acp/tool-trace.ts +186 -11
  346. package/src/ad-pipeline/run.ts +4 -2
  347. package/src/agent/runner.ts +169 -3
  348. package/src/agent/self-ambient-cache.ts +156 -0
  349. package/src/agent/self-ambient.ts +8 -1
  350. package/src/agent/subagent-callable.ts +3 -2
  351. package/src/agent/task-notification.ts +5 -0
  352. package/src/agent-mission/review-loop.ts +6 -3
  353. package/src/agent-substrate/acp-implementer.ts +14 -2
  354. package/src/agent-substrate/pr-reviewer.ts +14 -0
  355. package/src/agent-substrate/self-review-cli.ts +30 -4
  356. package/src/ask-user-question/tool.ts +22 -0
  357. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  358. package/src/autopilot/pr-manager.ts +80 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/capture/frame-state-detect.ts +39 -0
  361. package/src/capture/tui-self-report.ts +149 -6
  362. package/src/chat/chat-cli.ts +10 -2
  363. package/src/chat/index.ts +138 -26
  364. package/src/chat/input-control-key.ts +5 -3
  365. package/src/chat/pickers/modal-runtime.ts +6 -0
  366. package/src/chat/pickers/modals.ts +8 -2
  367. package/src/chat/tool-interrupt-behavior.ts +38 -0
  368. package/src/chat/tool-render/dispatch.ts +5 -1
  369. package/src/chat/turn-typeahead.ts +75 -20
  370. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  371. package/src/cli/agent-cli.ts +41 -13
  372. package/src/cli/ask-bare.ts +1 -0
  373. package/src/cli/config-audit.ts +123 -0
  374. package/src/cli/decisions-cli.ts +80 -6
  375. package/src/cli/import-cli.ts +12 -0
  376. package/src/cli/log-event-names.ts +17 -0
  377. package/src/cli/mcp-login.ts +21 -5
  378. package/src/cli/msg-cli.ts +89 -0
  379. package/src/cli/pod-cli.ts +14 -3
  380. package/src/cli/pr-cli.ts +273 -81
  381. package/src/cli/pr-land-base-read.ts +34 -0
  382. package/src/cli/pr-land-heavy-remote.ts +82 -26
  383. package/src/cli/pr-land-overlap-evidence.ts +109 -11
  384. package/src/cli/pr-land-pod-shadow-job.ts +106 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-refusal.ts +20 -5
  387. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  388. package/src/cli/pty-takeover-cli.ts +88 -14
  389. package/src/cli/release-cli.ts +80 -14
  390. package/src/cli/seat-cli.ts +138 -3
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/sim-cli.ts +18 -0
  393. package/src/cli/tasks-cli.ts +97 -19
  394. package/src/context-bus/context-first.ts +13 -0
  395. package/src/context-bus/context-now.ts +13 -2
  396. package/src/context-bus/ops-events.ts +79 -0
  397. package/src/control-plane/lease-holder.ts +12 -8
  398. package/src/control-plane/ledger.ts +163 -4
  399. package/src/control-plane/server.ts +91 -11
  400. package/src/core-turn/run-core-turn.ts +2 -0
  401. package/src/core-turn/run-goal-loop.ts +243 -3
  402. package/src/core-turn/seat-turn-cap.ts +79 -0
  403. package/src/core-turn/short-question.ts +38 -6
  404. package/src/core-turn/types.ts +6 -0
  405. package/src/dashboard/acp-active-model.ts +42 -1
  406. package/src/dashboard/acp-boot.ts +3 -0
  407. package/src/dashboard/background-jobs-status.ts +66 -0
  408. package/src/dashboard/index.ts +339 -657
  409. package/src/dashboard/input/agent-wake.ts +242 -0
  410. package/src/dashboard/input/chat-main-entry-runtime.ts +6 -1
  411. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  412. package/src/dashboard/input/chat-main-session.ts +8 -1
  413. package/src/dashboard/input/chat-main-turn.ts +12 -3
  414. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  415. package/src/dashboard/input/external-input-host.ts +49 -9
  416. package/src/dashboard/input/internal-turn.ts +261 -0
  417. package/src/dashboard/input/mouse-wiring.ts +108 -11
  418. package/src/dashboard/input/seat-autowake.ts +318 -0
  419. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  420. package/src/dashboard/log-click-runtime.ts +118 -2
  421. package/src/dashboard/loop-scheduler.ts +72 -0
  422. package/src/dashboard/seat-boot-preamble.ts +18 -0
  423. package/src/dashboard/skill-runtime.ts +2 -0
  424. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  425. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  426. package/src/dashboard/slash-runtime/index.ts +13 -0
  427. package/src/dashboard/turn-busy-teardown.ts +50 -0
  428. package/src/dashboard/turn-preamble.ts +116 -40
  429. package/src/dashboard/turn-session-layers.ts +4 -2
  430. package/src/dashboard/turn-start-segments.ts +222 -0
  431. package/src/decisions/decision-ledger.ts +45 -4
  432. package/src/discord-self-message.ts +4 -4
  433. package/src/display/prompt-row-owner.ts +146 -0
  434. package/src/display/resize-listener.ts +33 -2
  435. package/src/domains/release-tool.ts +18 -1
  436. package/src/field-note/transcribe.ts +17 -0
  437. package/src/fold-stack.ts +4 -2
  438. package/src/git-fs/index.ts +263 -36
  439. package/src/github/remote-call.ts +81 -0
  440. package/src/goals/registry.ts +46 -6
  441. package/src/goals/types.ts +7 -1
  442. package/src/graph-runner/runner.ts +1 -0
  443. package/src/grok/credential.ts +26 -0
  444. package/src/harness/gate-reserve.ts +87 -0
  445. package/src/harness/harness-clean.ts +2 -1
  446. package/src/harness/harness-cli-command.ts +52 -5
  447. package/src/harness/harness-gc.ts +2 -1
  448. package/src/harness/harness-incidents.ts +70 -20
  449. package/src/harness/harness-pod-dispatch.ts +87 -10
  450. package/src/harness/harness-queue.ts +68 -4
  451. package/src/harness/harness-stop.ts +4 -3
  452. package/src/harness/harness-substrate-default.ts +78 -7
  453. package/src/harness/harness-worktree-auto.ts +2 -1
  454. package/src/harness/harness-worktrees.ts +3 -2
  455. package/src/hooks/dispatch.ts +2 -1
  456. package/src/index.ts +156 -27
  457. package/src/input/external-input-queue.ts +64 -7
  458. package/src/intake-plane/slash.ts +14 -3
  459. package/src/keybindings.ts +4 -1
  460. package/src/llm/route-decision.ts +36 -0
  461. package/src/llm/tool-loop-steered-rejection.ts +41 -0
  462. package/src/llm-request-shape.ts +209 -0
  463. package/src/llm.ts +301 -283
  464. package/src/loops/consensus.ts +348 -0
  465. package/src/loops/msg-wake.ts +206 -4
  466. package/src/loops/observe.ts +19 -3
  467. package/src/loops/orchestrator/tick.ts +88 -12
  468. package/src/loops/orchestrator/traffic.ts +64 -1
  469. package/src/loops/registry.ts +30 -0
  470. package/src/market/signed-index.ts +14 -0
  471. package/src/maturity/feature-maturity.ts +1 -1
  472. package/src/mcp/mcp-oauth.ts +54 -5
  473. package/src/models/prompts.ts +28 -0
  474. package/src/msg/msg-sse-client.ts +223 -0
  475. package/src/msg/msg-store.ts +86 -2
  476. package/src/mss/logging/log-store.ts +225 -1
  477. package/src/mss/logging/render-categories.ts +5 -0
  478. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  479. package/src/nexus/api/http-server.ts +54 -15
  480. package/src/nexus/api/loop-resources.ts +19 -3
  481. package/src/nexus/api/ops-api.ts +11 -0
  482. package/src/nexus/daemon-thin-inventory.md +37 -0
  483. package/src/nexus/index.ts +70 -0
  484. package/src/nexus/state/state.ts +1 -0
  485. package/src/oauth/store.ts +32 -7
  486. package/src/onboarding/first-run.ts +28 -3
  487. package/src/ops/overview-cache.ts +16 -4
  488. package/src/ops/overview.ts +59 -2
  489. package/src/ops/resources.ts +82 -0
  490. package/src/plugins/maker/connector-maker.ts +41 -0
  491. package/src/plugins/maker/skill-maker.ts +42 -0
  492. package/src/pr-tool/census.ts +303 -0
  493. package/src/pr-tool/inflight-registry.ts +143 -0
  494. package/src/prompt-library/chat-conciseness.ts +13 -0
  495. package/src/prompt-library/universal-preamble.ts +10 -5
  496. package/src/pty-shell/pty-manifest.ts +12 -3
  497. package/src/pty-shell/tui-run-state.ts +34 -3
  498. package/src/release-loop/gate-host-reservation.ts +97 -0
  499. package/src/release-loop/landing-freeze.ts +5 -0
  500. package/src/release-loop/light-rc.ts +5 -2
  501. package/src/release-loop/placement.ts +92 -1
  502. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  503. package/src/release-loop/rehearsal.ts +73 -17
  504. package/src/repl/index.ts +20 -2
  505. package/src/seat-loop/seat-knowhow.ts +282 -0
  506. package/src/seat-loop/seat-loop.ts +41 -2
  507. package/src/seat-loop/traffic-signal.ts +5 -1
  508. package/src/self-dev/ask-launch-flow.ts +37 -3
  509. package/src/self-dev/decompose-compose-graph.ts +28 -27
  510. package/src/self-dev/decompose-proposal.ts +53 -38
  511. package/src/self-dev/decompose.ts +17 -0
  512. package/src/self-dev/dev-pipeline.ts +31 -2
  513. package/src/self-dev/draft-residue.ts +267 -33
  514. package/src/self-dev/draft-sweep.ts +59 -4
  515. package/src/self-dev/external-call-zero.ts +77 -0
  516. package/src/self-dev/launch-preflight-text.ts +6 -0
  517. package/src/self-dev/launch-preflight.ts +25 -3
  518. package/src/self-dev/local-supervisor-judge.ts +185 -0
  519. package/src/self-dev/run-supervisor.ts +229 -19
  520. package/src/self-dev/run-types.ts +20 -0
  521. package/src/self-dev/shard-aggregate.ts +13 -2
  522. package/src/self-dev/shard-plan.ts +56 -1
  523. package/src/self-dev/shard-run.ts +207 -12
  524. package/src/self-dev/spawn-lane-files.ts +19 -0
  525. package/src/self-implement/app-api-budget.ts +51 -11
  526. package/src/self-implement/config-gate.ts +2 -1
  527. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  528. package/src/self-implement/expose-gate.ts +2 -1
  529. package/src/self-implement/follow-up-placement.ts +79 -0
  530. package/src/self-implement/gate-artifacts.ts +416 -0
  531. package/src/self-implement/gate-baseline.ts +96 -5
  532. package/src/self-implement/gate-cli.ts +207 -17
  533. package/src/self-implement/gate-remote.ts +136 -26
  534. package/src/self-implement/gate-scenario.ts +85 -0
  535. package/src/self-implement/goal-author.ts +160 -8
  536. package/src/self-implement/graph-authority.ts +38 -6
  537. package/src/self-implement/graph-overlay-condition.ts +92 -1
  538. package/src/self-implement/heal-triage.ts +79 -0
  539. package/src/self-implement/host-regate.ts +97 -7
  540. package/src/self-implement/orchestrator.ts +115 -134
  541. package/src/self-implement/pr-title.ts +123 -0
  542. package/src/self-implement/run-checkpoint.ts +235 -0
  543. package/src/self-implement/run-ledger.ts +162 -15
  544. package/src/self-implement/run-stop.ts +4 -3
  545. package/src/self-implement/run-ttl.ts +28 -4
  546. package/src/self-implement/seams.ts +2 -0
  547. package/src/self-implement/shadow-stage.ts +7 -6
  548. package/src/self-implement/stop-autoheal.ts +2 -1
  549. package/src/self-implement/train-gate-remote.ts +37 -8
  550. package/src/self-implement/train-reach-grouping.ts +157 -0
  551. package/src/self-implement/train-scenario-layers.ts +133 -0
  552. package/src/self-implement/uncommitted-work.ts +2 -0
  553. package/src/session/pending-input.ts +19 -0
  554. package/src/session/session-start.ts +224 -0
  555. package/src/session-runtime/index.ts +22 -267
  556. package/src/session-runtime/parallel-dispatch.ts +22 -5
  557. package/src/shell-runner/background-surface.ts +15 -5
  558. package/src/skills/tools/agent.ts +39 -6
  559. package/src/skills/tools/dev-harness.ts +6 -4
  560. package/src/skills/tools/list-dir.ts +11 -0
  561. package/src/skills/tools/schedule-wakeup.ts +408 -0
  562. package/src/skills/tools/shell.ts +246 -4
  563. package/src/status/bar.ts +26 -0
  564. package/src/steward/digest-delivery.ts +118 -0
  565. package/src/steward/hold-hygiene.ts +120 -0
  566. package/src/steward/resync-tick.ts +114 -23
  567. package/src/steward/ta-repair-event-collect.ts +158 -0
  568. package/src/steward/triage.ts +10 -0
  569. package/src/surface/shell-runner-boot.ts +5 -2
  570. package/src/task-agent/card-evidence.ts +25 -1
  571. package/src/task-agent/green-sweep.ts +8 -3
  572. package/src/task-agent/judge.ts +76 -0
  573. package/src/task-agent/land-queue.ts +79 -0
  574. package/src/task-agent/live-moves.ts +30 -9
  575. package/src/task-agent/postland-card.ts +5 -0
  576. package/src/task-agent/prelaunch-already-done.ts +98 -0
  577. package/src/task-agent/real-launch-guard.ts +37 -0
  578. package/src/task-agent/rejudge-on-head.ts +89 -12
  579. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  580. package/src/task-agent/repair-cycle.ts +45 -7
  581. package/src/task-agent/repair-worker.ts +7 -0
  582. package/src/task-agent/run-identity.ts +200 -0
  583. package/src/task-agent/shadow.ts +50 -3
  584. package/src/task-agent/task-hand.ts +182 -5
  585. package/src/task-agent/train-landing.ts +77 -0
  586. package/src/task-agent/work-order.ts +104 -0
  587. package/src/task-orchestrator/surfaces/pod-command-job.ts +151 -37
  588. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  589. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  590. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  591. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  592. package/src/task-orchestrator/surfaces/pod-lease.ts +118 -6
  593. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  594. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  595. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  596. package/src/task-orchestrator/surfaces/pod-pool.ts +3 -1
  597. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  598. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +67 -0
  599. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  600. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  601. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  602. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +525 -0
  603. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  604. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  605. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +362 -0
  606. package/src/task-orchestrator/surfaces/self-implement-pod.ts +138 -19
  607. package/src/telegram.ts +2 -4
  608. package/src/tui/chat/execution-badge.ts +5 -1
  609. package/src/tui/input/pickers.ts +732 -0
  610. package/src/tui/input-lag-probe.ts +230 -0
  611. package/src/tui/slash/mission.ts +492 -0
  612. package/src/tui/slash/term.ts +877 -0
  613. package/src/tui-client/dashboard-session.ts +9 -0
  614. package/src/tui.ts +52 -0
  615. package/src/user-config/gemini-server-tools.ts +9 -0
  616. package/src/user-config.ts +53 -16
  617. package/src/util/spawn-sync-output.ts +7 -0
  618. package/src/ux-sim/fake-bin.ts +154 -0
  619. package/src/ux-sim/fake-clock.ts +36 -0
  620. package/src/ux-sim/headless-tui.ts +72 -0
  621. package/src/ux-sim/in-process-cli.ts +2 -1
  622. package/src/ux-sim/scenario.ts +255 -0
  623. package/src/ux-sim/temp-git-remote.ts +82 -0
  624. package/src/version/packed-revision.json +1 -1
  625. package/src/video-pipeline/recipes/vlog.ts +25 -7
  626. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  630. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  632. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  635. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  636. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  639. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  641. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  647. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  651. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  662. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  668. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  671. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  672. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  673. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  676. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  678. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  679. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  680. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  682. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  688. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  695. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  698. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  703. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  705. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  768. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  774. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +0 -1
  775. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_ssgManifest.js +0 -0
@@ -0,0 +1,86 @@
1
+ /** Opt-in compiler graph cache for an exclusive, stable remote gate checkout. */
2
+ import { createHash } from 'node:crypto';
3
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { hostname } from 'node:os';
5
+ import { isAbsolute, join } from 'node:path';
6
+ import { normalizedDiagnosticSet } from './tsc-incremental-diagnostics.js';
7
+
8
+ export interface CachedTscRun { out: string; ran: boolean; why?: string; exitCode?: number }
9
+ type Reference = { schema: 1; key: string; out: string; exitCode: number; decision: boolean; head?: string };
10
+ export interface IncrementalCacheInput<T extends CachedTscRun> {
11
+ cwd: string;
12
+ base: string;
13
+ head?: string;
14
+ changed: ReadonlySet<string>;
15
+ config: string;
16
+ command: string;
17
+ cacheDir: string;
18
+ run: (command: string) => T;
19
+ decision: (result: T) => boolean;
20
+ log: (message: string) => void;
21
+ }
22
+
23
+ function compilerOutcome(result: CachedTscRun): 'clean' | 'diagnostics' | 'unmeasured' {
24
+ if (!result.ran) return 'unmeasured';
25
+ if (result.exitCode === 0) return 'clean';
26
+ return result.exitCode === 1 || result.exitCode === 2 ? 'diagnostics' : 'unmeasured';
27
+ }
28
+
29
+ function equivalent<T extends CachedTscRun>(current: T, baseline: T, decide: (result: T) => boolean): boolean {
30
+ const a = normalizedDiagnosticSet(current.out);
31
+ const b = normalizedDiagnosticSet(baseline.out);
32
+ return a !== null && a === b && compilerOutcome(current) !== 'unmeasured'
33
+ && compilerOutcome(current) === compilerOutcome(baseline) && decide(current) === decide(baseline);
34
+ }
35
+
36
+ export function incrementalCacheKey(input: Pick<IncrementalCacheInput<CachedTscRun>, 'cwd' | 'base' | 'changed' | 'config'>): string {
37
+ const files = [input.config, 'tsconfig.json', 'tsconfig.gate.json', 'tsconfig.pwa-env.json', 'apps/pwa/tsconfig.json', 'bun.lock', 'node_modules/typescript/package.json'];
38
+ const hash = createHash('sha256');
39
+ for (const field of [hostname(), input.cwd, input.base, ...[...input.changed].sort()]) hash.update(field + '\0');
40
+ for (const file of files) {
41
+ hash.update(file + '\0');
42
+ try { hash.update(readFileSync(join(input.cwd, file))); }
43
+ catch { hash.update('<missing>'); }
44
+ hash.update('\0');
45
+ }
46
+ return hash.digest('hex');
47
+ }
48
+
49
+ /** A cache hit is accepted only when the prior cold reference still has the same diagnostic set and gate decision. */
50
+ export function runIncrementalCachedTsc<T extends CachedTscRun>(input: IncrementalCacheInput<T>): T {
51
+ if (!isAbsolute(input.cacheDir) || !/^[-\w./]+$/.test(input.cacheDir) || !/^[0-9a-f]{40}$/.test(input.base)) return input.run(input.command);
52
+ const key = incrementalCacheKey(input);
53
+ try { mkdirSync(input.cacheDir, { recursive: true, mode: 0o700 }); }
54
+ catch (cause) {
55
+ input.log(`[tsc-cache] unavailable key=${key.slice(0, 12)} reason=${cause instanceof Error ? cause.message : String(cause)}; cold`);
56
+ return input.run(input.command);
57
+ }
58
+ const buildInfo = join(input.cacheDir, `${key}.tsbuildinfo`);
59
+ const metaFile = join(input.cacheDir, `${key}.json`);
60
+ let reference: Reference | null = null;
61
+ try {
62
+ const parsed = JSON.parse(readFileSync(metaFile, 'utf8')) as Reference;
63
+ if (parsed.schema === 1 && parsed.key === key && typeof parsed.out === 'string'
64
+ && Number.isInteger(parsed.exitCode) && typeof parsed.decision === 'boolean' && existsSync(buildInfo)) reference = parsed;
65
+ } catch { /* missing or damaged cache is a cold miss */ }
66
+ const incremental = input.run(`${input.command} --incremental --tsBuildInfoFile '${buildInfo}'`);
67
+ const prior = reference ? { out: reference.out, ran: true, exitCode: reference.exitCode } as T : null;
68
+ if (prior && equivalent(incremental, prior, input.decision) && input.decision(prior) === reference!.decision) {
69
+ input.log(`[tsc-cache] hit key=${key.slice(0, 12)} warmRc=${incremental.exitCode} coldRc=${prior.exitCode} warmGate=${input.decision(incremental) ? 'PASS' : 'FAIL'} coldGate=${reference!.decision ? 'PASS' : 'FAIL'}`);
70
+ return incremental;
71
+ }
72
+ const cold = input.run(input.command);
73
+ const matched = equivalent(incremental, cold, input.decision);
74
+ input.log(`[tsc-cache] ${reference ? 'mismatch-cold' : 'miss-cold'} key=${key.slice(0, 12)} warmRc=${incremental.exitCode ?? 'unknown'} coldRc=${cold.exitCode ?? 'unknown'} warmGate=${incremental.ran ? input.decision(incremental) ? 'PASS' : 'FAIL' : 'unmeasured'} coldGate=${cold.ran ? input.decision(cold) ? 'PASS' : 'FAIL' : 'unmeasured'} normalized=${matched ? 'same' : 'different'}`);
75
+ if (matched && cold.exitCode !== undefined) {
76
+ const next: Reference = { schema: 1, key, out: cold.out, exitCode: cold.exitCode, decision: input.decision(cold), head: input.head };
77
+ const temp = `${metaFile}.${process.pid}.tmp`;
78
+ try { writeFileSync(temp, JSON.stringify(next), { mode: 0o600 }); renameSync(temp, metaFile); }
79
+ catch {
80
+ for (const path of [temp, metaFile, buildInfo]) { try { rmSync(path, { force: true }); } catch { /* next run must cold-check damaged cache */ } }
81
+ }
82
+ } else {
83
+ for (const path of [metaFile, buildInfo]) { try { rmSync(path, { force: true }); } catch { /* invalid metadata remains a cold miss */ } }
84
+ }
85
+ return cold;
86
+ }
@@ -0,0 +1,76 @@
1
+ /** Diagnostic comparison for the incremental compiler. Only union member order is ignored. */
2
+
3
+ function atomAt(value: string, start: number): { text: string; end: number } | null {
4
+ if (value[start] === '"') {
5
+ const end = value.indexOf('"', start + 1);
6
+ return end < 0 ? null : { text: value.slice(start, end + 1), end: end + 1 };
7
+ }
8
+ const name = /^[A-Za-z_$][\w$]*/.exec(value.slice(start));
9
+ if (!name) return null;
10
+ let end = start + name[0].length;
11
+ if (value[end] === '<') {
12
+ let depth = 1;
13
+ let cursor = end + 1;
14
+ let quoted = false;
15
+ for (; cursor < value.length; cursor++) {
16
+ if (value[cursor] === '"' && value[cursor - 1] !== '\\') quoted = !quoted;
17
+ if (quoted) continue;
18
+ if (value[cursor] === '<') depth++;
19
+ else if (value[cursor] === '>' && --depth === 0) break;
20
+ }
21
+ if (depth === 0) end = cursor + 1;
22
+ }
23
+ const raw = value.slice(start, end);
24
+ return { text: raw.includes(' | ') && raw.includes('<') && raw.endsWith('>')
25
+ ? `${name[0]}<${normalizeUnionAtoms(raw.slice(name[0].length + 1, -1))}>` : raw, end };
26
+ }
27
+
28
+ function normalizeUnionAtoms(line: string): string {
29
+ let result = '';
30
+ for (let i = 0; i < line.length;) {
31
+ const first = atomAt(line, i);
32
+ if (!first || line.slice(first.end, first.end + 3) !== ' | ') {
33
+ if (first) { result += first.text; i = first.end; }
34
+ else { result += line[i]!; i++; }
35
+ continue;
36
+ }
37
+ const parts = [first.text];
38
+ let end = first.end;
39
+ while (line.slice(end, end + 3) === ' | ') {
40
+ const next = atomAt(line, end + 3);
41
+ if (!next) break;
42
+ parts.push(next.text);
43
+ end = next.end;
44
+ }
45
+ result += parts.sort().join(' | ');
46
+ i = end;
47
+ }
48
+ return result;
49
+ }
50
+
51
+ function normalizeDiagnosticLine(line: string): string {
52
+ // The observed reorder is a TypeScript union containing quoted literal members.
53
+ // Bare quoted prose such as 'a | b' may be a string value, so keep it byte-exact.
54
+ return line.replace(/'([^'\n]*\|[^'\n]*)'/g, (quoted, type: string) => type.includes('"') ? `'${normalizeUnionAtoms(type)}'` : quoted);
55
+ }
56
+
57
+ /** Include continuation lines; the existing gate parser reads only TS header lines. */
58
+ export function normalizedDiagnosticSet(output: string): string | null {
59
+ const blocks: string[] = [];
60
+ const other: string[] = [];
61
+ let block: string[] | null = null;
62
+ for (const line of output.split(/\r?\n/)) {
63
+ if (/^.+?\.[cm]?tsx?\(\d+,\d+\): error TS\d+:/.test(line)) {
64
+ if (block) blocks.push(block.map(normalizeDiagnosticLine).join('\n'));
65
+ block = [line];
66
+ } else if (block && /^\s/.test(line)) block.push(line);
67
+ else {
68
+ if (block) blocks.push(block.map(normalizeDiagnosticLine).join('\n'));
69
+ block = null;
70
+ if (line.trim()) other.push(line);
71
+ }
72
+ }
73
+ if (block) blocks.push(block.map(normalizeDiagnosticLine).join('\n'));
74
+ if (/error TS\d+/.test(output) && blocks.length === 0) return null;
75
+ return JSON.stringify({ blocks: blocks.sort(), other });
76
+ }
@@ -3,7 +3,7 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
3
3
  import { dirname, join, resolve } from 'node:path';
4
4
  import { debug } from '../src/debug/log.js';
5
5
  import { effectiveInstanceRoot } from '../src/instance/resolve.js';
6
- import { GATE_REMOTE_DEFAULTS, isValidGateHost, resolveGateRemoteSettings, runOnRemote, type ExecResult, type RemoteRunOptions, type RemoteRunOutcome } from '../src/self-implement/gate-remote.js';
6
+ import { GATE_REMOTE_DEFAULTS, gateRemoteHostCap, isValidGateHost, resolveGateRemoteSettings, runOnRemote, type ExecResult, type RemoteRunOptions, type RemoteRunOutcome } from '../src/self-implement/gate-remote.js';
7
7
  import { getUserConfig } from '../src/user-config.js';
8
8
  import { parseTypecheckErrors, tscEnv } from '../src/typecheck-ratchet.js';
9
9
  import { compareDiagnostics, normalizeDiagnostics, type NormalizedDiagnostic } from './tsc-baseline-comparison.js';
@@ -143,7 +143,7 @@ export async function runSafetyNet(repo: string, argv: readonly string[] = [], d
143
143
  diagnostics = diagnosticsOf(result, worktree);
144
144
  if (!diagnostics) reason = 'local tsc did not produce a complete measurement';
145
145
  } else {
146
- const result = remote({ repo: worktree, host, mirror: settings.mirror, hostCap: settings.hostCap, argv: TSC_ARGV });
146
+ const result = remote({ repo: worktree, host, mirror: settings.mirror, hostCap: gateRemoteHostCap(settings, host), argv: TSC_ARGV });
147
147
  if (result.kind === 'ran') {
148
148
  if (result.commit !== commit) throw new Error('remote measured a different commit');
149
149
  diagnostics = diagnosticsOf({ rc: result.rc, stdout: result.stdout.toString('utf8'), stderr: result.stderr.toString('utf8') }, worktree);
package/src/acp/client.ts CHANGED
@@ -692,6 +692,7 @@ export class AcpAgent {
692
692
  sessionId: SessionId;
693
693
  cwd?: string;
694
694
  mcpServers?: McpServer[];
695
+ _meta?: Record<string, unknown>;
695
696
  }): Promise<LoadSessionResponse> {
696
697
  if (!this.connection) throw new Error('AcpAgent not started');
697
698
  if (!this.peerCapabilities?.loadSession) {
@@ -701,6 +702,7 @@ export class AcpAgent {
701
702
  sessionId: req.sessionId,
702
703
  cwd: req.cwd ?? this.cwd,
703
704
  mcpServers: req.mcpServers ?? [],
705
+ ...(req._meta ? { _meta: req._meta } : {}),
704
706
  });
705
707
  }
706
708
 
@@ -764,13 +766,14 @@ export class AcpAgent {
764
766
 
765
767
  /** Begin a new session in the configured cwd. Returns the agent-
766
768
  * assigned sessionId — caller stores this for follow-up turns. */
767
- async newSession(): Promise<SessionId> {
769
+ async newSession(meta?: Record<string, unknown>): Promise<SessionId> {
768
770
  if (!this.connection) throw new Error('AcpAgent not started');
769
771
  let response;
770
772
  try {
771
773
  response = await this.connection.newSession({
772
774
  cwd: this.cwd,
773
775
  mcpServers: [],
776
+ ...(meta ? { _meta: meta } : {}),
774
777
  });
775
778
  } catch (error) {
776
779
  if (this.spec.id === 'claude'
@@ -43,6 +43,8 @@ import {
43
43
  type CoreTurnContext,
44
44
  type CoreTurnDispatchTool,
45
45
  } from '../core-turn/index.js';
46
+ import { stripGoalRepeatReadbackPreface } from '../core-turn/run-goal-loop.js';
47
+ import { parseSeatTurnCapConfig, resolveSeatTurnCap } from '../core-turn/seat-turn-cap.js';
46
48
  import { getUserConfig } from '../user-config.js';
47
49
  import { getModelFamily } from '../models/prompts.js';
48
50
  import { resolveModelContextWindow } from '../models/context-window.js';
@@ -50,7 +52,7 @@ import type { AcpServerOptions, AcpTurnContext } from './server.js';
50
52
  import { acpToolDenialResult } from './tool-approval.js';
51
53
  import { readOriginSessionMeta } from './origin-session-meta.js';
52
54
  import { isFactQuestion } from './fact-question.js';
53
- import { classifyTuiChatIntent, formatTuiRouteLine, type TuiChatRoute } from '../core-turn/short-question.js';
55
+ import { classifyTuiChatIntent, formatTuiRouteLine, isSeatOpsDirective, type TuiChatRoute } from '../core-turn/short-question.js';
54
56
  import { HARNESS_ROLE_ENV } from '../harness/harness-space.js';
55
57
 
56
58
  const FACT_QUESTION_INSTRUCTION = '사실·최신 정보 질문이다. WebSearch 를 1~2회 쓰고 검색 결과(제목·스니펫·URL)로 답하라. 출처 링크를 붙여라. 셸·브라우저·파일 도구는 검색 결과로 부족할 때만. 도구 예산에 닿으면 지금까지 근거로 답하고 끝에 «더 찾아볼까요?»를 붙여라.';
@@ -64,8 +66,10 @@ type QuickTuiRoute = Exclude<TuiChatRoute, '코딩·구현' | '읽기·분석'>;
64
66
  const QUICK_TOOLS: Record<QuickTuiRoute, readonly string[]> = {
65
67
  '조회': ['decisions_pending', 'ops_seats', 'ops_status', 'release_status', 'logs_query', 'context_now', 'memory_recall', 'Read'],
66
68
  '설정 변경': ['DashboardConfigGet', 'DashboardConfigSet', 'LlmListAvailableModels', 'prompt_getRuntimeConfig', 'prompt_setRuntimeConfig', 'view_getConfig', 'view_applyRuntimeConfig', 'view_saveConfig', 'memory_recall'],
67
- '조사': ['WebSearch', 'OmniSearch', 'Grep', 'Glob', 'Read', 'fact_check', 'memory_recall'],
68
- '상시 일': ['schedule_manage', 'schedule_list', 'schedule_create', 'schedule_update', 'session_manage', 'ops_status', 'memory_recall'],
69
+ // MsgList is a read-only ledger listing (never acks); MsgPost · MsgAck · RunShell · Bash stay out (TUI-QUICK-ROUTE-EXPLICIT-CMD).
70
+ '조사': ['WebSearch', 'OmniSearch', 'Grep', 'Glob', 'Read', 'fact_check', 'memory_recall', 'MsgList', 'Agent'],
71
+ // ScheduleWakeup (H5) wakes this TUI in-process; schedule_manage is OS cron — both belong to «상시 일».
72
+ '상시 일': ['schedule_manage', 'schedule_list', 'schedule_create', 'schedule_update', 'ScheduleWakeup', 'session_manage', 'ops_status', 'memory_recall'],
69
73
  };
70
74
 
71
75
  export function toolsForTuiRoute(tools: readonly LLMToolSpec[], route: QuickTuiRoute): LLMToolSpec[] {
@@ -133,6 +137,9 @@ export interface CoreTurnBridgeDeps {
133
137
  abortPollMs?: number;
134
138
  /** Only the in-process dashboard session opts into TUI routing; daemon ACP stays unchanged. */
135
139
  tuiRouting?: boolean;
140
+ /** TUI-H1-SEAT-GOALLOOP — the seat this TUI works for (`detectSeatTui`), read per turn. null/absent = a human
141
+ * conversation TUI (routing unchanged). A seat TUI sends operational directives to the goal loop. */
142
+ resolveSeat?: () => string | null;
136
143
  }
137
144
 
138
145
  /** Default abort-poll cadence. 50ms = 20 Hz: responsive without
@@ -228,16 +235,24 @@ export function bridgeCoreTurnToAcp(
228
235
  // Only a goal-driven harness child (explicit executor role — dev-harness · self-implement surfaces) keeps every
229
236
  // turn on the goal loop. A human TUI inside a harness space (one-word `dev --elanous`, `--hold`) is routed (UX 10-07).
230
237
  const harness = process.env[HARNESS_ROLE_ENV]?.trim() === 'executor';
238
+ // seatKnown=false: no resolver (or it threw) — routed as a human TUI, but the log keeps «unknown», not «not a seat».
239
+ let seat: string | null = null;
240
+ let seatKnown = false;
241
+ if (deps.tuiRouting && !harness && deps.resolveSeat) {
242
+ try { seat = deps.resolveSeat(); seatKnown = true; }
243
+ catch (error) { debug.log('chat.route', 'seat-unresolved', { error: String(error) }, { level: 'warn' }); }
244
+ }
231
245
  const route = deps.tuiRouting && !harness
232
246
  ? classifyTuiChatIntent(turnCtx.userText, {
233
247
  hasAttachments: turnCtx.promptBlocks?.some((block) => block.type !== 'text') ?? false,
248
+ seat: seat !== null,
234
249
  })
235
250
  : { route: '코딩·구현' as const, reason: harness ? 'harness' : 'legacy', goalLoop: true };
236
251
  const tools = !route.goalLoop && route.route !== '코딩·구현' && route.route !== '읽기·분석'
237
- ? toolsForTuiRoute(availableTools, route.route)
252
+ ? toolsForTuiRoute(availableTools, route.route) // bridgeCoreTurnToAcp applies route allowlists here.
238
253
  : availableTools;
239
254
  if (deps.tuiRouting) {
240
- debug.log('chat.route', 'decided', { route: route.route, reason: route.reason, goalLoop: route.goalLoop });
255
+ debug.log('chat.route', 'decided', { route: route.route, reason: route.reason, goalLoop: route.goalLoop, seat, seatKnown });
241
256
  // Only a quick route is announced: a coding turn's transcript stays exactly as before (preservation).
242
257
  // Awaited so the route line precedes the answer; a failed write is observed, not fatal to the turn.
243
258
  if (!route.goalLoop) {
@@ -253,6 +268,17 @@ export function bridgeCoreTurnToAcp(
253
268
  // 하드코딩 기본 ON 아님 — config 로 아밍(안전).
254
269
  const goalLoopCfg = getUserConfig().llm.goalLoop;
255
270
  const armGoalLoop = goalLoopCfg?.enabled === true && route.goalLoop;
271
+ // 인지(TUI-H1-SEAT-GOALLOOP) — 자리 TUI 의 운영 지시가 그래도 단일 턴이면(예: llm.goalLoop 꺼짐) 경고로 남긴다.
272
+ // 빠른 짧은 물음(short-*)은 자리에서도 «의도적» 단일 턴이라 경고에서 뺀다(«다음 행이 뭐야?»).
273
+ if (deps.tuiRouting && seat !== null && !armGoalLoop && !route.reason.startsWith('short-')
274
+ && isSeatOpsDirective(turnCtx.userText)) {
275
+ try {
276
+ debug.log('chat.route', 'seat-ops-single-turn', {
277
+ seat, route: route.route, reason: route.reason, goalLoop: route.goalLoop,
278
+ goalLoopEnabled: goalLoopCfg?.enabled === true,
279
+ }, { level: 'warn' });
280
+ } catch { /* observation cannot interrupt a turn */ }
281
+ }
256
282
  // 사실 질문 예산은 «단일 턴» 전용이다 — goal loop 와 겹치면 예산을 다 쓴 뒤에도 루프가 계속 재촉해
257
283
  // 매 continuation 이 «Tool budget reached» 로 거부되고, 모델은 그것을 도구 장애로 읽어 blocked 를 남긴다
258
284
  // (10-14 13:48 운영 TUI OP: route short-question·goalLoop ⊕ factQuestion → 소진 뒤 헛호출 7회).
@@ -292,6 +318,7 @@ export function bridgeCoreTurnToAcp(
292
318
  let finalSupplement: { answer: string; supplement: string; finalText: string } | null = null;
293
319
  // turnFamily 는 관측용으로만 유지(goal loop 아밍 판정은 위 사실 질문 판정 앞에서 한다).
294
320
  const turnModel = modelOverride ?? getUserConfig().llm.model;
321
+ let resolvedRoute: { provider: string; model: string } | null = null;
295
322
  const turnFamily = getModelFamily(turnModel);
296
323
  if (armGoalLoop) {
297
324
  // 관측 — 어느 family/모델에서 across-turn goal-loop 가 아밍됐나(전-family 개방 검증).
@@ -307,10 +334,17 @@ export function bridgeCoreTurnToAcp(
307
334
  safeguard: 'context-pressure-bail',
308
335
  });
309
336
  }
337
+ // TUI-SEAT-TURN-CAP — 자리 판정으로 goal loop 에 온 턴만 core 턴 상한·«할 일 0» 판정을 받는다(사람 TUI·하니스 자식 0).
338
+ const seatTurnCap = armGoalLoop && seat !== null && route.reason.startsWith('seat-')
339
+ ? { seat, ...resolveSeatTurnCap(parseSeatTurnCapConfig(getUserConfig().chat?.seatTurnCap)) }
340
+ : undefined;
310
341
  const runTurnDispatch = (c: CoreTurnContext): Promise<unknown> =>
311
342
  armGoalLoop
312
343
  ? runGoalLoop(c, {
313
344
  ...(goalLoopCfg?.maxIterations !== undefined ? { maxIterations: goalLoopCfg.maxIterations } : {}),
345
+ // #29 처방 — 자리 판정으로 goal loop 에 «되돌아온» 턴만 빈 evidence 완료를 답으로 받는다.
346
+ ...(route.reason.startsWith('seat-') ? { lenientCompletionEvidence: true } : {}),
347
+ ...(seatTurnCap !== undefined ? { seatTurnCap } : {}),
314
348
  ...(goalCtxWindow > 0 ? { contextTokenLimit: goalCtxWindow } : {}),
315
349
  })
316
350
  : runCoreTurn(c);
@@ -389,8 +423,18 @@ export function bridgeCoreTurnToAcp(
389
423
  void turnCtx.pushToolCall(call);
390
424
  },
391
425
  onToolResult: (call) => { void turnCtx.pushToolResult(call); },
426
+ // 실제로 응답한 공급자·모델을 기억한다 — 폴백 체인이 넘기면(예 codex → grok) 턴 모델(turnModel)과 달라진다.
427
+ // streamLLMWithTools 가 스트림을 (다시) 열 때마다 부른다 → 사용량 직전 값 = 그 사용량을 낸 쪽.
428
+ onResolvedProvider: (provider, model) => { resolvedRoute = { provider, model }; },
392
429
  // 턴 모델(라우팅 결과)을 실어 보낸다 — 대시보드 턴 지표가 설정 모델로 ctx·단가를 잡지 않게.
393
- onUsage: (usage) => { void turnCtx.pushUsage({ ...usage, model: usage.model ?? turnModel }); },
430
+ // ⭐ 폴백이면 «넘어간» 모델·공급자를 싣는다(TUI-MODEL-BADGE-ACTUAL · 완료 배지가 읽는다 · 상태줄·/model 은 후속 TUI-MODEL-BADGE-SOURCE).
431
+ onUsage: (usage) => {
432
+ void turnCtx.pushUsage({
433
+ ...usage,
434
+ model: usage.model ?? resolvedRoute?.model ?? turnModel,
435
+ ...(resolvedRoute ? { routeProvider: resolvedRoute.provider } : {}),
436
+ });
437
+ },
394
438
  // Codex Responses API reasoning summary stream. Currently
395
439
  // surfaced via forensic only (debug.log) — acts as the
396
440
  // "did the model actually emit reasoning?" verification
@@ -462,10 +506,19 @@ export function bridgeCoreTurnToAcp(
462
506
  const visibleFinalText = needsFollowup ? extractLastAssistantText(completedMessages) : finalAssistantText;
463
507
  const originalFinalStreamed = needsFollowup && finalAssistantText !== null
464
508
  && streamedTextSum.endsWith(finalAssistantText);
509
+ // TUI-GOAL-REPEAT-ANSWER — 골 루프가 «인사 + 같은 답» 재방출을 화면에서 가리면(원장은 그대로)
510
+ // 브리지의 스트림 합계에는 그 답이 없다. 그대로 보면 «마지막 답을 못 그렸다»고 재표면화로 다시
511
+ // 그린다 — 이전 답이 이미 화면에 있는데도. 인사를 뗀 답 부분이 스트림 꼬리에 있으면 «그렸다»로
512
+ // 본다(골 루프 경로에서만 — 다른 경로의 판정은 그대로).
513
+ const goalRepeatStrippedFinalText = armGoalLoop && visibleFinalText !== null
514
+ ? stripGoalRepeatReadbackPreface(visibleFinalText)
515
+ : visibleFinalText;
465
516
  const synthesisAlreadyStreamed =
466
517
  visibleFinalText !== null
467
518
  && visibleFinalText.length > 0
468
- && streamedTextSum.endsWith(visibleFinalText);
519
+ && (streamedTextSum.endsWith(visibleFinalText)
520
+ || (goalRepeatStrippedFinalText !== null && goalRepeatStrippedFinalText.length > 0
521
+ && streamedTextSum.endsWith(goalRepeatStrippedFinalText)));
469
522
  // ⭐ 최종 답 = 모델 답 ⊕ 런타임 검증 보충이면 사용자에겐 «모델 답»만 보인다 — 보충은 로그로(#25).
470
523
  // 대화 이력(completedMessages)엔 그대로 남아 다음 턴 맥락은 바뀌지 않는다.
471
524
  const supplement = finalSupplement !== null && finalAssistantText === finalSupplement.finalText
@@ -491,7 +544,11 @@ export function bridgeCoreTurnToAcp(
491
544
  });
492
545
  }
493
546
  if (supplement !== null) {
494
- const answerStreamed = supplement.answer.length > 0 && streamedTextSum.trimEnd().endsWith(supplement.answer);
547
+ // TUI-GOAL-REPEAT-ANSWER — 위와 같은 이유: 인사를 뗀 답 부분이 스트림 꼬리에 있으면 그렸다(골 루프만).
548
+ const answerStreamed = supplement.answer.length > 0
549
+ && (streamedTextSum.trimEnd().endsWith(supplement.answer)
550
+ || (armGoalLoop
551
+ && streamedTextSum.trimEnd().endsWith(stripGoalRepeatReadbackPreface(supplement.answer))));
495
552
  try {
496
553
  // 보충 «전체»를 남긴다 — 한 행이 저장 전에 잘리지 않게 조각(part/parts)으로 나눈다(리뷰 r3·r4).
497
554
  const redacted = redactSecretText(supplement.supplement);
@@ -81,6 +81,9 @@ export interface ElanousUiUsagePayload {
81
81
  provider?: 'anthropic' | 'openai';
82
82
  /** 그 턴이 실제로 요청한 모델(라우팅 결과 — 설정 모델과 다를 수 있다). */
83
83
  model?: string;
84
+ /** 이 사용량을 낸 «실제» 공급자(폴백 체인이 넘겼으면 넘어간 쪽 · 예 `grok`). `provider` 는 과금 계열 축이라 따로 둔다
85
+ * (TUI-MODEL-BADGE-ACTUAL · 10-16). */
86
+ routeProvider?: string;
84
87
  inputTokens?: number;
85
88
  outputTokens?: number;
86
89
  cacheReadInputTokens?: number;
package/src/acp/server.ts CHANGED
@@ -838,6 +838,8 @@ export interface AcpTurnContext {
838
838
  pushUsage: (usage: {
839
839
  provider?: 'anthropic' | 'openai';
840
840
  model?: string;
841
+ /** 실제로 응답한 공급자(폴백이면 넘어간 쪽). */
842
+ routeProvider?: string;
841
843
  inputTokens?: number;
842
844
  outputTokens?: number;
843
845
  cacheReadInputTokens?: number;
@@ -1839,6 +1841,7 @@ function wireAcpConnection(
1839
1841
  id: `turn:${Date.now()}`,
1840
1842
  ...(usage.provider !== undefined ? { provider: usage.provider } : {}),
1841
1843
  ...(usage.model !== undefined ? { model: usage.model } : {}),
1844
+ ...(usage.routeProvider !== undefined ? { routeProvider: usage.routeProvider } : {}),
1842
1845
  ...(usage.inputTokens !== undefined ? { inputTokens: usage.inputTokens } : {}),
1843
1846
  ...(usage.outputTokens !== undefined ? { outputTokens: usage.outputTokens } : {}),
1844
1847
  ...(usage.cacheReadInputTokens !== undefined
@@ -1,4 +1,4 @@
1
- import { appendMessage } from '../session/index.js';
1
+ import { appendMessage, onSessionCreated } from '../session/index.js';
2
2
  // ⛔ 메시지 «모양»은 `session/chat.ts` 가 갖는다 — 여기서 베끼지 않는다.
3
3
  // 같은 계약을 두 벌로 두면 한쪽만 자라고, 그때 「어느 표면의 기록인가」가 갈린다.
4
4
  import { buildToolTraceMessage } from '../session/chat.js';
@@ -24,9 +24,13 @@ import { debug } from '../debug/log.js';
24
24
  * Goodhart 시험이었다. ⇒ 주입 가능한 함수로 떼어 **실행으로** 문다. */
25
25
  /** ⛔ 이 저장소 «밖»으로 열지 않는다 — 소비처가 이 파일과 그 시험뿐이다(리뷰 must-fix:
26
26
  * 쓰이지 않는 공개 표면). 시험은 리터럴로 넘기므로 이름을 export 할 필요가 없다. */
27
+ type TraceMessage = ReturnType<typeof buildToolTraceMessage>;
28
+ type AppendFn = (sessionId: string, msg: TraceMessage) => unknown;
29
+ type FailureObserver = (info: { sessionId: string; tool: string; id: string; reason: string }) => void;
30
+
27
31
  interface AcpToolTraceDeps {
28
32
  /** 시험 주입점. 기본은 실제 세션 저장소. */
29
- readonly append?: (sessionId: string, msg: ReturnType<typeof buildToolTraceMessage>) => unknown;
33
+ readonly append?: AppendFn;
30
34
  /** ⛔⭐ 메시지 «모양»을 만드는 자리 — 기본은 `session/chat.ts` 의 공유 빌더.
31
35
  *
32
36
  * 📏 무인 리뷰 must-fix(PR #11120): 산출 필드(`role`/`toolName`/…)만 검사하면
@@ -35,7 +39,166 @@ interface AcpToolTraceDeps {
35
39
  * ⇒ 주입점으로 열어 **「공유 빌더를 쓴다」를 시험이 «실행으로» 확인**할 수 있게 한다. */
36
40
  readonly buildMessage?: typeof buildToolTraceMessage;
37
41
  /** 실패를 «이름으로» 남기는 자리. 기본은 관측 로그. */
38
- readonly observeFailure?: (info: { sessionId: string; tool: string; id: string; reason: string }) => void;
42
+ readonly observeFailure?: FailureObserver;
43
+ /** 지연·회수·상한을 남기는 자리(`trace-persist-deferred|flushed|dropped`). 기본은 관측 로그. */
44
+ readonly observe?: (event: TraceDeferEvent, data: Record<string, unknown>) => void;
45
+ /** 「세션이 원장에 생겼다」를 듣는 자리. 기본은 `session/index.ts` 의 `onSessionCreated`. */
46
+ readonly subscribeSessionCreated?: (listener: (meta: { readonly id: string }) => void) => () => void;
47
+ }
48
+
49
+ type TraceDeferEvent = 'trace-persist-deferred' | 'trace-persist-flushed' | 'trace-persist-dropped';
50
+
51
+ /** ⛔⭐⭐ **「세션이 아직 원장에 없다」는 실패가 아니라 «순서»다 — 지연 기록한다.**
52
+ *
53
+ * 📏 2026-10-16 실측(TUI 결함 #30·#64 · `eln logs --category acp.tool` 12h):
54
+ * `trace-persist-failed «session not found: elanous-session-ndusg6»` 7건이 **13:12:03~15Z 한 턴**에 몰렸고,
55
+ * 그 세션 파일의 첫 줄은 **13:12:48Z**(턴 «끝»)였다.
56
+ * 🔑 원인(호출부): ACP 서버는 세션 id 를 «메모리에만» 민팅하고(`acpServerRegisterSession` · `server.ts`),
57
+ * 원장 채택은 **턴이 «끝난 뒤»** 에 일어난다 — `persistCompletedTuiAcpTurn`(서버 · origin 메타가 있을 때) 또는
58
+ * 대시보드의 `adoptChatSession`(SESSION-RESUME-ISOLATED · 턴 완료 뒤). 그런데 툴 흔적은 «턴 도중»
59
+ * `pushToolResult` → 이 함수에서 쓴다. ⇒ ***새 세션의 «첫 턴» 도구 흔적은 전부 잃었다***
60
+ * (`/session new`·ACP 갱신마다 새 id 라 첫 턴이 반복된다).
61
+ * ⇒ 그 오류면 메시지를 세션별로 붙잡아 두고, 세션이 원장에 생기는 순간(`onSessionCreated`) 또는
62
+ * 같은 세션의 다음 호출 때 «원래 시각(ts) 그대로» 붙인다. 경고는 세션당 «한 번»(지연) ⊕ 회수 때 «수»로.
63
+ * ⛔ 출처(`source`)를 짐작해 여기서 세션을 «만들지» 않는다 — 같은 ACP 경로를 PWA 도 타므로
64
+ * TUI 로 낙인찍으면 남의 세션 속성을 틀리게 박는다. 만드는 일은 원래 주인(턴 완료 채택)에게 둔다. */
65
+ /* ⚠️ 상한은 «메모리 바닥»만 지킨다 — 영영 채택되지 않는 세션(턴 도중 종료)이 쌓이지 않게.
66
+ * 세션당 100 을 넘으면 그 뒤 흔적은 버리고, 세션 32 를 넘으면 가장 오래 기다린 세션을 통째로 버린다.
67
+ * 어느 쪽이든 `trace-persist-dropped` 를 «한 줄» 남길 뿐 버린 «수»를 세거나 간격을 두지 않는다
68
+ * (버림 계수·보고 방식은 연결 골 `ASK-ACP-TRACE-EVICTION-ACCOUNTING` 이 정한다).
69
+ * 축출된 id 가 다시 오면 「한 번」 경고부터 다시 시작한다 — id 는 base36 무작위 6자라 드물다. */
70
+ const MAX_PENDING_PER_SESSION = 100;
71
+ const MAX_PENDING_SESSIONS = 32;
72
+ const SESSION_NOT_FOUND = /^session not found: /;
73
+
74
+ interface PendingSession {
75
+ readonly entries: Array<{
76
+ readonly append: AppendFn;
77
+ readonly msg: TraceMessage;
78
+ readonly tool: string;
79
+ readonly id: string;
80
+ readonly observeFailure: FailureObserver | undefined;
81
+ }>;
82
+ /** 세션당 상한에 한 번 닿았나 — `trace-persist-dropped` 를 세션당 한 줄만 남기려고. */
83
+ capped: boolean;
84
+ readonly observe: (event: TraceDeferEvent, data: Record<string, unknown>) => void;
85
+ }
86
+
87
+ const pendingBySession = new Map<string, PendingSession>();
88
+ let unsubscribeCreated: (() => void) | null = null;
89
+
90
+ const defaultObserve = (event: TraceDeferEvent, data: Record<string, unknown>): void => {
91
+ debug.log('acp.tool', event, data);
92
+ };
93
+
94
+ const safeObserve = (fn: () => void): void => {
95
+ // ⛔ 관측 자체가 던져도 턴을 깨지 않는다 — 그러면 fail-soft 가 무의미해진다.
96
+ try { fn(); } catch { /* 관측은 마지막 방어선이다 */ }
97
+ };
98
+
99
+ const errorReason = (err: unknown): string =>
100
+ err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200);
101
+
102
+ function observeFailureOf(
103
+ sessionId: string,
104
+ call: { readonly tool: string; readonly id: string },
105
+ reason: string,
106
+ observeFailure: FailureObserver | undefined,
107
+ ): void {
108
+ const observe = observeFailure
109
+ ?? ((info) => { debug.log('acp.tool', 'trace-persist-failed', info); });
110
+ safeObserve(() => observe({ sessionId, tool: call.tool, id: call.id, reason }));
111
+ }
112
+
113
+ /** 붙잡아 둔 흔적을 원래 순서대로 붙인다. 세션이 여전히 없으면 그대로 둔다(`'missing'`). */
114
+ function flushPending(sessionId: string): 'missing' | 'flushed' | 'none' {
115
+ const p = pendingBySession.get(sessionId);
116
+ if (!p) return 'none';
117
+ let flushed = 0;
118
+ let failed = 0;
119
+ while (p.entries.length > 0) {
120
+ const entry = p.entries[0]!;
121
+ try {
122
+ entry.append(sessionId, entry.msg);
123
+ flushed += 1;
124
+ } catch (err) {
125
+ const reason = errorReason(err);
126
+ // ⛔ 회수 «도중» 세션이 사라져도(이미 몇 행을 붙인 뒤라도) 그 행과 나머지는 «지연» 그대로 둔다 — 실패가 아니다.
127
+ if (SESSION_NOT_FOUND.test(reason)) {
128
+ // ⭐ 그때까지 붙인 행 수는 «지금» 남긴다 — 다음 회수 보고는 그 뒤의 행만 센다.
129
+ if (flushed > 0 || failed > 0) {
130
+ safeObserve(() => p.observe('trace-persist-flushed', { sessionId, flushed, failed, partial: true }));
131
+ }
132
+ return 'missing';
133
+ }
134
+ failed += 1;
135
+ // ⛔ 회수 중 실패도 «같은» `trace-persist-failed` 로 — `flushed.failed` 합계에만 묻으면 실패가 안 보인다.
136
+ observeFailureOf(sessionId, { tool: entry.tool, id: entry.id }, reason, entry.observeFailure);
137
+ }
138
+ p.entries.shift();
139
+ }
140
+ pendingBySession.delete(sessionId);
141
+ safeObserve(() => p.observe('trace-persist-flushed', { sessionId, flushed, failed }));
142
+ if (pendingBySession.size === 0 && unsubscribeCreated) {
143
+ const off = unsubscribeCreated;
144
+ unsubscribeCreated = null;
145
+ try { off(); } catch { /* 구독 해제 실패는 무해 — 다음 지연이 다시 건다 */ }
146
+ }
147
+ return 'flushed';
148
+ }
149
+
150
+ function deferTrace(
151
+ sessionId: string,
152
+ call: { readonly id: string; readonly name: string },
153
+ append: AppendFn,
154
+ msg: TraceMessage,
155
+ reason: string,
156
+ deps: AcpToolTraceDeps,
157
+ ): void {
158
+ let p = pendingBySession.get(sessionId);
159
+ if (!p) {
160
+ if (pendingBySession.size >= MAX_PENDING_SESSIONS) {
161
+ // 가장 오래 기다린 세션부터 버린다 — 원장에 영영 안 생긴 세션(턴 도중 종료)이 쌓이지 않게.
162
+ const [oldestId, oldest] = pendingBySession.entries().next().value as [string, PendingSession];
163
+ pendingBySession.delete(oldestId);
164
+ safeObserve(() => oldest.observe('trace-persist-dropped', { sessionId: oldestId, reason: 'pending-session-cap' }));
165
+ }
166
+ p = { entries: [], capped: false, observe: deps.observe ?? defaultObserve };
167
+ pendingBySession.set(sessionId, p);
168
+ // ⭐ 경고는 세션당 «한 번» — 호출마다 같은 줄을 찍던 것이 결함 #64 의 다른 반쪽이다.
169
+ safeObserve(() => p!.observe('trace-persist-deferred', { sessionId, tool: call.name, id: call.id, reason }));
170
+ }
171
+ if (p.entries.length < MAX_PENDING_PER_SESSION) {
172
+ p.entries.push({ append, msg, tool: call.name, id: call.id, observeFailure: deps.observeFailure });
173
+ } else if (!p.capped) {
174
+ p.capped = true;
175
+ safeObserve(() => p!.observe('trace-persist-dropped', {
176
+ sessionId, tool: call.name, id: call.id, reason: 'pending-per-session-cap',
177
+ }));
178
+ }
179
+ if (!unsubscribeCreated) {
180
+ const subscribe = deps.subscribeSessionCreated ?? onSessionCreated;
181
+ try {
182
+ unsubscribeCreated = subscribe((meta) => {
183
+ if (!pendingBySession.has(meta.id)) return;
184
+ // ⭐ 채택 «직후» 같은 동기 구간에서 user/assistant 가 이어 붙는다(`persistCompletedTuiAcpTurn`).
185
+ // 마이크로태스크로 미뤄 그 뒤에 붙인다 — 그래야 「마지막 user 뒤의 tool 행」(다음 턴 관찰)이 산다.
186
+ queueMicrotask(() => { try { flushPending(meta.id); } catch { /* fail-soft */ } });
187
+ });
188
+ } catch { unsubscribeCreated = null; }
189
+ }
190
+ }
191
+
192
+ /** 시험 전용 — 모듈 상태(지연 큐·구독)를 비운다. */
193
+ export function _resetAcpToolTraceStateForTest(): void {
194
+ pendingBySession.clear();
195
+ if (unsubscribeCreated) { try { unsubscribeCreated(); } catch { /* 무해 */ } }
196
+ unsubscribeCreated = null;
197
+ }
198
+
199
+ /** 시험·관측용 — 세션별로 붙잡아 둔 흔적 수. */
200
+ export function pendingAcpToolTraceCount(sessionId: string): number {
201
+ return pendingBySession.get(sessionId)?.entries.length ?? 0;
39
202
  }
40
203
 
41
204
  /** 한 번의 툴 호출을 감사 기록으로 남긴다.
@@ -44,8 +207,9 @@ interface AcpToolTraceDeps {
44
207
  * (`session/chat.ts` 가 세운 규율).
45
208
  * ⚠️ **그러나 «조용히 삼키지 않는다»** — 실패하면 이름을 대고 관측에 남긴다.
46
209
  * ***조용한 실패야말로 16차가 내내 잡던 형태고, 이 PR 초판이 또 만들었다.***
210
+ * ⭐ 「세션이 아직 원장에 없다」면 지연 기록한다(위 `MAX_PENDING_*` 주석) — 이때도 `false` 다.
47
211
  *
48
- * @returns 저장을 시도해 «성공»했으면 `true`. ⛔ 「안 했다」와 「했는데 실패했다」는 다른 값이다. */
212
+ * @returns 지금 저장에 «성공»했으면 `true`. ⛔ 「안 했다」와 「했는데 실패했다」·「미뤘다」는 다른 값이다. */
49
213
  export function persistAcpToolTrace(
50
214
  sessionId: string,
51
215
  call: { readonly id: string; readonly name: string; readonly result?: unknown },
@@ -56,14 +220,25 @@ export function persistAcpToolTrace(
56
220
  // ⛔ 모양은 «공유 빌더»가 만든다 — 여기서 손으로 조립하지 않는다(계약을 두 벌로 두지 않는다).
57
221
  const build = deps.buildMessage ?? buildToolTraceMessage;
58
222
  try {
59
- append(sessionId, build(call.name, args, call.result));
60
- return true;
223
+ const msg = build(call.name, args, call.result);
224
+ // 앞서 미뤄 둔 흔적이 있으면 먼저 붙인다(순서 보존). 여전히 세션이 없으면 이것도 뒤에 줄 세운다.
225
+ if (pendingBySession.has(sessionId) && flushPending(sessionId) === 'missing') {
226
+ deferTrace(sessionId, call, append, msg, 'session not found (pending)', deps);
227
+ return false;
228
+ }
229
+ try {
230
+ append(sessionId, msg);
231
+ return true;
232
+ } catch (err) {
233
+ const reason = errorReason(err);
234
+ if (SESSION_NOT_FOUND.test(reason)) {
235
+ deferTrace(sessionId, call, append, msg, reason, deps);
236
+ return false;
237
+ }
238
+ throw err;
239
+ }
61
240
  } catch (err) {
62
- const reason = err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200);
63
- const observe = deps.observeFailure
64
- ?? ((info) => { debug.log('acp.tool', 'trace-persist-failed', info); });
65
- // ⛔ 관측 자체가 던져도 턴을 깨지 않는다 — 그러면 fail-soft 가 무의미해진다.
66
- try { observe({ sessionId, tool: call.name, id: call.id, reason }); } catch { /* 관측은 마지막 방어선이다 */ }
241
+ observeFailureOf(sessionId, { tool: call.name, id: call.id }, errorReason(err), deps.observeFailure);
67
242
  return false;
68
243
  }
69
244
  }