elanous 0.2.28 → 0.2.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (818) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +23 -0
  15. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +41 -0
  18. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 2213.2ccbada92c33ea0f.js} +3 -3
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2940-619bfd8ef337c611.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{3143.257997a5f1ed79df.js → 3902.e1e71aaac850a045.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/{1146.80d15ea7c6e6ee95.js → 4111.2bfedbb233ad206b.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{9938.b23e4d4dfa0114cd.js → 4999.c064a4000c2a9e94.js} +2 -2
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{1157.f08bf2b70915e176.js → 5304.04d24756f242a094.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{7752.5cbdd0b433c54af9.js → 5307.60f2209e809bd627.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{3309.364573ceedbdfd5f.js → 6323.8672b4817a306928.js} +1 -1
  74. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 6433.fc573af22bbc9ab7.js} +4 -4
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{949.1e7d45ccb71580aa.js → 6517.4147878ac06d584d.js} +2 -2
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/{2528.3868070ef1be69f9.js → 6767.ea607cf0c20a25af.js} +2 -2
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  93. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  94. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 7862.30a8d6482bb238eb.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2697.76ca2ac3efef6f3b.js → 8018.a32663f04a6fc5f9.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  109. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 9279-d28c5b7754d010ae.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9398-6aed28f0a96d0d6f.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/997ce8a5-2ad501927003b41b.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 9989.3694300e5f000b14.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-fa46d4588e8442c2.js → page-2ebb8fd59b9461f9.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/{page-ced0bcfc6542b3fc.js → page-349f2752d8cd37ad.js} +1 -1
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-cb249e81ed339318.js → page-0a07363b130182a1.js} +1 -1
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{e87d89b9.2e71c0ae475d28a1.js → e5012ffe.f727e23c231f4342.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{e117f801.e92bf10242653497.js → ebc7d829.264a0bcb6c750b50.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  183. package/apps/pwa/out/_next/static/css/{72becfd42807b50d.css → 3f5fc6f96e2cf7b2.css} +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/bin/elanous.mjs +7 -3
  278. package/graphs/context/nightly-condense.yaml +1 -0
  279. package/graphs/intake/intake-daily.yaml +8 -1
  280. package/graphs/intake/recipes.yaml +5 -0
  281. package/graphs/lecture/lecture-note.yaml +2 -2
  282. package/graphs/ops/harness-gc.yaml +1 -0
  283. package/graphs/release/recipes.yaml +3 -0
  284. package/graphs/release/release-loop.yaml +15 -7
  285. package/graphs/units/recipes.yaml +3 -0
  286. package/graphs/units/release-gate-recheck.yaml +15 -0
  287. package/package.json +2 -1
  288. package/plugins/agent-team/agents/research.md +1 -0
  289. package/scripts/check-native-tool-wiring.ts +3 -2
  290. package/scripts/ci-android-unit-tests.ts +16 -0
  291. package/scripts/ci-typecheck-changed.ts +40 -11
  292. package/scripts/coord-channel-watch.sh +45 -19
  293. package/scripts/coord-role-pack.ts +222 -0
  294. package/scripts/cron-run.ts +96 -3
  295. package/scripts/detect-test-interference.ts +38 -5
  296. package/scripts/gate-pr-cache.ts +65 -0
  297. package/scripts/gh-surface/capture.ts +126 -0
  298. package/scripts/gh-surface/gh +40 -0
  299. package/scripts/import-graph-scc.ts +38 -0
  300. package/scripts/install.ps1 +19 -0
  301. package/scripts/intake-social.ts +181 -0
  302. package/scripts/lecture-note/node.ts +71 -4
  303. package/scripts/lib/android-toolchain.ts +32 -0
  304. package/scripts/lib/deterministic-env.ts +62 -0
  305. package/scripts/lib/gate-test-env.ts +19 -0
  306. package/scripts/lib/morning-report-options.ts +41 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  310. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  311. package/scripts/release-loop/cut-branch.ts +4 -3
  312. package/scripts/release-loop/export-check-node.ts +0 -1
  313. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  314. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  315. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  316. package/scripts/release-loop/gate-batch-safe.ts +23 -0
  317. package/scripts/release-loop/gate-closure.ts +12 -8
  318. package/scripts/release-loop/gate-diff.ts +1 -1
  319. package/scripts/release-loop/gate-history.ts +422 -0
  320. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  321. package/scripts/release-loop/gate-node.ts +806 -94
  322. package/scripts/release-loop/gate-partial.ts +106 -9
  323. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  324. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  325. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  326. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  327. package/scripts/release-loop/gate-triage-node.ts +190 -0
  328. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  329. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  330. package/scripts/release-loop/import-graph-scc.ts +215 -0
  331. package/scripts/release-loop/node-verdict.ts +2 -0
  332. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  333. package/scripts/release-loop/resume-release.ts +33 -4
  334. package/scripts/release-loop/resume.ts +13 -5
  335. package/scripts/release-loop/spawn-lane.ts +51 -0
  336. package/scripts/release-loop/tui-node-checks.ts +23 -0
  337. package/scripts/release-loop/tui-sim-node.ts +3 -2
  338. package/scripts/release-loop/unattended-release.ts +16 -0
  339. package/scripts/release-loop/version-node.ts +62 -4
  340. package/scripts/test-deterministic.ts +46 -73
  341. package/scripts/train-reach-grouping.ts +48 -0
  342. package/scripts/tsc-incremental-cache.ts +86 -0
  343. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  344. package/scripts/tsc-main-safety-net.ts +2 -2
  345. package/scripts/usage-rollup.ts +11 -3
  346. package/src/acp/client.ts +4 -1
  347. package/src/acp/core-turn-bridge.ts +145 -24
  348. package/src/acp/elanous-extensions.ts +2 -0
  349. package/src/acp/server.ts +2 -0
  350. package/src/ad-pipeline/run.ts +4 -2
  351. package/src/agent/ref-grounding.ts +18 -0
  352. package/src/agent/runner.ts +169 -3
  353. package/src/agent/subagent-callable.ts +3 -2
  354. package/src/agent-mission/review-loop.ts +6 -3
  355. package/src/agent-substrate/acp-implementer.ts +14 -2
  356. package/src/agent-substrate/pr-reviewer.ts +41 -21
  357. package/src/agent-substrate/self-review-cli.ts +30 -4
  358. package/src/autopilot/pr-manager.ts +62 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/budget/pty-usage-reemit.ts +7 -0
  361. package/src/budget/run-usage-rollup.ts +9 -0
  362. package/src/budget/usage-daily-store.ts +98 -0
  363. package/src/capture/tui-self-report.ts +37 -4
  364. package/src/chat/chat-cli.ts +10 -2
  365. package/src/chat/index.ts +107 -20
  366. package/src/chat/input-control-key.ts +5 -3
  367. package/src/chat/pickers/modal-runtime.ts +1 -0
  368. package/src/chat/pickers/modals.ts +3 -1
  369. package/src/chat/tool-interrupt-behavior.ts +38 -0
  370. package/src/chat/tool-render/dispatch.ts +5 -1
  371. package/src/chat/turn-typeahead.ts +191 -29
  372. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  373. package/src/cli/agent-cli.ts +41 -13
  374. package/src/cli/config-audit.ts +123 -0
  375. package/src/cli/dashboard-name-flag.ts +48 -0
  376. package/src/cli/decisions-cli.ts +80 -6
  377. package/src/cli/doctor-cli.ts +80 -0
  378. package/src/cli/log-event-names.ts +19 -0
  379. package/src/cli/mcp-login.ts +21 -5
  380. package/src/cli/msg-cli.ts +133 -2
  381. package/src/cli/pr-cli.ts +546 -112
  382. package/src/cli/pr-land-heavy-remote.ts +233 -0
  383. package/src/cli/pr-land-overlap-evidence.ts +167 -14
  384. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  387. package/src/cli/pty-takeover-cli.ts +125 -16
  388. package/src/cli/release-cli.ts +122 -14
  389. package/src/cli/remote-resolve.ts +2 -1
  390. package/src/cli/seat-cli.ts +164 -19
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/tasks-cli.ts +105 -21
  393. package/src/cli/usage-cli.ts +146 -12
  394. package/src/cli/usage-daily-cli.ts +84 -0
  395. package/src/context-bus/context-first.ts +13 -0
  396. package/src/context-bus/context-now.ts +95 -7
  397. package/src/context-bus/ops-events.ts +75 -0
  398. package/src/control-plane/lease-holder.ts +12 -8
  399. package/src/control-plane/ledger.ts +163 -4
  400. package/src/control-plane/server.ts +91 -11
  401. package/src/core-turn/auth-rejected-notice.ts +41 -0
  402. package/src/core-turn/run-core-turn.ts +14 -2
  403. package/src/core-turn/run-goal-loop.ts +239 -4
  404. package/src/core-turn/seat-turn-cap.ts +79 -0
  405. package/src/core-turn/short-question.ts +78 -13
  406. package/src/core-turn/types.ts +10 -0
  407. package/src/dashboard/acp-active-model.ts +40 -0
  408. package/src/dashboard/acp-boot.ts +3 -0
  409. package/src/dashboard/auto-compact-runtime.ts +2 -0
  410. package/src/dashboard/boot-banner.ts +80 -0
  411. package/src/dashboard/dashboard-status-lines.ts +11 -0
  412. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  413. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  414. package/src/dashboard/goal-loop-thinking.ts +16 -0
  415. package/src/dashboard/hitl-boot.ts +9 -4
  416. package/src/dashboard/index.ts +448 -998
  417. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  418. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  419. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  420. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +176 -4
  421. package/src/dashboard/input/chat-main-session.ts +14 -3
  422. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  423. package/src/dashboard/input/chat-main-turn.ts +14 -4
  424. package/src/dashboard/input/compact-prepass-recovery.ts +130 -0
  425. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  426. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  427. package/src/dashboard/input/external-input-host.ts +71 -0
  428. package/src/dashboard/input/internal-turn.ts +261 -0
  429. package/src/dashboard/input/log-fold-binding.ts +18 -0
  430. package/src/dashboard/input/mouse-wiring.ts +17 -4
  431. package/src/dashboard/input/seat-autowake.ts +318 -0
  432. package/src/dashboard/input/turn-steer-bridge.ts +164 -0
  433. package/src/dashboard/log-click-runtime.ts +5 -3
  434. package/src/dashboard/loop-scheduler.ts +72 -0
  435. package/src/dashboard/running-build-status.ts +74 -0
  436. package/src/dashboard/seat-boot-preamble.ts +131 -0
  437. package/src/dashboard/seat-local-instructions.ts +305 -0
  438. package/src/dashboard/skill-runtime.ts +2 -0
  439. package/src/dashboard/slash-runtime/dashboard-handlers.ts +220 -1203
  440. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  441. package/src/dashboard/slash-runtime/index.ts +13 -0
  442. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  443. package/src/dashboard/term-slash-runtime.ts +15 -0
  444. package/src/dashboard/turn-busy-teardown.ts +50 -0
  445. package/src/dashboard/turn-preamble.ts +30 -2
  446. package/src/dashboard/turn-session-layers.ts +176 -0
  447. package/src/dashboard/turn-stream-formatter.ts +14 -6
  448. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  449. package/src/decisions/decision-ledger.ts +45 -4
  450. package/src/discord-self-message.ts +4 -4
  451. package/src/domains/release-tool.ts +26 -10
  452. package/src/domains/surface-events.ts +4 -1
  453. package/src/domains/watch-default-scheduler.ts +8 -9
  454. package/src/field-note/transcribe.ts +17 -0
  455. package/src/fold-stack.ts +24 -1
  456. package/src/git-fs/dirty.ts +32 -4
  457. package/src/git-fs/index.ts +43 -1
  458. package/src/github/remote-call.ts +81 -0
  459. package/src/goals/registry.ts +46 -6
  460. package/src/goals/types.ts +7 -1
  461. package/src/graph-runner/runner.ts +2 -0
  462. package/src/grok/credential.ts +26 -0
  463. package/src/harness/harness-clean.ts +2 -1
  464. package/src/harness/harness-cli-command.ts +52 -5
  465. package/src/harness/harness-gc.ts +34 -6
  466. package/src/harness/harness-incidents.ts +57 -20
  467. package/src/harness/harness-pod-dispatch.ts +87 -10
  468. package/src/harness/harness-queue.ts +53 -4
  469. package/src/harness/harness-stop.ts +4 -3
  470. package/src/harness/harness-substrate-default.ts +78 -7
  471. package/src/harness/harness-worktree-auto.ts +2 -1
  472. package/src/harness/harness-worktrees.ts +3 -2
  473. package/src/hooks/dispatch.ts +2 -1
  474. package/src/index.ts +166 -26
  475. package/src/input/external-input-queue.ts +251 -0
  476. package/src/intake-plane/slash.ts +14 -3
  477. package/src/interactive-terminal-modal.ts +13 -0
  478. package/src/keybindings.ts +4 -1
  479. package/src/llm/route-decision.ts +25 -0
  480. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  481. package/src/llm-stream-retry-display.ts +59 -0
  482. package/src/llm.ts +391 -74
  483. package/src/log-entry.ts +3 -3
  484. package/src/log-pane/search.ts +29 -4
  485. package/src/loops/agent-reply.ts +256 -0
  486. package/src/loops/budget.ts +37 -7
  487. package/src/loops/consensus.ts +348 -0
  488. package/src/loops/loop-cli.ts +3 -2
  489. package/src/loops/msg-address.ts +57 -0
  490. package/src/loops/msg-wake.ts +484 -0
  491. package/src/loops/observe.ts +19 -3
  492. package/src/loops/orchestrator/inbox.ts +60 -3
  493. package/src/loops/orchestrator/tick.ts +80 -6
  494. package/src/loops/orchestrator/traffic.ts +64 -1
  495. package/src/loops/registry.ts +72 -4
  496. package/src/market/signed-index.ts +14 -0
  497. package/src/mcp/mcp-oauth.ts +54 -5
  498. package/src/memory.ts +20 -5
  499. package/src/models/prompts.ts +28 -0
  500. package/src/msg/msg-sse-client.ts +223 -0
  501. package/src/msg/msg-store.ts +86 -2
  502. package/src/mss/logging/log-store.ts +225 -1
  503. package/src/native-tool-catalog.ts +125 -0
  504. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  505. package/src/nexus/api/http-server.ts +59 -15
  506. package/src/nexus/api/loop-resources.ts +19 -3
  507. package/src/nexus/api/ops-api.ts +13 -0
  508. package/src/nexus/api/project-autopsy.ts +127 -0
  509. package/src/nexus/api/terminals.ts +3 -0
  510. package/src/nexus/api/workflow-approvals.ts +2 -0
  511. package/src/nexus/daemon-thin-inventory.md +37 -0
  512. package/src/nexus/index.ts +70 -0
  513. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  514. package/src/nexus/state/state.ts +1 -0
  515. package/src/oauth/codex-account-store.ts +15 -3
  516. package/src/oauth/codex-billing-route.ts +31 -0
  517. package/src/oauth/store.ts +32 -7
  518. package/src/onboarding/first-run.ts +28 -3
  519. package/src/ops/overview-cache.ts +16 -4
  520. package/src/ops/overview-collect.ts +19 -2
  521. package/src/ops/resources.ts +82 -0
  522. package/src/panes/log-pane.ts +67 -8
  523. package/src/persona/presets.ts +44 -0
  524. package/src/plugins/maker/connector-maker.ts +41 -0
  525. package/src/plugins/maker/skill-maker.ts +42 -0
  526. package/src/plugins/maker/wizard-generate.ts +6 -4
  527. package/src/pr-tool/census.ts +288 -0
  528. package/src/preview/terminal.ts +14 -1
  529. package/src/prompt-cache/types.ts +2 -0
  530. package/src/prompt-enhance/enhance.ts +24 -8
  531. package/src/prompt-library/chat-conciseness.ts +13 -0
  532. package/src/prompt-library/universal-preamble.ts +283 -61
  533. package/src/pty-shell/pty-control-ipc.ts +4 -1
  534. package/src/pty-shell/pty-manifest.ts +77 -5
  535. package/src/pty-shell/registry.ts +19 -2
  536. package/src/pty-shell/tui-run-state.ts +253 -0
  537. package/src/release-loop/gate-host-reservation.ts +97 -0
  538. package/src/release-loop/landing-freeze.ts +5 -0
  539. package/src/release-loop/light-rc.ts +32 -4
  540. package/src/release-loop/placement.ts +92 -1
  541. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  542. package/src/release-loop/rehearsal.ts +73 -17
  543. package/src/render.ts +5 -1
  544. package/src/repl/index.ts +20 -2
  545. package/src/seat-loop/seat-knowhow.ts +282 -0
  546. package/src/seat-loop/seat-loop.ts +41 -2
  547. package/src/seat-loop/seat-report.ts +42 -2
  548. package/src/seat-loop/traffic-signal.ts +3 -0
  549. package/src/self-dev/ask-launch-flow.ts +24 -3
  550. package/src/self-dev/decompose-compose-graph.ts +28 -27
  551. package/src/self-dev/decompose-proposal.ts +53 -38
  552. package/src/self-dev/decompose.ts +17 -0
  553. package/src/self-dev/dev-pipeline.ts +31 -2
  554. package/src/self-dev/draft-residue.ts +24 -9
  555. package/src/self-dev/draft-sweep.ts +59 -4
  556. package/src/self-dev/external-call-zero.ts +77 -0
  557. package/src/self-dev/launch-preflight-text.ts +6 -0
  558. package/src/self-dev/launch-preflight.ts +25 -3
  559. package/src/self-dev/local-supervisor-judge.ts +185 -0
  560. package/src/self-dev/run-supervisor.ts +300 -24
  561. package/src/self-dev/run-types.ts +20 -0
  562. package/src/self-dev/shard-aggregate.ts +15 -2
  563. package/src/self-dev/shard-plan.ts +47 -0
  564. package/src/self-dev/shard-run.ts +135 -12
  565. package/src/self-dev/spawn-lane-files.ts +19 -0
  566. package/src/self-health/signatures.ts +132 -0
  567. package/src/self-implement/app-api-budget.ts +51 -11
  568. package/src/self-implement/config-gate.ts +2 -1
  569. package/src/self-implement/doctor-visit.ts +118 -0
  570. package/src/self-implement/expose-gate.ts +2 -1
  571. package/src/self-implement/gate-artifacts.ts +405 -0
  572. package/src/self-implement/gate-cli.ts +212 -18
  573. package/src/self-implement/gate-remote.ts +110 -25
  574. package/src/self-implement/gate-scenario.ts +85 -0
  575. package/src/self-implement/goal-author-decompose.ts +80 -16
  576. package/src/self-implement/goal-author.ts +270 -76
  577. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  578. package/src/self-implement/goal-file-name.ts +65 -0
  579. package/src/self-implement/graph-authority.ts +38 -6
  580. package/src/self-implement/graph-overlay-condition.ts +92 -1
  581. package/src/self-implement/ground-goal.ts +2 -1
  582. package/src/self-implement/heal-triage.ts +79 -0
  583. package/src/self-implement/host-regate.ts +74 -2
  584. package/src/self-implement/orchestrator.ts +14 -123
  585. package/src/self-implement/pr-title.ts +123 -0
  586. package/src/self-implement/review-mustfix-class.ts +115 -0
  587. package/src/self-implement/run-checkpoint.ts +235 -0
  588. package/src/self-implement/run-ledger.ts +266 -17
  589. package/src/self-implement/run-stop.ts +4 -3
  590. package/src/self-implement/run-ttl.ts +28 -4
  591. package/src/self-implement/running-runs.ts +10 -6
  592. package/src/self-implement/seams.ts +2 -0
  593. package/src/self-implement/self-implement-runtime.ts +32 -0
  594. package/src/self-implement/shadow-stage.ts +7 -6
  595. package/src/self-implement/stop-autoheal.ts +2 -1
  596. package/src/self-implement/train-gate-remote.ts +37 -8
  597. package/src/self-implement/train-reach-grouping.ts +157 -0
  598. package/src/self-implement/train-scenario-layers.ts +133 -0
  599. package/src/self-implement/uncommitted-work.ts +2 -0
  600. package/src/session/pending-input.ts +81 -11
  601. package/src/session/session-start.ts +224 -0
  602. package/src/session-runtime/index.ts +7 -1
  603. package/src/session-runtime/parallel-dispatch.ts +22 -5
  604. package/src/skills/tools/dev-harness.ts +6 -4
  605. package/src/skills/tools/ops-ledger.ts +707 -0
  606. package/src/skills/tools/persistent-grounding.ts +47 -7
  607. package/src/skills/tools/shell.ts +117 -1
  608. package/src/status/bar.ts +32 -2
  609. package/src/status/status-provider-info.ts +58 -0
  610. package/src/steward/resync-tick.ts +114 -23
  611. package/src/steward/ta-repair-event-collect.ts +158 -0
  612. package/src/task-agent/card-evidence.ts +25 -1
  613. package/src/task-agent/green-sweep.ts +8 -3
  614. package/src/task-agent/judge.ts +76 -0
  615. package/src/task-agent/land-queue.ts +79 -0
  616. package/src/task-agent/live-moves.ts +30 -9
  617. package/src/task-agent/postland-card.ts +5 -0
  618. package/src/task-agent/prelaunch-already-done.ts +98 -0
  619. package/src/task-agent/real-launch-guard.ts +37 -0
  620. package/src/task-agent/rejudge-on-head.ts +93 -13
  621. package/src/task-agent/remote-rejudge-bind.ts +62 -13
  622. package/src/task-agent/repair-cycle.ts +58 -7
  623. package/src/task-agent/repair-worker.ts +7 -0
  624. package/src/task-agent/run-identity.ts +200 -0
  625. package/src/task-agent/shadow.ts +50 -3
  626. package/src/task-agent/task-hand.ts +158 -5
  627. package/src/task-agent/train-landing.ts +77 -0
  628. package/src/task-agent/work-order.ts +104 -0
  629. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  630. package/src/task-orchestrator/surfaces/pod-command-job.ts +138 -22
  631. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  632. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  633. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  634. package/src/task-orchestrator/surfaces/pod-install-slots.ts +122 -15
  635. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  636. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  637. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +103 -0
  638. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  639. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  640. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  641. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  642. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  643. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  644. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  645. package/src/task-orchestrator/surfaces/self-implement-pod.ts +237 -46
  646. package/src/telegram.ts +2 -4
  647. package/src/terminal/session-registry.ts +6 -0
  648. package/src/thinking-line.ts +12 -3
  649. package/src/tool-runtime/index.ts +4 -0
  650. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  651. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  652. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  653. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  654. package/src/tui/input/pickers.ts +732 -0
  655. package/src/tui/slash/mission.ts +492 -0
  656. package/src/tui/slash/term.ts +877 -0
  657. package/src/tui-client/dashboard-session.ts +9 -0
  658. package/src/tui.ts +53 -0
  659. package/src/user-config/gemini-server-tools.ts +9 -0
  660. package/src/user-config.ts +106 -21
  661. package/src/util/spawn-sync-output.ts +7 -0
  662. package/src/ux-sim/fake-bin.ts +154 -0
  663. package/src/ux-sim/fake-clock.ts +36 -0
  664. package/src/ux-sim/fake-llm.ts +29 -0
  665. package/src/ux-sim/headless-tui.ts +72 -0
  666. package/src/ux-sim/in-process-cli.ts +176 -0
  667. package/src/ux-sim/temp-git-remote.ts +82 -0
  668. package/src/version/packed-revision.json +1 -1
  669. package/src/video-pipeline/recipes/vlog.ts +25 -7
  670. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  675. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  682. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  688. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  693. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  698. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  703. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  706. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  708. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  718. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  722. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  724. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  726. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  734. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  742. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  744. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  745. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  748. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  750. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  751. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  752. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/973cbf1b.3bbcf2b41548eca7.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/ceo/page-66ad46ed0279feb9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/loops/page-646b50f63b6fe732.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/morning/page-6f131b51193a36f9.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
  802. package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
  803. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
  804. package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
  805. package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
  806. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
  807. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  808. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  809. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  810. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  811. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  812. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  813. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  814. package/src/dashboard/bench-slash-runtime.ts +0 -40
  815. package/src/dashboard/input/search-modal-router.ts +0 -9
  816. package/src/dashboard/modals/pane-key-router.ts +0 -27
  817. package/src/dashboard/view-slash-runtime.ts +0 -48
  818. /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -41,6 +41,10 @@ import { attachLifecycleBridge } from '../signal/lifecycle-bridge.js';
41
41
  import { getChannelBus } from '../terminal-matrix/index.js';
42
42
  import type { ChannelBus } from '../terminal-matrix/channel-bus.js';
43
43
  import { startChildLivenessHeartbeat } from './child-liveness-heartbeat.js';
44
+ import {
45
+ SEAT_IDLE_NO_WORK_NOTICE, SEAT_TURN_CAP_CONTINUE_PROMPT, SEAT_TURN_CAP_TOOL_NOTICE,
46
+ isEmptyMailListResult, isIdleWaitCall, type SeatTurnCapConfig,
47
+ } from './seat-turn-cap.js';
44
48
 
45
49
  export {
46
50
  CHILD_LIVENESS_HEARTBEAT_ENV,
@@ -164,6 +168,11 @@ export function buildUpdateGoalToolSpec(): LLMToolSpec {
164
168
  };
165
169
  }
166
170
 
171
+ /** 반려·재요청은 모델에게만 가는 내부 지시다 — 사용자 답에 그 사정(«완료 주장이 거부됐다»·«죄송합니다»)이 새지 않게 한다
172
+ * (10-14 OPT 점검: evidence·rejected 판정 14회가 사용자 답의 사과 문장으로 나왔다). */
173
+ export const GOAL_INTERNAL_NOTICE_RULE =
174
+ '이 반려·재요청은 내부 지시다. 사용자에게 보이는 답에 «완료 주장이 거부됐다/어긋났다»·«죄송합니다» 같은 내부 사정을 쓰지 말고, 고친 결과와 사실만 말하라.';
175
+
167
176
  /** 목표 실행 계약 — 첫 turn 앞에 leading system 메시지로 주입. codex 자체 prompt.md /
168
177
  * ext-goal continuation.md 의 지속·anti-shrink·증거완료 언어 이식. ASCII + 한국어. */
169
178
  export const GOAL_SYSTEM_PREAMBLE = [
@@ -173,6 +182,7 @@ export const GOAL_SYSTEM_PREAMBLE = [
173
182
  '- 완료는 증거로 판정한다. 모든 요구사항/산출물/검증에 대해 실제 현재 상태에서 증거를 확인하라. 불확실하거나 간접적인 증거는 미달성으로 보고 계속하라.',
174
183
  `- 목표가 실제로 완전히 끝났고 증거로 확인됐을 때만 ${UPDATE_GOAL_TOOL_NAME} 도구를 status="complete" 로 호출하고 evidence 에 그 증거를 적어 종료하라. 완료 신호는 이 도구 호출뿐이다(텍스트 문장이 아니다).`,
175
184
  '- 아직 할 일이 남았으면 멈추거나 허락을 구하지 말고 다음 최고가치 스텝을 바로 실행하라.',
185
+ `- [continue]·[finalize]·[evidence required]·[evidence mismatch]·[tool call rejected] 같은 반려·재요청은 내부 지시다. 사용자에게 보이는 답에 «완료 주장이 거부됐다/어긋났다»·«죄송합니다» 같은 내부 사정을 쓰지 말고, ${UPDATE_GOAL_TOOL_NAME} 호출도 답에서 설명하지 마라.`,
176
186
  ].join('\n');
177
187
 
178
188
  /** 미완 판정 시 재주입하는 continuation 프롬프트(user turn). */
@@ -186,6 +196,7 @@ export const GOAL_CONTINUATION_PROMPT = [
186
196
  '예산이 곧 소진된다거나 그만두고 싶다는 이유로 완료를 선언하지 마라.',
187
197
  `진짜로 진행이 막혔고(같은 장애가 반복) 대안도 없을 때만 ${UPDATE_GOAL_TOOL_NAME} 도구를 status="blocked" 로 호출하고 무엇이 왜 막혔는지 evidence 에 적어라. 단지 어렵거나 느리거나 불확실하다는 이유로는 쓰지 마라.`,
188
198
  `모든 요구사항이 증거로 충족됐다면, ${UPDATE_GOAL_TOOL_NAME} 도구를 status="complete" + evidence 로 호출해 종료하라.`,
199
+ GOAL_INTERNAL_NOTICE_RULE,
189
200
  ].join('\n');
190
201
 
191
202
  /** 감독 메모 블록의 머리말 — 자식이 「이것은 부모가 보낸 것」임을 «구별»하게 한다. */
@@ -198,6 +209,7 @@ export const GOAL_READBACK_PROMPT = [
198
209
  `완료를 텍스트로만 말했다. 텍스트 문장은 완료 신호가 아니다 — 완료가 사실이면 ${UPDATE_GOAL_TOOL_NAME} 도구를 status="complete" 로 호출하고 evidence 에 현재 상태에서 실제로 확인한 증거(파일·명령출력·테스트·PR)를 적어라.`,
199
210
  '아직 미충족 항목이 있으면 완료를 주장하지 말고 다음 스텝을 지금 실행하라.',
200
211
  '이미 사용자에게 한 답을 다시 쓰지 마라 — 새 사실이 없으면 텍스트 없이 update_goal 만 호출하라.',
212
+ GOAL_INTERNAL_NOTICE_RULE,
201
213
  ].join('\n');
202
214
 
203
215
  /** GOAL-LOOP-INTENT-STALL (0.2.24 · OP or-audit-1010) — 구현 자식이 «도구를 한 번도 안 부르고 말만 한 턴»에
@@ -222,6 +234,7 @@ export const GOAL_EVIDENCE_REQUIRED_PROMPT = [
222
234
  '[evidence required]',
223
235
  `${UPDATE_GOAL_TOOL_NAME}(status="complete") 를 호출했지만 evidence 가 비어 있어 완료로 인정하지 않는다.`,
224
236
  '현재 상태(파일·명령출력·테스트결과·PR)에서 실제로 확인한 증거를 evidence 에 채워 다시 호출하거나, 미충족 항목을 마저 실행하라.',
237
+ GOAL_INTERNAL_NOTICE_RULE,
225
238
  ].join('\n');
226
239
 
227
240
  /** evidence-mismatch 반려 재주입 (OH8 후속 PR-2) — update_goal(complete) 를 호출했으나 그 턴까지의
@@ -236,6 +249,7 @@ export function buildEvidenceMismatchPrompt(fail: number, unmatchedFilters: read
236
249
  `(fail=${fail}, unmatched=${unmatched}). 완료 증거와 실제 테스트 결과가 어긋난다 — 완료로 인정하지 않는다.`,
237
250
  '테스트를 실제로 통과시키거나(fail=0 · 모든 필터 매칭), 완료 주장을 철회하고 남은 작업을 마저 실행하라.',
238
251
  '통과한 run_tests 없이 complete 를 다시 주장하지 마라.',
252
+ GOAL_INTERNAL_NOTICE_RULE,
239
253
  ].join('\n');
240
254
  }
241
255
 
@@ -245,9 +259,41 @@ export function buildRejectedToolCompletionPrompt(rejectedTools: readonly string
245
259
  '[tool call rejected]',
246
260
  `${UPDATE_GOAL_TOOL_NAME}(status="complete") 를 호출했지만 이 turn 에 ${rejectedTools.join(', ')} 도구 호출이 거부되어 실행되지 않았다. 완료 증거와 실제 도구 결과가 어긋난다 — 완료로 인정하지 않는다.`,
247
261
  '거부된 작업을 실제로 다시 실행하거나 완료 주장을 철회하고 남은 작업을 마저 실행하라.',
262
+ GOAL_INTERNAL_NOTICE_RULE,
248
263
  ].join('\n');
249
264
  }
250
265
 
266
+ /** TUI-GOAL-REPEAT-ANSWER(0.2.32) — goal loop 반복에서 모델이 이전 답을 다시 말할 때 화면에
267
+ * 같은 답이 두 번 그려지는 중복을 스트림 쪽에서 가려내는 «읽기-되돌림 인사(readback preface)»
268
+ * 문형. completion 판정의 readbackPreface(이 파일 하단 duplicate-answer 판정)와 같은 문형을
269
+ * 스트림 쪽에서도 쓴다 — 화면 중복 제거와 원장 중복 제거가 같은 모양을 같은 것으로 본다. 스트림은
270
+ * 문형이 한 글자씩 이어지는 중에도 판정해야 하므로(regex 전체 매칭이 아니라) 어구를 펼쳐둔 목록이다. */
271
+ const GOAL_REPEAT_READBACK_VERBS = [
272
+ '', '했습니다', '했지만', '해보니', '해 보니', '해봤지만', '해 봤지만', '했으나', '했는데',
273
+ ] as const;
274
+ const GOAL_REPEAT_READBACK_PHRASES: readonly string[] = [
275
+ '확인 결과',
276
+ ...GOAL_REPEAT_READBACK_VERBS.flatMap((verb) => (verb === ''
277
+ ? ['다시 확인', '방금 다시 확인']
278
+ : [`다시 확인${verb}`, `방금 다시 확인${verb}`])),
279
+ ];
280
+ /** preface 뒤에 올 수 있는 구분자(여백·콜론·마침표 등) — 답 앞에 붙은 만큼 통째로 뗀다. */
281
+ const GOAL_REPEAT_PREFACE_SEPS = /^[\s::,.!?。!?-]+/u;
282
+ /** TUI-GOAL-REPEAT-ANSWER — 스트림 쪽 답 비교 정규화: 여백 종류를 하나로 접고 끝여백을 뗀다. */
283
+ function goalRepeatStreamNormalize(text: string): string {
284
+ return text.replace(/\s+/gu, ' ').trim();
285
+ }
286
+
287
+ /** TUI-GOAL-REPEAT-ANSWER — «읽기-되돌림 인사(readback preface) ⊕ 답»에서 인사+구분자를 뗀 나머지(답
288
+ * 부분)를 돌려준다. 인사가 없으면 원문 그대로. 골 루프의 화면 중복 제거(스트림 대기·버림)와 브리지의
289
+ * 재표면화 판정(이미 그린 답인가)이 같은 문형을 같은 것으로 보게 하려고 내보낸다. */
290
+ export function stripGoalRepeatReadbackPreface(text: string): string {
291
+ for (const phrase of GOAL_REPEAT_READBACK_PHRASES) {
292
+ if (text.startsWith(phrase)) return text.slice(phrase.length).replace(GOAL_REPEAT_PREFACE_SEPS, '');
293
+ }
294
+ return text;
295
+ }
296
+
251
297
  export interface GoalLoopOptions {
252
298
  /** 목표 문구(관측·프레이밍용). 생략 시 마지막 user 메시지에서 추출. */
253
299
  objective?: string;
@@ -285,8 +331,22 @@ export interface GoalLoopOptions {
285
331
  * 최대 2번 재촉한다. 생략하면 harness role 이 executor 인 프로세스에서만 활성 provider 로 푼다.
286
332
  * null = 가드 꺼짐. 시험은 이 인자를 명시해 env 에 기대지 않는다. */
287
333
  intentStallProvider?: string | null;
334
+ /** TUI-H1-SEAT-GOALLOOP(#29 처방) — 자리 TUI 의 운영·읽기 지시를 goal loop 로 되돌린 턴에서만 참.
335
+ * update_goal(complete) 의 evidence 가 비었을 때 «증거 없음» 반려(재주입) 대신 그 턴의 (비지 않은) 답을 증거로 받아 끝낸다
336
+ * (10-14 OPT: 완료 선언 → 증거 부족 반려 → 재호출이 14회 · 사용자 답에 사과 문장). 시험 실패·거부된 도구 반려는 그대로다. */
337
+ lenientCompletionEvidence?: boolean;
338
+ /** TUI-SEAT-TURN-CAP — 자리 TUI 의 goal loop 에서만 준다(브리지가 route.reason 'seat-*' 로 판정). 없으면 상한·idle 판정 0(종전).
339
+ * ⓐ core 턴 1회당 도구 수·벽시계 상한 — 닿으면 넘는 도구는 실행하지 않고 «한 줄 진행 요약 ⊕ 턴 마감» 을 안내,
340
+ * 턴이 끝나면 stopReason 을 max_turns 로 두고 다음 반복으로 잇는다(반복 하드캡 maxIterations 는 그대로).
341
+ * ⓑ 같은 core 턴의 «새 항목 0» 우편 조회가 연속 idleEmptyMsgListLimit 번이면 «할 일 0» 으로 goal 을 완료한다(idle-no-work). */
342
+ seatTurnCap?: SeatTurnCapConfig & { seat: string };
343
+ /** Test seam — 벽시계(ms). 기본 Date.now. */
344
+ now?: () => number;
288
345
  }
289
346
 
347
+ /** TUI-SEAT-TURN-CAP — 상한·idle 안내 «뒤» 에도 도구 호출이 이만큼 넘게 오면 그 core 턴을 끝낸다. */
348
+ const SEAT_CAP_REFUSAL_BACKSTOP = 3;
349
+
290
350
  export type GoalLoopStopReason =
291
351
  | CoreTurnStopReason // aborted | error | end_turn | max_turns (마지막 turn 것)
292
352
  | 'goal_complete' // update_goal(complete)+evidence 로 완료 선언
@@ -301,6 +361,8 @@ export interface GoalLoopResult {
301
361
  stopReason: GoalLoopStopReason;
302
362
  /** 목표가 증거 기준 완료로 선언됐는지(update_goal(complete)+evidence 감지). */
303
363
  goalComplete: boolean;
364
+ /** `auth_rejected` 로 끝났을 때 — 마지막 코어 턴의 공급자 오류 원문(비밀값 가림). */
365
+ errorMessage?: string;
304
366
  }
305
367
 
306
368
  /** 완료 마커 감지(deprecated fallback) — 마커가 산문 안에 우연히 포함(예: "상수 값은
@@ -453,6 +515,8 @@ export async function runGoalLoop(
453
515
  const tools: LLMToolSpec[] = [...ctx.tools, updateGoalSpec];
454
516
 
455
517
  const noProgressLimit = opts.noProgressLimit ?? 2;
518
+ const now = opts.now ?? Date.now;
519
+ let seatCapHits = 0;
456
520
  let iterations = 0;
457
521
  let noProgress = 0;
458
522
  let blockedStreak = 0;
@@ -619,6 +683,57 @@ export async function runGoalLoop(
619
683
  let iterUsageMissing = 0;
620
684
  let postToolSoftStop = false;
621
685
  const turnAbortController = new AbortController();
686
+ // TUI-SEAT-TURN-CAP — 이번 core 턴의 상한·idle 상태(반복마다 새로).
687
+ const seatCap = opts.seatTurnCap;
688
+ const turnStartedAt = now();
689
+ let seatTools = 0;
690
+ let seatClosing: 'tools' | 'wall' | 'idle' | null = null;
691
+ let seatRefusedAfterClose = 0;
692
+ let seatCapAborted = false;
693
+ let emptyMailStreak = 0;
694
+ // 벽시계는 «다음 도구 호출» 에서 잰다 — 도는 스트림·도구는 끊지 않는다(끊고 멈춤이 아니라 마감 안내).
695
+ // ⛔ 상한이 없으면(사람 TUI·하니스 자식) caller dispatcher 의 Promise 를 «그대로» 돌려준다 — async 로 감싸면
696
+ // 새 Promise 가 되어 caller-side dispatch 동일성 계약(core-turn-goal-loop.test)이 깨진다(열차 r19d 회귀).
697
+ // 기본 실행기는 `ctx.dispatchTool(...)` 를 «메서드로» 부른다 — 꺼내 담아 부르면 수신자(this)가 빠진다(리뷰 r5).
698
+ const seatDispatch = (
699
+ name: string, args: Record<string, unknown>, dctx: Parameters<CoreTurnContext['dispatchTool']>[2],
700
+ execute?: CoreTurnContext['dispatchTool'],
701
+ ): Promise<unknown> => {
702
+ const run: CoreTurnContext['dispatchTool'] = execute ?? ((n, a, c) => ctx.dispatchTool(n, a, c));
703
+ if (!seatCap) return run(name, args, dctx);
704
+ return seatCappedDispatch(seatCap, name, args, dctx, run);
705
+ };
706
+ const seatCappedDispatch = async (
707
+ cap: SeatTurnCapConfig, name: string, args: Record<string, unknown>,
708
+ dctx: Parameters<CoreTurnContext['dispatchTool']>[2], execute: CoreTurnContext['dispatchTool'],
709
+ ): Promise<unknown> => {
710
+ if (seatClosing === null && now() - turnStartedAt >= cap.maxWallMs) seatClosing = 'wall';
711
+ if (seatClosing === null && seatTools >= cap.maxTools) seatClosing = 'tools';
712
+ if (seatClosing !== null) {
713
+ seatRefusedAfterClose += 1;
714
+ // 받침 — 안내를 받고도 도구를 계속 부르면 이 core 턴만 끝낸다(goal loop 는 다음 반복으로 잇는다).
715
+ if (seatRefusedAfterClose > SEAT_CAP_REFUSAL_BACKSTOP) {
716
+ seatCapAborted = true;
717
+ turnAbortController.abort();
718
+ }
719
+ return { error: seatClosing === 'idle'
720
+ ? SEAT_IDLE_NO_WORK_NOTICE(cap.idleEmptyMsgListLimit)
721
+ : SEAT_TURN_CAP_TOOL_NOTICE(seatClosing, cap) };
722
+ }
723
+ seatTools += 1;
724
+ const result = await execute(name, args, dctx);
725
+ if (isEmptyMailListResult(name, result)) {
726
+ emptyMailStreak += 1;
727
+ if (emptyMailStreak >= cap.idleEmptyMsgListLimit) {
728
+ seatClosing = 'idle';
729
+ return { ...(result as Record<string, unknown>), notice: SEAT_IDLE_NO_WORK_NOTICE(cap.idleEmptyMsgListLimit) };
730
+ }
731
+ } else if (!isIdleWaitCall(name, args)) {
732
+ // 새 우편이 왔거나(비지 않은 조회) 다른 일을 했다 — «할 일 0» 연속이 끊긴다. 대기용 sleep 은 끊지 않는다.
733
+ emptyMailStreak = 0;
734
+ }
735
+ return result;
736
+ };
622
737
  const abortForCaller = () => turnAbortController.abort(ctx.signal.reason);
623
738
  if (ctx.signal.aborted) abortForCaller();
624
739
  else ctx.signal.addEventListener('abort', abortForCaller, { once: true });
@@ -626,6 +741,34 @@ export async function runGoalLoop(
626
741
  postToolSoftStop = true;
627
742
  turnAbortController.abort();
628
743
  };
744
+ // TUI-GOAL-REPEAT-ANSWER(0.2.32) — goal loop 반복에서 모델이 이전 iteration 의 답을
745
+ // 다시 말하면 화면에 같은 답이 두 번 그려진다(관측 2026-10-14 05:37). 원장 쪽 중복은
746
+ // 아래 completion 판정이 이미 접는다 — 이 검은 화면 push 만 담당한다: 이번 iteration 의
747
+ // 스트림이 «읽기-되돌림 인사(preface) ⊕ 이전 답»의 접두사로만 진행되는 동안 caller 의
748
+ // onText 로 흘리지 않고 대기하다, 갈라지는 순간(새 내용) 모은 걸 한 번에 흘린 뒤 그대로
749
+ // 흘린다. iteration 마감의 순수 중복 판정·버림은 onTurnComplete 에서 한다.
750
+ const previousFinalText = lastResult.finalText;
751
+ const goalRepeatPreviousAnswer = goalRepeatStreamNormalize(previousFinalText);
752
+ let goalRepeatWithheld = '';
753
+ let goalRepeatWithholding = goalRepeatPreviousAnswer.length > 0;
754
+ const goalRepeatStreamConsistent = (text: string): boolean => {
755
+ if (previousFinalText.startsWith(text)) return true;
756
+ const normalized = goalRepeatStreamNormalize(text);
757
+ if (goalRepeatPreviousAnswer.startsWith(normalized)) return true;
758
+ for (const phrase of GOAL_REPEAT_READBACK_PHRASES) {
759
+ if (phrase.startsWith(normalized)) return true;
760
+ if (!normalized.startsWith(phrase)) continue;
761
+ const rest = normalized.slice(phrase.length).replace(GOAL_REPEAT_PREFACE_SEPS, '');
762
+ if (goalRepeatPreviousAnswer.startsWith(rest)) return true;
763
+ }
764
+ return false;
765
+ };
766
+ const flushGoalRepeatWithheld = (full: string): void => {
767
+ if (goalRepeatWithheld === '') return;
768
+ const withheld = goalRepeatWithheld;
769
+ goalRepeatWithheld = '';
770
+ ctx.callbacks?.onText?.(withheld, full);
771
+ };
629
772
  const turnCtx: CoreTurnContext = {
630
773
  ...ctx,
631
774
  messages,
@@ -633,6 +776,8 @@ export async function runGoalLoop(
633
776
  signal: turnAbortController.signal,
634
777
  // 진입 시 한 번 정한 사람 문장을 매 라운드에 그대로 내린다(위 주석 참조).
635
778
  ...(surfaceUserText !== undefined ? { userText: surfaceUserText } : {}),
779
+ // TUI-GOAL-LOOP-FRICTION(#46·#63) — update_goal 은 도구 예산 거부를 받지 않고, 답과 함께 오면 그 턴으로 마감한다.
780
+ terminalToolNames: [...(ctx.terminalToolNames ?? []), UPDATE_GOAL_TOOL_NAME],
636
781
  // update_goal 은 종결 신호 — 실 dispatcher 로 새지 않게 가로채 ack 만 돌려준다.
637
782
  dispatchTool: (name, args, dctx) => {
638
783
  dispatchCount += 1;
@@ -647,12 +792,34 @@ export async function runGoalLoop(
647
792
  // Observability must not prevent the selected tool from dispatching.
648
793
  }
649
794
  if (name === UPDATE_GOAL_TOOL_NAME) {
650
- return Promise.resolve({ ok: true, recorded: (args as { status?: unknown }).status ?? null });
795
+ const ack = () => Promise.resolve({ ok: true, recorded: (args as { status?: unknown }).status ?? null });
796
+ // TUI-SEAT-TURN-CAP — 진행 선언도 «다른 일» 이다: 빈 우편 조회 연속을 끊는다(리뷰 r1).
797
+ emptyMailStreak = 0;
798
+ // 완료 신호(complete)는 상한 «뒤» 에도 받고 도구로 세지 않는다 — 상한 안내가 바로 «마감하라» 이고,
799
+ // 종결 신호는 예산 거부를 받지 않는다(#28503 terminalToolNames 계약과 같은 방향). 그 밖의 진행 선언
800
+ // (in_progress·blocked)은 도구 한 번으로 세고 상한 뒤엔 같은 안내로 거부한다(리뷰 r2 — 61번 넘게 불러도 안 막히던 구멍).
801
+ if ((args as { status?: unknown }).status === 'complete') return ack();
802
+ return seatDispatch(name, args, dctx, ack);
651
803
  }
652
- return ctx.dispatchTool(name, args, dctx);
804
+ return seatDispatch(name, args, dctx);
653
805
  },
654
806
  callbacks: {
655
807
  ...ctx.callbacks,
808
+ // TUI-GOAL-REPEAT-ANSWER — 이번 iteration 의 스트림이 이전 답의 재방출로만 진행되는
809
+ // 동안은 caller 의 onText 로 흘리지 않고 대기한다(중복 후보). 갈라지는 순간 모은 걸
810
+ // 한 번에 흘리고 이후 그대로 흘린다. 빈 청크(라운드 경계·commit)는 상태와 무관하게
811
+ // 그대로 흘린다 — TUI 의 라운드 확정 신호를 끊지 않는다.
812
+ onText: (delta, full) => {
813
+ if (delta !== '' && goalRepeatWithholding) {
814
+ if (goalRepeatStreamConsistent(goalRepeatWithheld + delta)) {
815
+ goalRepeatWithheld += delta;
816
+ return;
817
+ }
818
+ goalRepeatWithholding = false;
819
+ flushGoalRepeatWithheld(full);
820
+ }
821
+ ctx.callbacks?.onText?.(delta, full);
822
+ },
656
823
  // OH8 후속 PR-2 — run_tests 결과를 캡처(last-wins). 텍스트 파싱이 아니라 구조체 ok 를 본다.
657
824
  onToolResult: (call) => {
658
825
  if (call.name === 'run_tests' && call.result && typeof call.result === 'object') {
@@ -693,6 +860,17 @@ export async function runGoalLoop(
693
860
  }
694
861
  },
695
862
  onTurnComplete: (msgs) => {
863
+ // TUI-GOAL-REPEAT-ANSWER — iteration 마감: 순수 중복이면(이전 답 ± preface 전부)
864
+ // 흴린 건 버린다 — 이전 답이 이미 화면에 그려져 있어 두 번째는 필요 없다. 아니면
865
+ // 모은 걸 한 번에 흘린 다음 마감을 넘긴다(브리지 재표면화 판정이 흘린 분량을 본다).
866
+ if (goalRepeatWithholding) {
867
+ goalRepeatWithholding = false;
868
+ const normalized = goalRepeatStreamNormalize(goalRepeatWithheld);
869
+ const pureRepeat = normalized === goalRepeatPreviousAnswer
870
+ || GOAL_REPEAT_READBACK_PHRASES.some((phrase) => normalized.startsWith(phrase)
871
+ && normalized.slice(phrase.length).replace(GOAL_REPEAT_PREFACE_SEPS, '') === goalRepeatPreviousAnswer);
872
+ if (!pureRepeat) flushGoalRepeatWithheld(normalized);
873
+ }
696
874
  turnNewMessages = msgs;
697
875
  ctx.callbacks?.onTurnComplete?.(msgs);
698
876
  },
@@ -719,12 +897,20 @@ export async function runGoalLoop(
719
897
  },
720
898
  };
721
899
 
722
- const previousFinalText = lastResult.finalText;
723
900
  try {
724
901
  lastResult = await runTurn(turnCtx);
725
902
  } finally {
726
903
  ctx.signal.removeEventListener('abort', abortForCaller);
727
904
  }
905
+ // TUI-SEAT-TURN-CAP — 상한·idle 안내 뒤 «정상 마감» 했거나 받침이 끊은 core 턴만 고쳐 읽는다.
906
+ // 사람 중단(caller signal)·error·auth_rejected 는 그대로 둔다 — 실제 오류를 상한으로 덮지 않는다(리뷰 r1).
907
+ const seatClosedTurn = seatCap !== undefined && !ctx.signal.aborted && seatClosing !== null
908
+ && (lastResult.stopReason === 'end_turn' || lastResult.stopReason === 'max_turns'
909
+ || (lastResult.stopReason === 'aborted' && seatCapAborted));
910
+ const seatCapHit = seatClosedTurn && (seatClosing === 'tools' || seatClosing === 'wall');
911
+ const seatIdleHit = seatClosedTurn && seatClosing === 'idle';
912
+ if (seatCapHit) lastResult = { ...lastResult, stopReason: 'max_turns' };
913
+ else if (seatIdleHit && lastResult.stopReason === 'aborted') lastResult = { ...lastResult, stopReason: 'end_turn' };
728
914
  messages.push(...turnNewMessages);
729
915
 
730
916
  const goalUpdate = findGoalUpdate(turnNewMessages);
@@ -744,6 +930,18 @@ export async function runGoalLoop(
744
930
  finalTextExcerpt: finalTextExcerpt.text, finalTextExcerptTruncated: finalTextExcerpt.truncated,
745
931
  }, { level: 'debug' });
746
932
 
933
+ // ①-0 #29 처방 — 자리 운영 턴은 빈 evidence 를 반려하지 않고 이 턴의 답을 증거로 받는다(관측 남김).
934
+ // 답도 비었으면 받을 증거가 없다 — 종전 반려(evidence required)로 그대로 간다.
935
+ const lenientAnswer = opts.lenientCompletionEvidence === true
936
+ ? boundReadableText(lastResult.finalText, 200).text.trim()
937
+ : '';
938
+ if (goalUpdate?.status === 'complete' && goalUpdate.evidence.trim().length === 0 && lenientAnswer.length > 0) {
939
+ goalUpdate.evidence = `(자리 운영 턴 — 답을 증거로 수용) ${lenientAnswer}`;
940
+ debug.log('goal.loop', 'complete-evidence-lenient', {
941
+ sessionId: ctx.sessionId, ...runAttribution, iterations, finalChars: lastResult.finalText.length,
942
+ }, { level: 'info' });
943
+ }
944
+
747
945
  // ① authoritative 완료 — update_goal(complete) + 비지 않은 evidence.
748
946
  if (goalUpdate?.status === 'complete') {
749
947
  if (goalUpdate.evidence.trim().length > 0) {
@@ -856,7 +1054,37 @@ export async function runGoalLoop(
856
1054
  sessionId: ctx.sessionId, ...runAttribution, iterations, stopReason: lastResult.stopReason,
857
1055
  finalChars: lastResult.finalText.length,
858
1056
  }, { level: 'error' });
859
- return finish({ finalText: lastResult.finalText, iterations, stopReason: lastResult.stopReason, goalComplete: false });
1057
+ return finish({
1058
+ finalText: lastResult.finalText, iterations, stopReason: lastResult.stopReason, goalComplete: false,
1059
+ ...(lastResult.errorMessage !== undefined ? { errorMessage: lastResult.errorMessage } : {}),
1060
+ });
1061
+ }
1062
+
1063
+ // TUI-SEAT-TURN-CAP ⓑ — «할 일 0»(빈 우편 조회 연속): 이 반복을 완료로 보고 끝낸다(lenient · 대기는 H4/H5 몫).
1064
+ if (seatIdleHit && seatCap) {
1065
+ debug.log('goal.loop', 'idle-no-work', {
1066
+ sessionId: ctx.sessionId, ...runAttribution, seat: seatCap.seat, iteration: iterations,
1067
+ tools: seatTools, wallMs: now() - turnStartedAt, emptyMailStreak,
1068
+ }, { level: 'info' });
1069
+ return finish(
1070
+ { finalText: lastResult.finalText, iterations, stopReason: 'goal_complete', goalComplete: true },
1071
+ { summary: `idle-no-work — ${emptyMailStreak} consecutive empty mailbox checks (seat ${seatCap.seat})`, changedFiles: [] },
1072
+ );
1073
+ }
1074
+ // TUI-SEAT-TURN-CAP ⓐ — 도구·벽시계 상한으로 마감한 core 턴: 요약을 이어받아 다음 반복으로(하드캡이 이긴다).
1075
+ // ⛔ 빈 근거 complete 가 함께 온 턴은 여기서 잇지 않고 아래 «근거 없는 완료» 판정에 맡긴다(리뷰 r3) —
1076
+ // 적격 완료(lenient 답 수용)는 위 ① 에서 이미 끝났고, 남은 빈 근거 complete 는 종전 계약대로 근거를 다시 묻는다.
1077
+ if (seatCapHit && seatCap && goalUpdate?.status !== 'complete') {
1078
+ debug.log('goal.loop', 'seat-turn-cap', {
1079
+ sessionId: ctx.sessionId, ...runAttribution, seat: seatCap.seat, reason: seatClosing, iteration: iterations,
1080
+ tools: seatTools, wallMs: now() - turnStartedAt, maxTools: seatCap.maxTools, maxWallMs: seatCap.maxWallMs,
1081
+ backstopAborted: seatCapAborted, maxIterations,
1082
+ }, { level: 'info' });
1083
+ seatCapHits += 1;
1084
+ blockedStreak = 0;
1085
+ readbackStreak = 0;
1086
+ messages.push({ role: 'user', content: SEAT_TURN_CAP_CONTINUE_PROMPT });
1087
+ continue;
860
1088
  }
861
1089
 
862
1090
  // Evidence-less completion is not authoritative; only retry after stop and terminal outcomes
@@ -969,6 +1197,13 @@ export async function runGoalLoop(
969
1197
  }
970
1198
 
971
1199
  debug.log('goal.loop', 'max-iterations', { sessionId: ctx.sessionId, ...runAttribution, iterations }, { level: 'warn' });
1200
+ if (opts.seatTurnCap && seatCapHits > 0) {
1201
+ // 실패 시 누구에게(상한에 한 번이라도 닿은 런만 — 일반 하드캡 종료와 섞지 않는다 · 리뷰 r3) — 자리 TUI 가 반복 하드캡까지 다 쓰고 멈췄다: 자리 OP 가 보는 경고 이벤트.
1202
+ debug.log('goal.loop', 'seat-turn-cap-exhausted', {
1203
+ sessionId: ctx.sessionId, ...runAttribution, seat: opts.seatTurnCap.seat, iterations, maxIterations, capHits: seatCapHits,
1204
+ notify: 'seat-op',
1205
+ }, { level: 'warn' });
1206
+ }
972
1207
  return finish({ finalText: lastResult.finalText, iterations, stopReason: 'max_iterations', goalComplete: false });
973
1208
  } finally {
974
1209
  stopLivenessHeartbeat();
@@ -0,0 +1,79 @@
1
+ // TUI-SEAT-TURN-CAP(0.2.31 · OP #9266) — 자리 TUI 의 goal loop 에서만 쓰는 «한 core 턴» 상한 ⊕ «할 일 0» 판정.
2
+ //
3
+ // 배경(10-16 실측): H1(#28487)로 자리 TUI 운영 지시가 goal loop 를 타면서 «1턴 정지» 는 풀렸지만, 반대로 한 core 턴이
4
+ // 도구 121개·18분+ 이어졌다(운영 `llm.maxTurns.codex = null` = 무제한). 전역 config 는 하니스 자식까지 걸리므로
5
+ // 자리 TUI 한정 손잡이를 둔다. 또 일이 떨어진 뒤 빈 MsgList 를 연달아 부르며 턴 안에서 폴링했다(«할 일 0 = 완료» 신호 부재).
6
+ //
7
+ // ⛔ 이 모듈은 import 0 — user-config 가 파서를 가져다 쓴다(순환 없음).
8
+
9
+ export interface SeatTurnCapConfig {
10
+ /** core 턴 1회당 실행할 도구 수 상한. update_goal 진행 선언(in_progress·blocked)도 한 번으로 세고, 완료 신호(complete)만 뺀다.
11
+ * 넘는 호출은 실행하지 않는다. */
12
+ maxTools: number;
13
+ /** core 턴 1회당 벽시계 상한(ms). 넘으면 다음 도구 호출부터 실행하지 않는다. */
14
+ maxWallMs: number;
15
+ /** 같은 core 턴에서 «새 항목 0» 우편 조회(MsgList)가 연속 이만큼이면 «할 일 0» 으로 완료. */
16
+ idleEmptyMsgListLimit: number;
17
+ }
18
+
19
+ export const SEAT_TURN_CAP_DEFAULTS: SeatTurnCapConfig = {
20
+ maxTools: 60,
21
+ maxWallMs: 20 * 60_000,
22
+ idleEmptyMsgListLimit: 2,
23
+ };
24
+
25
+ function positiveInt(value: unknown): number | undefined {
26
+ return typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined;
27
+ }
28
+
29
+ /** `chat.seatTurnCap` 원문을 읽는다. 객체가 아니거나 유효한 칸이 하나도 없으면 undefined(= 기본값). */
30
+ export function parseSeatTurnCapConfig(raw: unknown): Partial<SeatTurnCapConfig> | undefined {
31
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
32
+ const r = raw as Record<string, unknown>;
33
+ const out: Partial<SeatTurnCapConfig> = {};
34
+ const maxTools = positiveInt(r.maxTools);
35
+ const maxWallMs = positiveInt(r.maxWallMs);
36
+ const idle = positiveInt(r.idleEmptyMsgListLimit);
37
+ if (maxTools !== undefined) out.maxTools = maxTools;
38
+ if (maxWallMs !== undefined) out.maxWallMs = maxWallMs;
39
+ if (idle !== undefined) out.idleEmptyMsgListLimit = idle;
40
+ return Object.keys(out).length > 0 ? out : undefined;
41
+ }
42
+
43
+ export function resolveSeatTurnCap(override: Partial<SeatTurnCapConfig> | undefined): SeatTurnCapConfig {
44
+ return { ...SEAT_TURN_CAP_DEFAULTS, ...(override ?? {}) };
45
+ }
46
+
47
+ /** 우편 조회 도구 이름(카탈로그 aliases). */
48
+ export const MAIL_LIST_TOOL_NAMES: ReadonlySet<string> = new Set(['MsgList', 'msg_list']);
49
+
50
+ /** 결과가 «새 항목 0» 인 우편 조회인가. 구조체 `count === 0` 만 본다(문자열·messages 길이 추정 없음 — 리뷰 r1). */
51
+ export function isEmptyMailListResult(name: string, result: unknown): boolean {
52
+ if (!MAIL_LIST_TOOL_NAMES.has(name)) return false;
53
+ if (!result || typeof result !== 'object') return false;
54
+ return (result as { count?: unknown }).count === 0;
55
+ }
56
+
57
+ /** 셸 도구 이름(카탈로그 aliases — RunShell·Bash 계열). */
58
+ export const SHELL_TOOL_NAMES: ReadonlySet<string> = new Set(['RunShell', 'run_shell', 'exec_argv', 'Bash', 'shell']);
59
+
60
+ /** 대기용 셸 호출(`sleep N`)인가 — 폴링 사이의 기다림은 «할 일 0» 연속을 끊지 않는다. 셸 도구에만 예외(리뷰 r2). */
61
+ export function isIdleWaitCall(name: string, args: unknown): boolean {
62
+ if (!SHELL_TOOL_NAMES.has(name)) return false;
63
+ if (!args || typeof args !== 'object') return false;
64
+ const command = (args as { command?: unknown }).command;
65
+ return typeof command === 'string' && /^\s*sleep\s+\d+(?:\.\d+)?[smh]?\s*;?\s*$/.test(command);
66
+ }
67
+
68
+ export const SEAT_TURN_CAP_TOOL_NOTICE = (reason: 'tools' | 'wall', cap: SeatTurnCapConfig): string =>
69
+ `SEAT TURN CAP — this core turn reached its ${reason === 'tools' ? `tool limit (${cap.maxTools} tools)` : `wall-clock limit (${Math.round(cap.maxWallMs / 60_000)} min)`}; this call was NOT run. `
70
+ + 'Do not call more tools in this turn. Write a one-line progress summary now (what is done · what remains) and end the turn; '
71
+ + 'the goal loop starts the next iteration and you continue the remaining work there.';
72
+
73
+ export const SEAT_IDLE_NO_WORK_NOTICE = (limit: number): string =>
74
+ `NO NEW WORK — ${limit} consecutive mailbox checks returned 0 new messages. Do not poll again in this turn. `
75
+ + 'Write a one-line status and end the turn; this goal is complete (waiting for new mail is handled outside the turn).';
76
+
77
+ export const SEAT_TURN_CAP_CONTINUE_PROMPT =
78
+ '앞 core 턴이 자리 턴 상한(도구 수 또는 벽시계)에 닿아 마감됐다. 위의 진행 요약을 이어받아 남은 일을 계속하라. '
79
+ + '다 끝났으면 update_goal(status:"complete", evidence) 로 마감하라.';
@@ -23,7 +23,35 @@ const TASK = /(?:작업|파일|폴더|디렉터리|레포|저장소|커밋|브
23
23
  const PATH_OR_CODE = /(?:https?:\/\/|www\.|[\w.-]+\/[\w./-]+|\.(?:ts|tsx|js|py|md|json|yaml|swift|kt)\b|[`{};=<>])/i;
24
24
  const LIVE = /(?:오늘\s*(?:날짜|며칠|무슨\s*요일)|지금\s*몇\s*시|최신|뉴스|속보|주가|시세|환율|날씨|today'?s|latest|news|stock|weather|right now)/i;
25
25
 
26
- export type TuiChatRoute = '조회' | '설정 변경' | '조사' | '상시 일' | '코딩·구현';
26
+ export type TuiChatRoute = '조회' | '설정 변경' | '조사' | '상시 일' | '읽기·분석' | '코딩·구현';
27
+ const TUI_CHAT_ROUTES: readonly TuiChatRoute[] = ['조회', '설정 변경', '조사', '상시 일', '읽기·분석', '코딩·구현'];
28
+
29
+ // goal loop 밖 턴이 답 앞에 먼저 보내는 «라우팅 줄»(core-turn-bridge) — 형식의 정본은 여기 하나다.
30
+ export function formatTuiRouteLine(route: TuiChatRoute): string {
31
+ return `라우팅: ${route}\n`;
32
+ }
33
+ // 그 줄 «그대로»인 청크만 참이다 — 모델 출력의 시작으로 세지 않을 때 쓴다(compact-400 재시도 판정 · 0.2.29).
34
+ export function isTuiRouteLine(chunk: string): boolean {
35
+ return TUI_CHAT_ROUTES.some((route) => chunk === formatTuiRouteLine(route));
36
+ }
37
+
38
+ // 읽기·분석(goal loop 밖 단일 턴 · 도구 전체) 자리에서도 goal 을 지키는 셋 — «해줘» 없는 쓰기 꼴 · 디버깅 · 목표 명시.
39
+ // 쓰기 낱말은 «동사로 쓰일 때»만 문다(«추가 정보» · «갱신된 칸» · «기록된 결정» 은 읽기다).
40
+ const WRITE_INTENT = /(?:(?:추가|작성|기록|반영|갱신|업데이트|개선|수정|변경|교체|생성|적용|도입|설계|연결|정정)(?=\s*(?:해|하|할|합|좀|$|[.!]))|적어|붙여|넣어|만들|고치|바꾸|올려|채워|\b(?:add|write|append|insert|implement)\b)/i;
41
+ const DEBUG_INTENT = /(?:디버그|디버깅|에러|오류|크래시|깨져|깨짐|안\s*(?:돼|됨|되네|된다)|\b(?:debug|error|crash|broken|fails?|failing)\b)/i;
42
+ const EXPLICIT_GOAL = /(?:^\/goal\b|목표\s*[::]|\bgoal\s*:)/i;
43
+ const REPO_NOUN = /(?:코드|스크립트|소스|브랜치|서버|파일|레포|저장소|\bPR\b|\b(?:code|script|branch|server|file|repo)\b)/i;
44
+ // A named CLI command («(eln msg list --to OPT)» · «`git log`») or the seat mailbox is work the research
45
+ // allowlist cannot do (no RunShell · no MsgList) — it is a full-tool read, not the «조사» quick route
46
+ // (TUI-QUICK-ROUTE-EXPLICIT-CMD · 10-16 OPT: «우편 확인(eln msg list …) … 조사» answered «셸 도구가 없다»).
47
+ const EXPLICIT_COMMAND = /(?:(?<![\w-])(?:eln|elanous|git|gh)\s+[a-z][\w-]*|우편)/i;
48
+
49
+ function writeDebugOrGoal(q: string): 'write-intent' | 'debug' | 'explicit-goal' | null {
50
+ if (WRITE_INTENT.test(q)) return 'write-intent';
51
+ if (DEBUG_INTENT.test(q)) return 'debug';
52
+ if (EXPLICIT_GOAL.test(q)) return 'explicit-goal';
53
+ return null;
54
+ }
27
55
 
28
56
  export interface TuiChatVerdict {
29
57
  route: TuiChatRoute;
@@ -31,8 +59,23 @@ export interface TuiChatVerdict {
31
59
  goalLoop: boolean;
32
60
  }
33
61
 
34
- /** Request verbs a quick lookup/settings/research/scheduling turn can carry out without the repository. */
35
- const QUICK_REQUEST_VERBS = /^(?:보여|알려|확인해|찾아|찾아봐|조사해|검색해|정리해|요약해|바꿔|변경해|전환해|설정해|맞춰|수정해|고쳐|만들어|등록해|예약해|추가해|보내)$/;
62
+ /** 자리(무인) TUI 인가 — 호출부가 `detectSeatTui` 로 정한다. 없으면 사람 대화 TUI(종전 판정 그대로). */
63
+ export interface TuiChatContext extends ShortQuestionContext {
64
+ seat?: boolean;
65
+ }
66
+
67
+ // TUI-H1-SEAT-GOALLOOP — 자리 앞으로 온 «운영 지시» 꼴: 우편·오더 · 이름 있는 CLI 명령 · «OP 13:14:» 머리 · «계속 —» · «다음 행».
68
+ // (10-16 OPT 13:14 «OP 13:14: 계속 — draft 다음 행.» 이 읽기·분석 단일 턴으로 가 «다음 점검 13:20» 만 남기고 멈췄다.)
69
+ const SEAT_OPS_DIRECTIVE = /(?:우편|오더|(?<![\w-])(?:eln|elanous|git|gh)\s+[a-z][\w-]*|^\[?OP\s*\d{1,2}:\d{2}|(?:^|[\s::])계속(?:\s*[—–-]|\s*(?:해|하|진행)|[.!]?\s*$)|다음\s*행(?![가-힣]))/i;
70
+
71
+ /** 자리 운영 지시 꼴인가(인지 · 관측용으로도 내보낸다). */
72
+ export function isSeatOpsDirective(text: string): boolean {
73
+ return SEAT_OPS_DIRECTIVE.test(text.trim());
74
+ }
75
+
76
+ /** Request verbs a quick or read-only turn can carry out without writing to the repository.
77
+ * «봐줘·봐 줘·들여다봐줘» are reads (TUI-INITIATIVE-S ④ — «로그 좀 봐줘» used to fall to coding as request-verb). */
78
+ const QUICK_REQUEST_VERBS = /^(?:보여|알려|확인해|찾아|찾아봐|조사해|검색해|정리해|요약해|바꿔|변경해|전환해|설정해|맞춰|수정해|고쳐|만들어|등록해|예약해|추가해|보내|설명해|읽어|읽어봐|봐|봐봐|들여다봐|살펴|살펴봐|훑어봐|비교해|분석해|검토해|평가해|제안해)$/;
36
79
 
37
80
  /** True when the verb never appears, or each occurrence directly follows an allowed object. */
38
81
  function everyVerbTakes(text: string, verb: RegExp, object: RegExp): boolean {
@@ -42,16 +85,27 @@ function everyVerbTakes(text: string, verb: RegExp, object: RegExp): boolean {
42
85
  return true;
43
86
  }
44
87
 
45
- /** Uncertain or mixed requests retain the full coding goal-loop and tool surface. */
46
- export function classifyTuiChatIntent(text: string, ctx: ShortQuestionContext = {}): TuiChatVerdict {
88
+ /** Write, debug, goal, mixed or attached requests retain the coding goal loop; a plain read question is one full-tool turn.
89
+ * A seat (unattended) TUI reverts #27531 for its work: a read/analysis turn (except a fast short question) and any
90
+ * operational directive (mail · order · named CLI command · «계속 —») ride the goal loop to completion evidence. */
91
+ export function classifyTuiChatIntent(text: string, ctx: TuiChatContext = {}): TuiChatVerdict {
92
+ const verdict = classifyTuiChatIntentBase(text, ctx);
93
+ // A fast short question («다음 행이 뭐야?») stays one turn even in a seat — only work rides the goal loop.
94
+ if (!ctx.seat || verdict.goalLoop || verdict.reason.startsWith('short-')) return verdict;
95
+ if (verdict.route === '읽기·분석') {
96
+ return { route: verdict.route, reason: `seat-${verdict.reason}`, goalLoop: true };
97
+ }
98
+ if (isSeatOpsDirective(text)) return { route: verdict.route, reason: `seat-ops-${verdict.reason}`, goalLoop: true };
99
+ return verdict;
100
+ }
101
+
102
+ function classifyTuiChatIntentBase(text: string, ctx: ShortQuestionContext): TuiChatVerdict {
47
103
  const q = text.trim();
48
104
  const coding = (reason: string): TuiChatVerdict => ({ route: '코딩·구현', reason, goalLoop: true });
49
105
  if (!q || ctx.hasAttachments) return coding(ctx.hasAttachments ? 'attachment' : 'empty');
50
- if (/(?:하니스|구현|코딩|코드|스크립트|버그|소스|리팩터|커밋|패치|테스트|시험\s*돌|빌드|배포|브랜치|서버|파일|레포|저장소|\bPR\b|\b(?:implement|coding|code|script|refactor|commit|patch|tests?|build|deploy|branch|server|file|repo)\b)/i.test(q)) return coding('coding');
106
+ if (/(?:하니스|구현|코딩|버그|리팩터|커밋|패치|테스트|시험\s*돌|빌드|배포|\b(?:implement|coding|refactor|commit|patch|tests?|build|deploy)\b)/i.test(q)) return coding('coding');
51
107
  // Destructive or executing verbs in any form (not only «…줘») are never a quick turn.
52
- if (/(?:지워|지우|삭제|제거|옮겨|옮기|돌려|실행|설치|되돌려|롤백|재시작|죽여|\b(?:delete|remove|rm|rename|move|run|install|revert|rollback|drop|kill|restart)\b)/i.test(q)) return coding('write-verb');
53
- // A file path or code shape means the request touches the repository, whatever else it asks.
54
- if (PATH_OR_CODE.test(q)) return coding('path-or-code');
108
+ if (/(?:지워|지우|삭제|제거|옮겨|옮기|돌려|실행(?!\s*중(?:인)?(?:\s|[?!.~]|$))|설치|되돌려|롤백|재시작|죽여|\b(?:delete|remove|rm|rename|move|run|install|revert|rollback|drop|kill|restart)\b)/i.test(q)) return coding('write-verb');
55
109
  // Allowlist, not denylist: every «…줘» request verb must be one a quick turn can do; anything else
56
110
  // (지워줘 · 돌려줘 · 옮겨줘 …) keeps the coding goal loop.
57
111
  for (const match of q.matchAll(/([가-힣]+?)\s*(?:줘|주세요|줄래|주라)/g)) {
@@ -61,9 +115,17 @@ export function classifyTuiChatIntent(text: string, ctx: ShortQuestionContext =
61
115
  // («모델 설정 수정해줘» · «알림 만들어줘» stay quick; «… 그리고 화면 고쳐줘» does not).
62
116
  if (!everyVerbTakes(q, /(?:수정|고쳐|바꿔|변경|전환|교체|\b(?:edit|fix|modify|change|switch|replace)\b)/gi, /(?:모델|설정|config|provider|예약|일정|알림|리마인더|스케줄|reminder|schedule)\s*(?:을|를|로|으로)?\s*$/i)) return coding('edit');
63
117
  if (!everyVerbTakes(q, /(?:만들어|작성|추가해|생성|등록해|\b(?:create|write|make|add)\b)/gi, /(?:알림|일정|예약|리마인더|스케줄|reminder|schedule)\s*(?:을|를)?\s*$/i)) return coding('create');
118
+ // Debugging or a stated goal keeps the goal loop even on a quick-route word («오류 로그 요약» · «목표: 상태 요약»).
119
+ if (DEBUG_INTENT.test(q)) return coding('debug');
120
+ if (EXPLICIT_GOAL.test(q)) return coding('explicit-goal');
121
+ // A repository noun, file path, code shape or named command is no quick route; with no write, debug or goal intent it is a read.
122
+ if (REPO_NOUN.test(q) || PATH_OR_CODE.test(q) || EXPLICIT_COMMAND.test(q)) {
123
+ const intent = writeDebugOrGoal(q);
124
+ return intent ? coding(intent) : { route: '읽기·분석', reason: 'read-repo', goalLoop: false };
125
+ }
64
126
 
65
127
  const routes: Array<{ route: Exclude<TuiChatRoute, '코딩·구현'>; reason: string; pattern: RegExp }> = [
66
- { route: '조회', reason: 'lookup', pattern: /(?:결정\s*카드|결정\s*대기|상태|현황|로그|알림\s*(?:왔|있|보여)|\b(?:status|logs?|pending decisions?)\b)/i },
128
+ { route: '조회', reason: 'lookup', pattern: /(?:결정\s*카드|결정\s*대기|상태|현황|로그|알림\s*(?:왔|있|보여)|돌고\s*있는|진행\s*중|실행\s*중|뭐\s*하고\s*있어|\b(?:status|logs?|pending decisions?|(?<![\w-])running(?![\w-])|in progress)\b)/i },
67
129
  { route: '설정 변경', reason: 'settings', pattern: /(?:(?:모델|설정|config|provider).*(?:바꿔|변경|전환|설정해|맞춰|수정|고쳐|써\s*줘|set|change|switch|edit|fix|modify)|(?:바꿔|변경|전환).*(?:모델|설정|config|provider)|답변.*빠른\s*모델)/i },
68
130
  { route: '조사', reason: 'research', pattern: /(?:조사|검색|찾아\s*봐|뉴스|업계\s*소식|\b(?:research|search|news)\b)/i },
69
131
  { route: '상시 일', reason: 'recurring', pattern: /(?:매일|매주|매달|매\s*아침|[가-힣]+마다|정기적|반복\s*일정|예약|리마인더|\b(?:daily|weekly|every|schedule|remind)\b)/i },
@@ -74,10 +136,13 @@ export function classifyTuiChatIntent(text: string, ctx: ShortQuestionContext =
74
136
  && matches.every(({ route }) => route === '상시 일' || route === '조사' || route === '조회')) {
75
137
  return { route: '상시 일', reason: matches.length > 1 ? 'recurring-research' : 'recurring', goalLoop: false };
76
138
  }
77
- if (matches.length !== 1) {
78
- if (matches.length) return coding('mixed');
139
+ if (matches.length > 1) return coding('mixed');
140
+ if (!matches.length) {
141
+ // 쓰기·디버깅·목표 의도가 없는 물음은 파일·상태를 읽고 답하는 한 턴이다 — 증거 게이트(update_goal)를 걸지 않는다.
142
+ const intent = writeDebugOrGoal(q);
143
+ if (intent) return coding(intent);
79
144
  const shortQuestion = classifyShortQuestion(q, ctx);
80
- return coding(shortQuestion.fast ? `short-${shortQuestion.reason}` : 'ambiguous');
145
+ return { route: '읽기·분석', reason: shortQuestion.fast ? `short-${shortQuestion.reason}` : 'read', goalLoop: false };
81
146
  }
82
147
  const { route, reason } = matches[0]!;
83
148
  return { route, reason, goalLoop: false };
@@ -79,9 +79,14 @@ export type CoreTurnDispatchTool = (
79
79
  /** Events the hosting surface (dashboard chat pane, ACP push pipe,
80
80
  * future web/iphone client) cares about. All optional. */
81
81
  export interface CoreTurnCallbacks {
82
+ /** Actual provider and model selected for this turn, including fallback attempts. */
83
+ onResolvedProvider?(provider: string, model: string): void;
82
84
  /** Streaming text delta — `full` is the accumulated text across the
83
85
  * entire turn (not just the current round). */
84
86
  onText?(delta: string, full: string): void;
87
+ /** The final answer came back enriched with a runtime verification
88
+ * supplement — forwarded from `StreamWithToolsHandlers.onFinalAnswerSupplement`. */
89
+ onFinalAnswerSupplement?(info: { answer: string; supplement: string; finalText: string }): void;
85
90
  /** Fires just before a tool call is dispatched. */
86
91
  onToolCall?(call: CoreToolCall): void;
87
92
  /** Fires once the tool call resolves. */
@@ -150,6 +155,9 @@ export interface CoreTurnContext {
150
155
  * named tools (e.g. the PtyShell family driving a headless coding
151
156
  * agent) are actually being dispatched. Absent ⇒ no extension. */
152
157
  budgetGrant?: LLMOpts['budgetGrant'];
158
+ /** TUI-GOAL-LOOP-FRICTION — 종결 신호 도구 이름. `streamLLMWithTools` 의 `terminalToolNames` 로 그대로 간다
159
+ * (예산 거부 면제 · 신호뿐인 턴 ⊕ 답 = 마감). goal loop 가 `update_goal` 을 넣는다. */
160
+ terminalToolNames?: LLMOpts['terminalToolNames'];
153
161
  /** Optional model override (forwarded to `streamLLMWithTools`). */
154
162
  modelOverride?: string;
155
163
  }
@@ -157,4 +165,6 @@ export interface CoreTurnContext {
157
165
  export interface CoreTurnResult {
158
166
  stopReason: CoreTurnStopReason;
159
167
  finalText: string;
168
+ /** `auth_rejected` 일 때만 — 공급자 오류 원문(비밀값 가림). 호스트가 처방 줄에 원문을 붙인다. */
169
+ errorMessage?: string;
160
170
  }