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
@@ -108,6 +108,10 @@ export interface ChatPickerModalBindings {
108
108
  getInputZoneHeight: () => number;
109
109
  width: number;
110
110
  getWidth?: () => number;
111
+ /** Live prompt anchor (input bottom row + col). When present it wins
112
+ * over the mount-time `bounds` snapshot, so a terminal resize moves
113
+ * an already-open picker with the prompt (TUI-PICKER-RESIZE-SHRINK). */
114
+ getAnchor?: () => { row: number; col: number };
111
115
  onKey?: PickerOnKey;
112
116
  onRowClick?: PickerOnRowClick;
113
117
  }
@@ -124,6 +128,7 @@ type FramedPickerSpec<T> = {
124
128
  getInputZoneHeight: () => number;
125
129
  width: number;
126
130
  getWidth?: () => number;
131
+ getAnchor?: () => { row: number; col: number };
127
132
  onKey?: PickerOnKey;
128
133
  onRowClick?: PickerOnRowClick;
129
134
  };
@@ -132,7 +137,8 @@ function createFramedPickerModal<T>(spec: FramedPickerSpec<T>): ModalSurface {
132
137
  const computeBounds = (): (ModalBounds & { startIdx: number; visibleCount: number }) | null => {
133
138
  const rows = spec.getRows();
134
139
  const inputZoneHeight = spec.getInputZoneHeight();
135
- const bottomRow = spec.bounds.row - inputZoneHeight;
140
+ const anchor = spec.getAnchor?.() ?? spec.bounds;
141
+ const bottomRow = anchor.row - inputZoneHeight;
136
142
  if (rows.length === 0 || bottomRow < 4) return null;
137
143
  const { visibleCount, startIdx } = pickerWindow(
138
144
  rows.length,
@@ -142,7 +148,7 @@ function createFramedPickerModal<T>(spec: FramedPickerSpec<T>): ModalSurface {
142
148
  if (visibleCount <= 0) return null;
143
149
  const height = visibleCount + 3;
144
150
  const row = bottomRow - height + 1;
145
- return { row, col: spec.bounds.col, width: spec.getWidth?.() ?? spec.width, height, startIdx, visibleCount };
151
+ return { row, col: anchor.col, width: spec.getWidth?.() ?? spec.width, height, startIdx, visibleCount };
146
152
  };
147
153
 
148
154
  /** Phase 4.5a (substrate Occam · §4-pre.7 · 2026-05-03) — update
@@ -0,0 +1,38 @@
1
+ // ── 도구별 «제출로 끊어도 되나» 선언 (10-14 · 대표 «지금 밀어 넣기») ─────────────────
2
+ //
3
+ // 턴 중에 사용자가 «지금 밀어 넣기»를 하면, 도는 도구가 «전부» `cancel` 일 때만 턴을 끊고 그 발화로
4
+ // 바로 이어 간다. 하나라도 `block` 이면 끊지 않고 다음 도구 경계에 최우선으로 넣는다.
5
+ // ⭐ 기본은 `block` 이다 — 모르는 도구(쓰기·실행·자식 띄우기)를 «끊어도 된다»로 읽지 않는다.
6
+ // ⭐ `cancel` 은 부작용 없는 읽기·대기 도구만 — 끊으면 결과를 버릴 뿐 바깥 상태가 안 바뀐다.
7
+ // (Claude Code `Tool.interruptBehavior()` 계약과 같은 축 · 기본 block)
8
+ // ⚠️ 이 표가 «도구 선언 칸»이다. TUI 는 도는 도구의 «이름»만 알아서 스펙 객체가 아니라 이름으로 선언한다.
9
+ // 새 읽기 전용 도구를 더하면 여기 한 줄을 더한다.
10
+
11
+ export type ToolInterruptBehavior = 'cancel' | 'block';
12
+
13
+ const DECLARED: ReadonlyMap<string, ToolInterruptBehavior> = new Map<string, ToolInterruptBehavior>([
14
+ ['Read', 'cancel'],
15
+ ['Grep', 'cancel'],
16
+ ['Glob', 'cancel'],
17
+ ['ListDir', 'cancel'],
18
+ ['WebSearch', 'cancel'],
19
+ ['WebFetch', 'cancel'],
20
+ // 대기·조회 — 끊어도 자식은 산다(턴만 끊는다).
21
+ ['AgentOutput', 'cancel'],
22
+ ['AgentList', 'cancel'],
23
+ ['TaskGet', 'cancel'],
24
+ ['TaskList', 'cancel'],
25
+ ]);
26
+
27
+ export function toolInterruptBehavior(name: string): ToolInterruptBehavior {
28
+ return DECLARED.get(name) ?? 'block';
29
+ }
30
+
31
+ /**
32
+ * 도는 도구가 «전부» 끊어도 되는가. 도는 도구가 없으면(모델이 글을 쓰는 중) 참이다.
33
+ * 막는 도구 이름을 함께 낸다(안내 줄용).
34
+ */
35
+ export function canInterruptRunningTools(names: readonly string[]): { ok: boolean; blocking: string[] } {
36
+ const blocking = [...new Set(names.filter(name => toolInterruptBehavior(name) === 'block'))].sort();
37
+ return { ok: blocking.length === 0, blocking };
38
+ }
@@ -361,7 +361,11 @@ function extractSyntheticGuardSummary(result: unknown): string | null {
361
361
  return 'inspect budget exhausted — summarize inspected files';
362
362
  }
363
363
  if (text.includes('TOOL CALL REJECTED')) {
364
- return 'tool budget exhausted — final answer required';
364
+ // Only the turn-budget stub is a budget; phase guards (VERIFY/REPAIR/INSPECT ACTION
365
+ // REQUIRED …) reject a tool for the current phase and must not read as «budget» (#67).
366
+ if (text.includes('tool-loop budget exhausted')) return 'tool budget exhausted — final answer required';
367
+ const reason = /\b([A-Z][A-Z]+(?: [A-Z]+)* (?:REQUIRED|EXHAUSTED))\b/.exec(text)?.[1];
368
+ return reason ? `tool call rejected — ${reason.toLowerCase()}` : 'tool call rejected';
365
369
  }
366
370
  if (text.includes('RUNTIME BLOCKED')) {
367
371
  return 'reuse current candidates';
@@ -19,6 +19,10 @@ export interface TurnTypeaheadState {
19
19
  * «짝지어» 떨어낸다 — 위치·문자열로 짝지으면 같은 발화가 두 번 들어간다(10-14 중복 수리).
20
20
  */
21
21
  queuedPendingIds?: (string | null)[];
22
+ /** «지금 밀어 넣기»가 «다음 도구 경계 최우선»으로 떨어졌다(도는 도구가 취소 불가). 큐가 비거나 턴이 끝나면 지운다. */
23
+ steerPriority?: boolean;
24
+ /** 이번 턴에 도구 경계로 들어간 수 — 큐가 비었을 때 «✓ 넣음» 줄로 보인다. 턴이 끝나면 지운다. */
25
+ injectedCount?: number;
22
26
  }
23
27
 
24
28
  /** 큐 길이에 맞춘 id 짝(모자라면 null 로 채운다). 순수. */
@@ -89,16 +93,31 @@ export type TurnTypeaheadKeyResult = {
89
93
  submissionDisposition?: 'immediate' | 'fifo';
90
94
  /** 큐에서 «다른 길»로 빠진 항목의 레지스트리 id — 호출측이 레지스트리에서도 떨어낸다(되꺼내기). */
91
95
  releasedPendingIds?: string[];
96
+ /** 빈 입력에서 Enter(대기 항목이 있을 때) = «지금 밀어 넣기» 요청. 판정·실행은 호출측의 책임이다. */
97
+ pushNowRequested?: boolean;
92
98
  };
93
99
 
94
100
  /** 등록소 소유의 관측용 표시 조회. 이름·문법·실행 정책은 이 순수 판정기에 두지 않는다. */
95
101
  export type TurnTypeaheadImmediateSubmissionLookup = (text: string) => boolean;
96
102
 
103
+ /** 줄바꿈 키 — Shift+Enter · Alt+Enter · Ctrl+J(`input-control-key.ts` 와 같은 꼴). */
104
+ export function isTypeaheadNewlineKey(key: { name: string; ctrl?: boolean; alt?: boolean; shift?: boolean; meta?: boolean }): boolean {
105
+ if (key.name === 'enter') return !key.ctrl && !key.meta && (!!key.shift || !!key.alt);
106
+ return key.name === 'j' && !!key.ctrl && !key.alt && !key.shift && !key.meta;
107
+ }
108
+
109
+ /** 에코·큐 행은 한 줄로 그린다 — 버퍼 속 줄바꿈은 `↵` 로 보여 준다(행을 깨지 않는다). */
110
+ function oneLine(text: string): string {
111
+ return text.replace(/\n/g, '↵');
112
+ }
113
+
97
114
  /** 스트리밍 중 키 1개 판정(순수). mouse/비-press/수정키는 소유하지 않는다.
98
115
  * - printable → buffer 누적
99
116
  * - backspace → 마지막 코드포인트 제거(빈 버퍼면 미소유 — 기존 semantics 보존)
117
+ * - shift/alt+enter · ctrl+j → buffer 에 줄바꿈(빈 buffer 면 소유만)
100
118
  * - enter → 비어 있지 않은 buffer를 FIFO 제출 큐에 넣고 다음 문장을 위한 buffer를 비운다
101
- * - ctrl+up → 마지막 제출 큐 항목을 buffer 끝으로 되꺼낸다
119
+ * - 빈 buffer 에서 enter(대기 항목이 있을 때) → «지금 밀어 넣기» 요청(`pushNowRequested`)
120
+ * - ctrl+up → 대기 항목 «전부»를 입력 순서대로 buffer 앞으로 되꺼낸다(편집 가능한 것만 이 큐에 든다)
102
121
  * - escape 등 나머지 → 미소유(턴 중단 등 기존 경로 그대로) */
103
122
  export function applyTurnTypeaheadKey(
104
123
  state: TurnTypeaheadState,
@@ -117,8 +136,20 @@ export function applyTurnTypeaheadKey(
117
136
  return { state: { ...state, buffer: cps.join('') }, consumed: true, changed: true };
118
137
  }
119
138
 
120
- if (key.name === 'enter' && !key.ctrl && !key.alt) {
121
- if (!state.buffer.trim()) return { state, consumed: false, changed: false };
139
+ // ⭐ 턴 중에도 Shift+Enter(⊕ Alt+Enter · Ctrl+J)는 «줄바꿈»이다 — 유휴 입력창과 같은 계약.
140
+ // 종전엔 수식자를 안 보고 «제출»(FIFO 대기)로 떨어져, 도는 턴 위에 쓰던 여러 줄이 반토막으로 나갔다.
141
+ // 빈 버퍼의 줄바꿈은 소유만 하고 버퍼는 안 바꾼다(맨 앞 빈 줄을 만들지 않는다).
142
+ if (isTypeaheadNewlineKey(key)) {
143
+ if (!state.buffer) return { state, consumed: true, changed: false };
144
+ return { state: { ...state, buffer: `${state.buffer}\n` }, consumed: true, changed: true };
145
+ }
146
+
147
+ if (key.name === 'enter' && !key.ctrl && !key.alt && !key.shift) {
148
+ if (!state.buffer.trim()) {
149
+ // ⭐ 「한 번 더 Enter = 지금」 — 큐가 비면 옛 계약 그대로 소유하지 않는다.
150
+ if (state.queuedSubmissions.length === 0) return { state, consumed: false, changed: false };
151
+ return { state, consumed: true, changed: false, pushNowRequested: true };
152
+ }
122
153
  try {
123
154
  if (state.buffer.startsWith('/') && isImmediateSubmission?.(state.buffer)) {
124
155
  return {
@@ -147,18 +178,16 @@ export function applyTurnTypeaheadKey(
147
178
  // ⛔ 정확한 조합만 소유한다 — 수식자를 덜 보면 `ctrl+shift+up` 같은 조합까지 삼켜
148
179
  // 다른 층이 쓸 키를 조용히 먹는다.
149
180
  if (key.name === 'up' && key.ctrl && !key.alt && !key.shift && !key.meta) {
150
- const recalled = state.queuedSubmissions.at(-1);
151
- if (recalled === undefined) return { state, consumed: false, changed: false };
152
- const ids = turnTypeaheadPendingIds(state);
181
+ if (state.queuedSubmissions.length === 0) return { state, consumed: false, changed: false };
182
+ // ⭐ 전부 꺼낸다(Claude Code 동형) — 한 건씩이면 여러 건을 고칠 때 순서가 뒤집힌다.
183
+ // 입력 순서를 지키고, 치던 초안은 맨 뒤에 둔다.
184
+ const recalled = [...state.queuedSubmissions, ...(state.buffer ? [state.buffer] : [])].join('\n');
185
+ const released = presentIds(turnTypeaheadPendingIds(state));
153
186
  return {
154
- state: {
155
- buffer: state.buffer + recalled,
156
- queuedSubmissions: state.queuedSubmissions.slice(0, -1),
157
- ...idsField(ids.slice(0, -1)),
158
- },
187
+ state: { ...withoutIds(state), buffer: recalled, queuedSubmissions: [], steerPriority: undefined },
159
188
  consumed: true,
160
189
  changed: true,
161
- ...(ids.at(-1) ? { releasedPendingIds: presentIds(ids.slice(-1)) } : {}),
190
+ ...(released.length > 0 ? { releasedPendingIds: released } : {}),
162
191
  };
163
192
  }
164
193
 
@@ -203,6 +232,18 @@ export function dequeueTurnTypeaheadHandoff(
203
232
  return { handoff: { kind: 'prefill', text: state.buffer }, state: createTurnTypeaheadState() };
204
233
  }
205
234
 
235
+ /** 턴 범위 표시(최우선·넣음 수)를 지운다 — 다음 턴으로 넘기지 않는다. 순수. */
236
+ function clearTurnScopedMarks(state: TurnTypeaheadState): TurnTypeaheadState {
237
+ if (state.steerPriority === undefined && state.injectedCount === undefined) return state;
238
+ const { steerPriority: _p, injectedCount: _n, ...rest } = state;
239
+ return rest;
240
+ }
241
+
242
+ /** «지금 밀어 넣기»가 다음 경계 최우선으로 떨어졌음을 적는다. 레지스트리에 든 항목이 없으면 그대로. 순수. */
243
+ export function markTurnTypeaheadPriority(state: TurnTypeaheadState): TurnTypeaheadState {
244
+ return presentIds(turnTypeaheadPendingIds(state)).length > 0 ? { ...state, steerPriority: true } : state;
245
+ }
246
+
206
247
  /** ⭐ 턴 종료 드레인 **한 걸음** — `src/dashboard/index.ts` 의 inner-loop 가 반복마다 이걸 부른다.
207
248
  * ⛔ 종전엔 그 순서(dequeue → state 교체 → nextInitial 누적 → submit 이면 enter 주입)가
208
249
  * `index.ts` 안에만 있어서, 테스트가 그 순서를 **베껴 모사**할 수밖에 없었다. 베낀 테스트는
@@ -223,6 +264,7 @@ export function drainTurnTypeaheadOnce(
223
264
  */
224
265
  releasedPendingIds: string[];
225
266
  } {
267
+ state = clearTurnScopedMarks(state);
226
268
  if (opts?.interrupted && state.queuedSubmissions.length > 0) {
227
269
  const restored = [...state.queuedSubmissions, ...(state.buffer ? [state.buffer] : [])].join('\n');
228
270
  return {
@@ -308,6 +350,8 @@ export function drainedIntoTurn(
308
350
  };
309
351
  }
310
352
  if (matched.length === 0) return { state: next, sentence: null, matched };
353
+ next = { ...next, injectedCount: (next.injectedCount ?? 0) + matched.length };
354
+ if (presentIds(turnTypeaheadPendingIds(next)).length === 0) delete next.steerPriority;
311
355
  const count = matched.length;
312
356
  const label = count === 1 ? '⏳ 턴 안 1건' : `⏳ 턴 안 ${count}건`;
313
357
  const quoted = matched.map(text => `"${text}"`).join(' · ');
@@ -333,8 +377,9 @@ export function renderTurnTypeaheadEcho(
333
377
  const count = state.queuedSubmissions.length;
334
378
  const suffix = opts?.includeQueueSuffix && count > 0 ? ` ⏎ ${count}건 대기 · 턴 종료 시 전송` : '';
335
379
  const budget = Math.max(8, width - 2 - [...suffix].length);
336
- const cps = [...state.buffer];
337
- const shown = cps.length > budget ? cps.slice(cps.length - budget).join('') : state.buffer;
380
+ const buffer = oneLine(state.buffer);
381
+ const cps = [...buffer];
382
+ const shown = cps.length > budget ? cps.slice(cps.length - budget).join('') : buffer;
338
383
  return `${shown}${suffix}`;
339
384
  }
340
385
 
@@ -351,13 +396,23 @@ export function renderTurnTypeaheadQueueRow(
351
396
  width: number,
352
397
  ): string | null {
353
398
  const count = state.queuedSubmissions.length;
354
- if (count === 0) return null;
355
- const head = state.queuedSubmissions[0] ?? '';
356
- const label = count === 1 ? '⏳ 대기 1건' : `⏳ 대기 ${count}건`;
357
- // 되꺼내기 키를 화면에 적는다 — 안내가 없어 대기 발화를 취소·수정할 길을 몰랐다(2026-09-26 베어 VM 실측 · UX 12).
358
- const tail = ' · 턴 종료 시 전송 · Ctrl+↑ 되꺼내기';
399
+ if (count === 0) {
400
+ // ✓ 넣음 — 도구 경계로 들어간 뒤 큐가 비었다(턴이 끝나면 지워진다).
401
+ const injected = state.injectedCount ?? 0;
402
+ return injected > 0 ? `✓ 넣음 ${injected}건 · 도는 턴에 이어서 반영` : null;
403
+ }
404
+ const head = oneLine(state.queuedSubmissions[0] ?? '');
405
+ // ⭐ 항목 상태를 보인다 — 레지스트리에 든 것은 다음 도구 경계에, 안 든 것(슬래시·세션 없음)은 응답 뒤에 나간다.
406
+ const steerable = presentIds(turnTypeaheadPendingIds(state)).length;
407
+ const waiting = count - steerable;
408
+ const parts: string[] = [];
409
+ if (steerable > 0) parts.push(`${state.steerPriority ? '⚡ 최우선 · 다음 도구 경계에 넣음' : '↳ 다음 도구 경계에 넣음'} ${steerable}건`);
410
+ if (waiting > 0) parts.push(`⏳ 대기(응답 뒤) ${waiting}건`);
411
+ const label = parts.join(' · ');
412
+ // 되꺼내기·밀어 넣기 키를 화면에 적는다 — 안내가 없어 대기 발화를 취소·수정할 길을 몰랐다(2026-09-26 베어 VM 실측 · UX 12).
413
+ const tail = ' · Ctrl+↑ 되꺼내기 · 빈 Enter 지금 밀어 넣기';
359
414
  const budget = Math.max(8, width - [...label].length - [...tail].length - 5);
360
415
  const cps = [...head];
361
- const shown = cps.length > budget ? `${cps.slice(0, budget).join('')}…` : head;
416
+ const shown = cps.length > budget ? `${cps.slice(0, budget).join('')}…` : cps.join('');
362
417
  return `${label} · "${shown}"${tail}`;
363
418
  }
@@ -8,8 +8,10 @@ Arguments:
8
8
  text Prompt text for the single-turn agent.
9
9
 
10
10
  Options:
11
- --new Force a new session instead of using the active one
12
- --session <id> Continue an explicit session (id or unique prefix). Overrides --new and active session.
11
+ --new Start a new session (the default since 0.2.31 — kept for compatibility)
12
+ --continue Continue the active session instead of starting a new one
13
+ --resume [id] Continue a session: the given id (or unique prefix), or the active session when no id is given. A word after --resume that is not session-id shaped (hex uuid) is read as the prompt, not the id.
14
+ --session <id> Continue an explicit session (id or unique prefix). Overrides --new, --continue and --resume.
13
15
  --json Emit a single JSON line {sessionId, provider, model, reply, logPath, budget} instead of streaming text + ui.info trailer. Stable shape for LLM self-spawn.
14
16
  --no-tools Disable the tool loop and fall back to text-only chat (for benchmarking / parity with `chat`).
15
17
  -h, --help display help for command
@@ -5,7 +5,8 @@ import { handleOnboardingRefusal, needsOnboarding, runOnboarding } from '../onbo
5
5
  import { runTurn, ensureCliSession, sessionBudget } from '../session/chat.js';
6
6
  import { suggestProjectForFolder } from '../project/project-store.js';
7
7
  import { NoLlmProviderAvailableError, noProviderAvailableMessage } from '../llm.js';
8
- import { resolveSessionId, getActiveSessionId, setActiveSessionId } from '../session/index.js';
8
+ import { resolveSessionId, getActiveSessionId, setActiveSessionId, loadSession, listSessions } from '../session/index.js';
9
+ import { decideSessionStart, observeSessionStart, splitResumeArgument } from '../session/session-start.js';
9
10
  import { getHarnessSpace } from '../harness/harness-space.js';
10
11
  import { encodeDetachedProgressFrame } from '../harness/dispatch-detached.js';
11
12
  import type { FeedbackEnvelope } from '../feedback/envelope.js';
@@ -65,12 +66,18 @@ export function registerAgentCommands(program: Command): void {
65
66
  .command('agent')
66
67
  .argument('[text...]', 'Prompt text for the single-turn agent.')
67
68
  .description('Single-turn agent — same as `chat` but with the tool loop on by default (Read/Grep/Glob/ListDir/Edit/Write + Bash). Use this when the LLM needs to inspect files / run commands / debug itself.')
68
- .option('--new', 'Force a new session instead of using the active one')
69
- .option('--session <id>', 'Continue an explicit session (id or unique prefix). Overrides --new and active session.')
69
+ .option('--new', 'Start a new session (the default since 0.2.31 — kept for compatibility)')
70
+ .option('--continue', 'Continue the active session instead of starting a new one')
71
+ .option('--resume [id]', 'Continue a session: the given id (or unique prefix), or the active session when no id is given. A word after --resume that is not session-id shaped (hex uuid) is read as the prompt, not the id.')
72
+ .option('--session <id>', 'Continue an explicit session (id or unique prefix). Overrides --new, --continue and --resume.')
70
73
  .option('--json', 'Emit a single JSON line {sessionId, provider, model, reply, logPath, budget} instead of streaming text + ui.info trailer. Stable shape for LLM self-spawn.')
71
74
  .option('--no-tools', 'Disable the tool loop and fall back to text-only chat (for benchmarking / parity with `chat`).')
72
- .action(async (parts: string[], opts: { new?: boolean; session?: string; json?: boolean; tools?: boolean }) => {
73
- if (!parts || parts.length === 0) {
75
+ .action(async (rawParts: string[], opts: { new?: boolean; continue?: boolean; resume?: string | boolean; session?: string; json?: boolean; tools?: boolean }) => {
76
+ // TUI-H8-FOLLOW ② — `agent --resume "질문"` 에서 Commander 가 질문 첫 낱말을 세션 id 로 먹지 않게.
77
+ const split = splitResumeArgument(opts.resume, rawParts ?? [], 'agent', process.argv.slice(2));
78
+ opts.resume = split.resume;
79
+ const parts = split.parts;
80
+ if (parts.length === 0) {
74
81
  console.error("error: missing required argument 'text'");
75
82
  process.exit(1);
76
83
  }
@@ -105,10 +112,12 @@ export function registerAgentCommands(program: Command): void {
105
112
  await runChatTurnCli({
106
113
  cfg: refreshed,
107
114
  userText: parts.join(' '),
108
- explicitSessionId: opts.session,
109
- reuseActive: opts.new !== true,
115
+ explicitSessionId: opts.session ?? (typeof opts.resume === 'string' ? opts.resume : undefined),
116
+ // 대표 #73 — 인자 없음 = 새 세션. 이어하기는 `--continue`/`--resume` 명시일 때만.
117
+ reuseActive: opts.continue === true || opts.resume === true,
110
118
  forceNew: opts.new === true,
111
119
  json: opts.json === true,
120
+ surface: 'agent',
112
121
  // commander stores --no-tools as `tools: false`, plain absence as undefined → default true here.
113
122
  enableTools: opts.tools !== false,
114
123
  });
@@ -385,11 +394,13 @@ tierCmd
385
394
 
386
395
  /** Single-turn CLI driver shared by `elanous ask` and `elanous chat`.
387
396
  *
388
- * Resolution order for sessionId:
389
- * 1. opts.explicitSessionId (`--session`) — wins, validates against
397
+ * Resolution order for sessionId (`decideSessionStart` · 대표 #73 기본 = 새 세션):
398
+ * 1. opts.explicitSessionId (`--session`/`--resume <id>`) — wins, validates against
390
399
  * resolveSessionId so a 6-char prefix works
391
- * 2. active session — when reuseActive
392
- * 3. fresh session — otherwise
400
+ * 2. fresh session — when forceNew
401
+ * 3. active session — only when reuseActive (`--continue`/`--resume`)
402
+ * 4. fresh session — otherwise (the default)
403
+ * Every decision emits `session`/`start` {surface, origin, reason}.
393
404
  *
394
405
  * When `json` is true, the function suppresses the streaming text +
395
406
  * ui.info trailer and instead emits exactly ONE JSON line on stdout
@@ -402,9 +413,12 @@ export async function runChatTurnCli(opts: {
402
413
  cfg: ReturnType<typeof reloadUserConfig>;
403
414
  userText: string;
404
415
  explicitSessionId: string | undefined;
416
+ /** 활성 세션 이어하기를 «명시로» 요청했나(`--continue`/`--resume`). 기본 false = 새 세션. */
405
417
  reuseActive: boolean;
406
418
  forceNew: boolean;
407
419
  json: boolean;
420
+ /** 관측용 표면 이름(`session`/`start`). 기본 'chat'. */
421
+ surface?: 'chat' | 'agent' | 'ask';
408
422
  /** When true, build a CORE-native + Bash tool catalog and route
409
423
  * through streamLLMWithTools so the LLM can drive multi-turn
410
424
  * exploration (file reads, grep, shell). Default false — CLI
@@ -429,11 +443,25 @@ export async function runChatTurnCli(opts: {
429
443
  process.exit(1);
430
444
  }
431
445
  resolvedSessionIdHint = id;
432
- } else if (opts.reuseActive && !opts.forceNew) {
433
- resolvedSessionIdHint = getActiveSessionId() ?? undefined;
434
446
  }
447
+ const startDecision = decideSessionStart({
448
+ ...(resolvedSessionIdHint ? { explicitSessionId: resolvedSessionIdHint } : {}),
449
+ continueActive: opts.reuseActive,
450
+ forceNew: opts.forceNew,
451
+ activeSessionId: () => getActiveSessionId(),
452
+ // TUI-H8-FOLLOW ① — 활성 표지가 사라진 세션이면 최신 세션으로.
453
+ sessionExists: (id) => loadSession(id) !== null,
454
+ latestSessionId: () => listSessions({ limit: 1 })[0]?.id ?? null,
455
+ });
456
+ resolvedSessionIdHint = startDecision.sessionIdHint;
435
457
  const session = ensureCliSession(opts.cfg, resolvedSessionIdHint);
436
458
  setActiveSessionId(session.id);
459
+ observeSessionStart({
460
+ surface: opts.surface ?? 'chat',
461
+ origin: resolvedSessionIdHint && session.id === resolvedSessionIdHint ? startDecision.origin : 'new',
462
+ reason: resolvedSessionIdHint && session.id !== resolvedSessionIdHint ? 'resume-target-missing' : startDecision.reason,
463
+ sessionId: session.id,
464
+ });
437
465
  if (!opts.json && (!resolvedSessionIdHint || session.id !== resolvedSessionIdHint)) {
438
466
  try {
439
467
  const project = suggestProjectForFolder(process.cwd());
@@ -37,6 +37,7 @@ export async function askBare({ text, provider, model, deps }: {
37
37
  ...(provider === undefined ? { initialProvider: chosenProvider } : { provider: chosenProvider }),
38
38
  ...(selected.model === '(none)' ? {} : { model: selected.model }),
39
39
  onResolvedProvider: (name, activeModel) => { resolvedProvider = name; resolvedModel = activeModel; },
40
+ usageSite: 'cli.ask-bare',
40
41
  });
41
42
  return { provider: resolvedProvider, model: resolvedModel, reply };
42
43
  }
@@ -0,0 +1,123 @@
1
+ // ── CFG-STORE2 · config 감사 이력 첫 칸 (0.2.29 · 2026-10-14) ──
2
+ //
3
+ // RFC-universe-by-house-not-tree-and-config-store-2026-10-06 §2 — 겹 저장소의 첫 칸은 «감사 이력».
4
+ // CFG-STORE1(config-drift.ts · 읽기 전용 드리프트) 위에 «쓰기» 축 하나를 더한다:
5
+ // `config set` · `config unset` 이 저장에 성공하면 바꾼 키·이전 값·다음 값·by·why 를 한 행으로 남긴다.
6
+ //
7
+ // ⛔ 불변식
8
+ // • 비밀은 «저장 전에» 가린다 — config-drift.ts 의 가림 원형(isSecretPath·isSecretValue·MASK·maskDeep)을
9
+ // 그대로 재사용한다: 비밀 경로(마디 하나라도 token/secret/key/…) ⊕ 비밀 모양 값(웹훅·토큰 접두·URL userinfo)
10
+ // ⊕ 객체 속 비밀 키(botToken 같은 자리) → '<masked>'. config-drift.ts 는 손대지 않는다(읽기 전용 그대로).
11
+ // • 감사 기록은 명령의 부속이다 — 호출부(src/index.ts config set/unset)가 fail-open 으로 감싼다(실패해도 경고만).
12
+ // • by 는 자리(ELANOUS_TRACK) ⊕ 런 id 환경 변수에서 푼다 — 명시 by > ELANOUS_TRACK > 런 id > 'cli'.
13
+ // • 읽기(readConfigHistory)는 없는 db 파일을 만들지 않는다.
14
+
15
+ import { Database } from 'bun:sqlite';
16
+ import { existsSync, mkdirSync } from 'node:fs';
17
+ import { dirname, join } from 'node:path';
18
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
19
+ import { isSecretPath, isSecretValue, maskDeep, MASK } from './config-drift.js';
20
+
21
+ // CFG-STORE1 가림 자(MASK) — 테스트 계약(config-audit.test.ts)이 이 경로로 소비한다.
22
+ export { MASK };
23
+
24
+ /** 한 번의 config 변경 — prev/next 는 저장 «전» 값과 저장 «후» 값(undefined = 그 자리에 키가 없다). */
25
+ export interface ConfigChange {
26
+ key: string;
27
+ prev?: unknown;
28
+ next?: unknown;
29
+ by?: string;
30
+ why?: string;
31
+ }
32
+
33
+ /** config_changes 표의 한 행 — prev/next 는 가려 직렬화한 값(null = 그 자리에 값이 없었다). */
34
+ export interface ConfigChangeRow {
35
+ at: string;
36
+ key: string;
37
+ prev: string | null;
38
+ next: string | null;
39
+ by: string;
40
+ why: string | null;
41
+ }
42
+
43
+ /** 감사 db 기본 자리 — 활성 config 뿌리(~/.elanous · --config-dir 격리 존중) 바로 옆 config-changes.db. */
44
+ function configAuditDbPath(dbPath?: string): string {
45
+ return dbPath ?? join(getElanousConfigDir(), 'config-changes.db');
46
+ }
47
+
48
+ /** by 해석 — 명시 by > 자리(ELANOUS_TRACK) > 런 id 환경 변수 > 'cli'. */
49
+ function resolveConfigChangeBy(by?: string): string {
50
+ const explicit = by?.trim();
51
+ if (explicit) return explicit;
52
+ const track = process.env.ELANOUS_TRACK?.trim();
53
+ if (track) return track;
54
+ for (const name of ['ELANOUS_RUN_ID', 'HARNESS_RUN_ID', 'RUN_ID']) {
55
+ const runId = process.env[name]?.trim();
56
+ if (runId) return runId;
57
+ }
58
+ return 'cli';
59
+ }
60
+
61
+ /** 저장용 값 — undefined → SQL NULL · 비밀(경로 마디 ⊕ 값 모양) → MASK · 나머지는 maskDeep 후 JSON 직렬화. */
62
+ function serializeConfigValue(key: string, value: unknown): string | null {
63
+ if (value === undefined) return null;
64
+ if (isSecretPath(key) || isSecretValue(value)) return MASK;
65
+ return JSON.stringify(maskDeep(value)) ?? 'null';
66
+ }
67
+
68
+ // Anonymous SQLite memory databases are private to each connection. Keep one
69
+ // connection for this process so record/read share the same audit history.
70
+ // File-backed stores keep their existing open/close-per-call lifetime.
71
+ let memoryDb: Database | undefined;
72
+
73
+ function openConfigChangesDb(dbPath: string): Database {
74
+ if (dbPath !== ':memory:') mkdirSync(dirname(dbPath), { recursive: true });
75
+ const db = dbPath === ':memory:'
76
+ ? (memoryDb ??= new Database(':memory:'))
77
+ : new Database(dbPath);
78
+ db.exec(`CREATE TABLE IF NOT EXISTS config_changes (
79
+ at TEXT NOT NULL,
80
+ key TEXT NOT NULL,
81
+ prev TEXT,
82
+ next TEXT,
83
+ by TEXT NOT NULL,
84
+ why TEXT
85
+ )`);
86
+ db.exec('CREATE INDEX IF NOT EXISTS config_changes_key_at ON config_changes(key, at)');
87
+ return db;
88
+ }
89
+
90
+ /** 한 번의 config 변경을 감사 이력에 «한 행»으로 남긴다. 비밀 값은 가려 쓴다. */
91
+ export function recordConfigChange(change: ConfigChange, dbPath?: string): ConfigChangeRow {
92
+ const path = configAuditDbPath(dbPath);
93
+ const db = openConfigChangesDb(path);
94
+ try {
95
+ const row: ConfigChangeRow = {
96
+ at: new Date().toISOString(),
97
+ key: change.key,
98
+ prev: serializeConfigValue(change.key, change.prev),
99
+ next: serializeConfigValue(change.key, change.next),
100
+ by: resolveConfigChangeBy(change.by),
101
+ why: change.why?.trim() ? change.why.trim() : null,
102
+ };
103
+ db.run(
104
+ 'INSERT INTO config_changes (at, key, prev, next, by, why) VALUES (?, ?, ?, ?, ?, ?)',
105
+ [row.at, row.key, row.prev, row.next, row.by, row.why],
106
+ );
107
+ return row;
108
+ } finally {
109
+ if (path !== ':memory:') db.close();
110
+ }
111
+ }
112
+
113
+ /** 한 키의 감사 이력 — 시간 오름차순. db 파일이 없으면 빈 배열(읽기가 파일을 만들지 않는다). */
114
+ export function readConfigHistory(key: string, dbPath?: string): ConfigChangeRow[] {
115
+ const path = configAuditDbPath(dbPath);
116
+ if (path !== ':memory:' && !existsSync(path)) return [];
117
+ const db = path === ':memory:' ? openConfigChangesDb(path) : new Database(path, { readonly: true });
118
+ try {
119
+ return db.query('SELECT at, key, prev, next, by, why FROM config_changes WHERE key = ? ORDER BY at ASC, rowid ASC').all(key) as ConfigChangeRow[];
120
+ } finally {
121
+ if (path !== ':memory:') db.close();
122
+ }
123
+ }
@@ -11,6 +11,7 @@ import { getUserConfig } from '../user-config.js';
11
11
  import { projectDecisionsToLinear } from '../decisions/decision-linear-projection.js';
12
12
  import { DecisionLedger, importDecisionMarkdown, type DecisionCategory, type DecisionLedgerOptions, type DecisionOption, type DecisionTrack, type DecisionEntry, type Seat, type SeatDecisionRecord } from '../decisions/decision-ledger.js';
13
13
  import { formatProactMeter, readProactMeter } from '../decisions/proact-meter.js';
14
+ import { CROWN_MARK, CROWN_THRESHOLD_CATEGORIES, CONSENSUS_CATEGORIES, ConsensusEngine, MAX_REVIEW_ROUND_TRIPS, categoryLabel, representativeLabel, type ConsensusCategory, type ConsensusRepresentative, type CrownCard, type ProposalCard } from '../loops/consensus.js';
14
15
  import { writeStdoutFully } from './stdout-flush.js';
15
16
 
16
17
  const repeat = (value: string, values: string[]) => [...values, value];
@@ -62,6 +63,14 @@ export function formatSeatDecisionRow(e: SeatDecisionRecord): string {
62
63
  return `${e.id} · 결정: ${e.decidedAt ? kst(e.decidedAt) : '시각 미상'} · 기록: ${e.recordedAt ? kst(e.recordedAt) : '시각 미상'} · ${e.seat} 결정 · 사후 보고 · ${e.title} → ${e.decision} · 위임: ${e.delegation}${e.refs?.length ? ` · 참조: ${e.refs.join(' · ')}` : ''}`;
63
64
  }
64
65
 
66
+ export function formatProposalRow(p: ProposalCard): string {
67
+ return `${p.id} · ${categoryLabel(p.category)} · ${p.title} · 사실 ${p.factId} · 비용 ${p.cost} · 되돌리기 ${p.undo}${p.thresholds.length ? ` · ${CROWN_MARK} 몫 ${p.thresholds.join('|')}` : ''} · 제안 ${representativeLabel(p.proposedBy)} · ${kst(p.proposedAt)} · 왕복 ${p.roundTrips}/${MAX_REVIEW_ROUND_TRIPS} · ${p.status === 'open' ? '검토 중' : p.status === 'agreed' ? '합의·실행·기록' : '불합의'}`;
68
+ }
69
+
70
+ export function formatCrownCardRow(c: CrownCard): string {
71
+ return `${c.id} · ${CROWN_MARK} ${c.reason === 'disagreement' ? '불합의' : '임계 승인'} · 제안 ${c.proposalId} · 조율자 주장: ${c.coordinatorClaim} | 수호자 주장: ${c.guardianClaim}${c.decisionId ? ` · 결정 카드 ${c.decisionId}` : ''}`;
72
+ }
73
+
65
74
  export function registerDecisionsCommands(program: Command, config: DecisionLedgerOptions = {}, out: Pick<Console, 'log'> = console, hqDeps: HqDeps = {}): void {
66
75
  const noXcheck = new Option('--no-xcheck <이유>', '교차 확인 생략 이유');
67
76
  // This flag takes a reason, not Commander's negated boolean default.
@@ -176,14 +185,24 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
176
185
  if (!o.auto && (o.delegation || o.track || o.agent)) throw new Error('delegation/track/agent require --auto');
177
186
  const by = o.auto ? { kind: 'auto' as const, agent: agent(o.agent), delegation: o.delegation!, ...(o.track ? { track: o.track } : {}) } : { kind: 'human' as const };
178
187
  if (!mayWrite('decide', o.hqOverride)) return;
179
- const { entry, delivery } = new DecisionLedger(config).decideWithDelivery(id, choice, by, o.note);
180
- if (delivery && !delivery.ok) {
181
- // The decision is recorded; only the answer to the waiting run failed — say so and how to retry, never «success».
182
- const hint = `⚠ 답 전달 실패(${delivery.questionId} · ${delivery.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-answer ${entry.id}`;
188
+ const { entry, delivery, notice } = new DecisionLedger(config).decideWithDelivery(id, choice, by, o.note);
189
+ const failures = [
190
+ ...(delivery && !delivery.ok ? [`⚠ 답 전달 실패(${delivery.questionId} · ${delivery.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-answer ${entry.id}`] : []),
191
+ ...(notice.status === 'failed' ? [`⚠ 자리 우편 실패(${notice.seat} · ${notice.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-notify ${entry.id}`] : []),
192
+ ];
193
+ if (failures.length) {
183
194
  process.exitCode = 3;
184
- return emit({ ...entry, delivery }, o.json, `결정: ${formatDecisionDetail(entry)}\n${hint}`);
195
+ return emit({ ...entry, ...(delivery ? { delivery } : {}), notice }, o.json, `결정: ${formatDecisionDetail(entry)}\n${failures.join('\n')}`);
185
196
  }
186
- return emit(delivery ? { ...entry, delivery } : entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
197
+ const sent = notice.status === 'sent' ? `\n자리 우편: ${notice.seat} #${notice.messageId}` : '';
198
+ return emit({ ...entry, ...(delivery ? { delivery } : {}), notice }, o.json, `결정: ${formatDecisionDetail(entry)}${sent}`);
199
+ }));
200
+ root.command('retry-notify <id>').description('기록된 결정의 올린 자리 우편만 중복 없이 재시도한다').option('--json').option('--hq-override')
201
+ .action((id: string, o: { json?: boolean; hqOverride?: boolean }) => fail(() => {
202
+ if (!mayWrite('retry-notify', o.hqOverride)) return;
203
+ const notice = new DecisionLedger(config).retryNotice(id);
204
+ if (notice.status === 'failed') process.exitCode = 3;
205
+ return emit(notice, o.json, notice.status === 'sent' ? `자리 우편: ${notice.seat} #${notice.messageId}` : notice.status === 'skipped' ? '올린 자리 없음 — 우편 대상 없음' : `⚠ 자리 우편 실패(${notice.seat} · ${notice.reason})`);
187
206
  }));
188
207
  root.command('retry-answer <id>').description('기록된 결정의 대기 질문 답 전달만 재시도한다').option('--json').option('--hq-override')
189
208
  .action((id: string, o: { json?: boolean; hqOverride?: boolean }) => fail(() => {
@@ -209,4 +228,59 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
209
228
  if (result.unread.length) process.exitCode = 1;
210
229
  return emit(result, o.json, `가져옴 ${result.imported.length} · 기존 ${result.existing.length} · 불완전 ${result.incomplete.length} · 못 읽음 ${result.unread.length}${result.incomplete.length ? `\n${result.incomplete.join('\n')}` : ''}${result.unread.length ? `\n${result.unread.join('\n')}` : ''}`);
211
230
  }));
231
+ const consensusRoot = root.command('consensus').description('두 대표 합의 — 조율자(일의 흐름)·수호자(몸)의 다섯 범주는 «둘의 합의» 뒤에 실행');
232
+ const consensusEngine = () => new ConsensusEngine({ stateDir: config.stateDir, now: config.now, resolveVersion: config.resolveVersion });
233
+ consensusRoot.command('propose').description('제안 카드를 올린다 — 사실 id·비용·되돌리기')
234
+ .requiredOption('--by <representative>', '제안 대표 (coordinator|guardian)')
235
+ .requiredOption('--category <category>', `합의 범주 (${CONSENSUS_CATEGORIES.join('|')})`)
236
+ .requiredOption('--title <text>').requiredOption('--fact-id <id>', '사실 id')
237
+ .requiredOption('--cost <text>', '비용').requiredOption('--undo <text>', '되돌리기')
238
+ .option('--threshold <category>', `${CROWN_MARK} 몫 임계 범주 (반복: ${CROWN_THRESHOLD_CATEGORIES.join('|')})`, repeat, [])
239
+ .option('--provider <name>', 'LLM 제공자 표식 — 가능하면 상대와 다른 제공자 (메아리 방지)')
240
+ .option('--json').option('--hq-override')
241
+ .action((o: { by: string; category: string; title: string; factId: string; cost: string; undo: string; threshold: string[]; provider?: string; json?: boolean; hqOverride?: boolean }) => fail(() => {
242
+ if (!mayWrite('consensus propose', o.hqOverride)) return;
243
+ const proposal = consensusEngine().propose({
244
+ by: o.by as ConsensusRepresentative, category: o.category as ConsensusCategory, title: o.title, factId: o.factId, cost: o.cost, undo: o.undo,
245
+ thresholds: o.threshold.map(threshold => threshold as DecisionCategory), provider: o.provider,
246
+ });
247
+ return emit(proposal, o.json, `제안: ${formatProposalRow(proposal)}`);
248
+ }));
249
+ consensusRoot.command('review <id>').description('상대 검토 왕복을 남긴다 — 최대 2왕복, 마지막 왕복은 결론으로')
250
+ .requiredOption('--by <representative>', '검토 대표 — 제안한 대표의 상대 (coordinator|guardian)')
251
+ .requiredOption('--claim <text>', '검토 주장')
252
+ .option('--provider <name>', 'LLM 제공자 표식 (메아리 방지)')
253
+ .option('--json').option('--hq-override')
254
+ .action((id: string, o: { by: string; claim: string; provider?: string; json?: boolean; hqOverride?: boolean }) => fail(() => {
255
+ if (!mayWrite('consensus review', o.hqOverride)) return;
256
+ const proposal = consensusEngine().review(id, { by: o.by as ConsensusRepresentative, claim: o.claim, provider: o.provider });
257
+ return emit(proposal, o.json, `검토 ${proposal.roundTrips}/${MAX_REVIEW_ROUND_TRIPS}왕복: ${formatProposalRow(proposal)}`);
258
+ }));
259
+ consensusRoot.command('agree <id>').description(`상대 대표의 합의 — 실행·합의 원장 기록 (임계 범주면 ${CROWN_MARK} 카드도 함께)`)
260
+ .requiredOption('--by <representative>', '합의 대표 — 제안한 대표의 상대 (coordinator|guardian)')
261
+ .option('--claim <text>', '합의 주장 (생략 시 제안대로 실행)')
262
+ .option('--provider <name>', 'LLM 제공자 표식 (메아리 방지)')
263
+ .option('--json').option('--hq-override')
264
+ .action((id: string, o: { by: string; claim?: string; provider?: string; json?: boolean; hqOverride?: boolean }) => fail(() => {
265
+ if (!mayWrite('consensus agree', o.hqOverride)) return;
266
+ const { proposal, crownCard } = consensusEngine().agree(id, { by: o.by as ConsensusRepresentative, claim: o.claim, provider: o.provider });
267
+ return emit({ proposal, ...(crownCard ? { crownCard } : {}) }, o.json,
268
+ `합의: ${formatProposalRow(proposal)}${crownCard ? `\n${CROWN_MARK} 카드: ${formatCrownCardRow(crownCard)}` : ''}`);
269
+ }));
270
+ consensusRoot.command('disagree <id>').description(`상대 대표의 불합의 — 양쪽 주장 나란히 ${CROWN_MARK} 결정 카드`)
271
+ .requiredOption('--by <representative>', '불합의 대표 — 제안한 대표의 상대 (coordinator|guardian)')
272
+ .requiredOption('--claim <text>', `불합의 주장 — ${CROWN_MARK} 카드에 나란히 실린다`)
273
+ .option('--provider <name>', 'LLM 제공자 표식 (메아리 방지)')
274
+ .option('--json').option('--hq-override')
275
+ .action((id: string, o: { by: string; claim: string; provider?: string; json?: boolean; hqOverride?: boolean }) => fail(() => {
276
+ if (!mayWrite('consensus disagree', o.hqOverride)) return;
277
+ const { proposal, crownCard } = consensusEngine().disagree(id, { by: o.by as ConsensusRepresentative, claim: o.claim, provider: o.provider });
278
+ return emit({ proposal, crownCard }, o.json, `불합의: ${formatProposalRow(proposal)}\n${CROWN_MARK} 카드: ${formatCrownCardRow(crownCard)}`);
279
+ }));
280
+ consensusRoot.command('crown').description(`${CROWN_MARK} 결정 카드 목록 — 불합의·임계 범주만 만든다`)
281
+ .option('--json')
282
+ .action((o: { json?: boolean }) => fail(() => {
283
+ const cards = consensusEngine().crownCards();
284
+ return emit(cards, o.json, cards.length ? cards.map(formatCrownCardRow).join('\n') : `${CROWN_MARK} 결정 카드 0건`);
285
+ }));
212
286
  }