elanous 0.2.38 → 0.2.41

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 (712) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/1178.1aa9cad0e7695427.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7573.2376e13c9c21f1f8.js → 1765.679b29625c8e88d4.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 1800.f7ff51dc4978a958.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2743.5d3f76948be32b34.js +41 -0
  31. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +32 -0
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +79 -0
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/{5300.677c97e0393742e6.js → 5892.2526d962339662d8.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/6874.d5cf7eb8edb2cabe.js +2 -0
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2415.738b777642a02233.js → 7191.fdc955f7d96064a4.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/{3389.012c70767a872f9b.js → 9869.81a1e24ca682d5a0.js} +1 -1
  125. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/b2271e54.c1de3347976e90b0.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → c0c1a699.0ba79f97005965d4.js} +7 -7
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  283. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  284. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  285. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  286. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  287. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +3 -0
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/video/explainer-line.yaml +4 -1
  298. package/graphs/work/research-report.yaml +11 -1
  299. package/package.json +1 -1
  300. package/scripts/dead-code/report.ts +169 -0
  301. package/scripts/disk-steward.ts +46 -0
  302. package/scripts/fleet/node-setup.sh +50 -0
  303. package/scripts/graph-units/verbs/research.ts +55 -0
  304. package/scripts/lib/morning-report-options.ts +3 -4
  305. package/scripts/lib/tui-regress-evidence.ts +56 -0
  306. package/scripts/llm-cost-ledger.ts +179 -8
  307. package/scripts/measure-nl-routing-corpus.ts +10 -2
  308. package/scripts/morning-report.ts +5 -1
  309. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  310. package/scripts/public-copy-lint.ts +163 -19
  311. package/scripts/public-export.ts +15 -7
  312. package/scripts/ratchets/train-side-invariants.sh +0 -1
  313. package/scripts/release-loop/export-check-node.ts +21 -3
  314. package/scripts/release-loop/gate-autoheal.ts +117 -0
  315. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  316. package/scripts/release-loop/gate-diff.ts +22 -3
  317. package/scripts/release-loop/gate-node.ts +583 -64
  318. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  319. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  320. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  321. package/scripts/release-loop/gate-triage-node.ts +70 -10
  322. package/scripts/release-loop/gate-wall.ts +5 -5
  323. package/scripts/release-loop/preflight.ts +6 -2
  324. package/scripts/release-loop/resume-release.ts +267 -20
  325. package/scripts/release-loop/resume.ts +48 -0
  326. package/scripts/release-loop/traffic-node.ts +6 -3
  327. package/scripts/release-loop/unattended-release.ts +4 -2
  328. package/scripts/release-loop/version-node.ts +7 -2
  329. package/scripts/release-story/draft.ts +1 -1
  330. package/scripts/research-bench/README.md +53 -0
  331. package/scripts/research-bench/questions.json +66 -0
  332. package/scripts/research-bench/rubric.md +33 -0
  333. package/scripts/research-bench/run.ts +523 -0
  334. package/scripts/shadow-authoring-probe.ts +20 -0
  335. package/scripts/tui-regress.ts +85 -10
  336. package/scripts/ux-sim.ts +19 -2
  337. package/src/acp/core-turn-bridge.ts +94 -4
  338. package/src/agent/autonomous-tools.ts +10 -3
  339. package/src/agent/monad-agent-turn.ts +4 -1
  340. package/src/agent/registry.ts +26 -2
  341. package/src/agent/shared-app-tools.ts +1 -1
  342. package/src/agent/surface-ux/build.ts +12 -3
  343. package/src/agent/surface-ux/types.ts +1 -1
  344. package/src/agent/task-notification.ts +75 -6
  345. package/src/agent/types.ts +3 -0
  346. package/src/agent-mission/driver.ts +29 -3
  347. package/src/agent-mission/mission-cli.ts +2 -1
  348. package/src/agent-substrate/review-context-pack.ts +365 -0
  349. package/src/agent-substrate/self-review-cli.ts +291 -20
  350. package/src/ask-user-question/index.ts +6 -0
  351. package/src/ask-user-question/inline-resolver.ts +49 -0
  352. package/src/auto-research/question-ladder-contract.ts +22 -3
  353. package/src/auto-research/research-turn.ts +359 -17
  354. package/src/autopilot/agent-loop.ts +1 -1
  355. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  356. package/src/autopilot/pty-control-loop.ts +8 -1
  357. package/src/boot/daemon-tools/index.ts +4 -3
  358. package/src/boot/daemon-tools/self-implement.ts +312 -7
  359. package/src/boot/daemon-tools/types.ts +2 -0
  360. package/src/budget/llm-cost.ts +44 -5
  361. package/src/budget/shadow-arms.ts +52 -0
  362. package/src/budget/unified-usage.ts +17 -1
  363. package/src/capture/tui-self-report.ts +14 -0
  364. package/src/chat/index.ts +33 -7
  365. package/src/chat/pickers/state.ts +7 -1
  366. package/src/cli/agent-cli.ts +43 -8
  367. package/src/cli/intake-cli.ts +22 -1
  368. package/src/cli/lesson-cli.ts +19 -3
  369. package/src/cli/log-event-names.ts +6 -0
  370. package/src/cli/mcp-login.ts +8 -18
  371. package/src/cli/msg-cli.ts +57 -1
  372. package/src/cli/pod-cli.ts +17 -2
  373. package/src/cli/pr-land-heavy-remote.ts +15 -9
  374. package/src/cli/pty-takeover-cli.ts +67 -7
  375. package/src/cli/release-cli.ts +79 -7
  376. package/src/cli/repo-cli.ts +2 -1
  377. package/src/cli/sim-cli.ts +7 -1
  378. package/src/cli/tasks-cli.ts +41 -13
  379. package/src/codex/models.ts +30 -15
  380. package/src/control-plane/ledger.ts +21 -4
  381. package/src/core-turn/run-core-turn.ts +47 -3
  382. package/src/core-turn/run-goal-loop.ts +240 -10
  383. package/src/core-turn/types.ts +9 -0
  384. package/src/dashboard/acp-boot.ts +72 -3
  385. package/src/dashboard/chat/acp-chat.ts +2 -2
  386. package/src/dashboard/classic-sigquit.ts +16 -0
  387. package/src/dashboard/index.ts +327 -27
  388. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  389. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  390. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  391. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  392. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  393. package/src/dashboard/input/external-input-host.ts +2 -0
  394. package/src/dashboard/sidetab-runtime.ts +228 -0
  395. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  396. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  397. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  398. package/src/dashboard/term-slash-runtime.ts +16 -18
  399. package/src/dashboard/turn-preamble.ts +14 -1
  400. package/src/disk-steward/judge.ts +73 -0
  401. package/src/disk-steward/ledger.ts +122 -0
  402. package/src/disk-steward/steward.ts +373 -0
  403. package/src/domains/guardian-tick.ts +191 -2
  404. package/src/domains/knowledge.ts +1 -1
  405. package/src/esc-abort-gate.ts +33 -1
  406. package/src/execution-loop/launch-gate.ts +206 -1
  407. package/src/graph-runner/graph-cli.ts +27 -4
  408. package/src/graph-runner/in-process-registry.ts +37 -0
  409. package/src/graph-runner/runner.ts +63 -11
  410. package/src/graph-wizard/generate.ts +16 -7
  411. package/src/graph-wizard/mission-compose.ts +201 -0
  412. package/src/grok/agent-search.ts +8 -2
  413. package/src/grok/credential.ts +5 -0
  414. package/src/grounding/ref-index.ts +30 -0
  415. package/src/grounding/ref-vector.ts +61 -0
  416. package/src/grounding/sources-cli.ts +11 -3
  417. package/src/grounding/sources.ts +15 -1
  418. package/src/harness/harness-cli-command.ts +305 -23
  419. package/src/harness/harness-incidents.ts +312 -7
  420. package/src/harness/harness-pod-dispatch.ts +7 -1
  421. package/src/harness/harness-space.ts +15 -1
  422. package/src/harness/progress-worker-entry.ts +59 -0
  423. package/src/harness/progress-worker-runtime.ts +11 -0
  424. package/src/index.ts +35 -5
  425. package/src/input/external-input-queue.ts +10 -0
  426. package/src/instance/dev-project.ts +25 -0
  427. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  428. package/src/intake-plane/intake-to-tasks.ts +246 -3
  429. package/src/intelligence-map/model-alias.ts +6 -5
  430. package/src/intelligence-map/model-catalog.ts +59 -2
  431. package/src/lessons/friction-ledger.ts +154 -0
  432. package/src/live-supply/collector.ts +149 -0
  433. package/src/live-supply/probes.ts +52 -0
  434. package/src/live-supply/snapshot.ts +40 -0
  435. package/src/llm/model-defaults.ts +4 -4
  436. package/src/llm.ts +473 -87
  437. package/src/loops/orchestrator/tick.ts +56 -0
  438. package/src/mcp/mcp-oauth.ts +3 -1
  439. package/src/model-tier/llm-tier-map.ts +9 -9
  440. package/src/model-tier/turn-tier.ts +1 -1
  441. package/src/msg/msg-mirror-github.ts +80 -0
  442. package/src/msg/msg-mirror-policy.ts +61 -0
  443. package/src/msg/msg-mirror-runner.ts +219 -0
  444. package/src/msg/msg-mirror-state.ts +33 -0
  445. package/src/msg/msg-store.ts +11 -0
  446. package/src/nexus/api/harness-api.ts +2 -1
  447. package/src/output-truncation.ts +41 -12
  448. package/src/project/project-store.ts +48 -1
  449. package/src/pty/snapshot.py +132 -0
  450. package/src/pty-shell/pty-control-ipc.ts +29 -2
  451. package/src/pty-shell/pty-manifest.ts +59 -3
  452. package/src/pty-shell/registry.ts +2 -0
  453. package/src/pty-shell/tui-run-state.ts +80 -3
  454. package/src/release-loop/gate-host-reservation.ts +157 -4
  455. package/src/release-loop/gate-shard-ledger.ts +68 -0
  456. package/src/release-loop/merged-pr-checklist.ts +25 -2
  457. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  458. package/src/release-loop/rehearsal.ts +27 -0
  459. package/src/release-loop/release-schedule.ts +90 -1
  460. package/src/research/bloom-exemplars.ts +135 -0
  461. package/src/research/edge-decision.ts +124 -15
  462. package/src/research/gap-followup.ts +249 -0
  463. package/src/research/lenses/counter-evidence.ts +100 -0
  464. package/src/research/lenses/working-backwards.ts +89 -0
  465. package/src/research/plugin-discovery.ts +242 -0
  466. package/src/research-bridge/invoke.ts +4 -2
  467. package/src/research-bridge/types.ts +2 -0
  468. package/src/self-dev/ask-launch-flow.ts +73 -131
  469. package/src/self-dev/dev-cli.ts +19 -17
  470. package/src/self-dev/dev-pipeline.ts +8 -4
  471. package/src/self-dev/graph-front-nodes.ts +23 -0
  472. package/src/self-dev/graph-journey-route.ts +10 -2
  473. package/src/self-dev/launch-preflight-text.ts +2 -2
  474. package/src/self-dev/launch-preflight.ts +47 -11
  475. package/src/self-dev/orchestrate-cli.ts +1 -0
  476. package/src/self-dev/orchestrate.ts +15 -0
  477. package/src/self-dev/run-supervisor.ts +204 -3
  478. package/src/self-dev/run-types.ts +3 -0
  479. package/src/self-implement/device-first.ts +8 -2
  480. package/src/self-implement/doctor-visit.ts +76 -58
  481. package/src/self-implement/gate-artifacts.ts +16 -0
  482. package/src/self-implement/gate-baseline.ts +75 -4
  483. package/src/self-implement/gate-cli.ts +368 -30
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +165 -24
  486. package/src/self-implement/goal-author-clarification.ts +205 -32
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +86 -10
  489. package/src/self-implement/graph-stage-units.ts +172 -0
  490. package/src/self-implement/graph-templates.ts +162 -1
  491. package/src/self-implement/graph-variant.ts +37 -4
  492. package/src/self-implement/host-regate.ts +124 -49
  493. package/src/self-implement/impl-findings-feedback.ts +188 -0
  494. package/src/self-implement/knowhow-pack.ts +227 -10
  495. package/src/self-implement/off-diff-evidence.ts +124 -0
  496. package/src/self-implement/orchestrator.ts +320 -28
  497. package/src/self-implement/run-ledger.ts +110 -14
  498. package/src/self-implement/run-stop.ts +33 -2
  499. package/src/self-implement/running-runs.ts +35 -12
  500. package/src/self-implement/seams.ts +6 -3
  501. package/src/self-implement/self-implement-cli.ts +40 -6
  502. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  503. package/src/self-implement/stop-autoheal.ts +15 -6
  504. package/src/session/chat.ts +66 -15
  505. package/src/session/request-size-guard.ts +123 -0
  506. package/src/session-runtime/provider-circuit.ts +140 -0
  507. package/src/shell-runner/file-engine.ts +1 -0
  508. package/src/shell-runner/types.ts +4 -0
  509. package/src/sidetab-core/model.ts +312 -0
  510. package/src/skills/tools/schedule-wakeup.ts +23 -1
  511. package/src/skills/tools/shell.ts +51 -5
  512. package/src/steward/directive-audit.ts +354 -0
  513. package/src/surface/child-process.ts +31 -0
  514. package/src/surface/tui-stderr-owner.ts +48 -0
  515. package/src/task-agent/cover.ts +30 -12
  516. package/src/task-agent/judge.ts +56 -0
  517. package/src/task-agent/parent-host.ts +14 -1
  518. package/src/task-agent/postland-card.ts +35 -2
  519. package/src/task-agent/rejudge-on-head.ts +46 -2
  520. package/src/task-agent/repair-cycle.ts +1 -1
  521. package/src/task-agent/task-hand.ts +133 -25
  522. package/src/task-agent/tier-split.ts +105 -21
  523. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  524. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  525. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +70 -2
  526. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  527. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  528. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  529. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  530. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  531. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  532. package/src/task-orchestrator/surfaces/self-implement-pod.ts +298 -45
  533. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  534. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  535. package/src/tui/entry.ts +25 -5
  536. package/src/tui/inline-choice.ts +188 -0
  537. package/src/tui/sidetab/list.ts +36 -165
  538. package/src/tui/sidetab/nl-tool.ts +2 -136
  539. package/src/tui/sidetab/peek.ts +52 -0
  540. package/src/tui/slash/term.ts +12 -1
  541. package/src/tui-client/dashboard-session.ts +10 -1
  542. package/src/user-config.ts +45 -9
  543. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  544. package/src/ux-sim/fake-land-queue.ts +88 -0
  545. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  546. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  547. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  548. package/src/ux-sim/goal-interim-trace.ts +24 -0
  549. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  550. package/src/ux-sim/release-sim-rig.ts +262 -0
  551. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  552. package/src/ux-sim/subagent-tools-device.ts +2 -2
  553. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  554. package/src/version/packed-revision.json +1 -1
  555. package/src/video-pipeline/recipes/explainer.ts +54 -2
  556. package/src/web-search/grok.ts +32 -6
  557. package/src/web-search/index.ts +8 -7
  558. package/src/workflow-runtime/node-catalog.ts +53 -4
  559. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  560. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +0 -148
  567. package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  571. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  572. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  581. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  583. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  586. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  592. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  604. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  605. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  607. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  614. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  617. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  629. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7628.6b16863ac3972333.js +0 -34
  636. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7954.4f7a8832663ee979.js +0 -115
  639. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  647. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  648. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +0 -226
  649. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  650. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  654. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +0 -122
  705. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  711. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  712. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -29,6 +29,9 @@ interface PodWorkerLeaseAttrs {
29
29
  idleTtlMs: number;
30
30
  leaseId?: string;
31
31
  leaseOwner?: string;
32
+ /** The just-sanitized generation remains fenceable until the next acquisition. */
33
+ lastLeaseId?: string;
34
+ lastLeaseOwner?: string;
32
35
  runId?: string;
33
36
  attemptId?: string;
34
37
  reason?: string;
@@ -235,8 +238,11 @@ export class ResourceLedger {
235
238
  if (index < 0) throw new ResourceLedgerError(409, 'no-warm-worker');
236
239
  const row = rows[index]!;
237
240
  const attrs = workerAttrs(row);
238
- const next: ResourceRecord = { ...row, attrs: { ...attrs, state: 'leased', generation: attrs.generation + 1,
239
- leaseId: randomUUID(), leaseOwner: request.owner, runId: request.runId, attemptId: request.attemptId },
241
+ const nextAttrs: PodWorkerLeaseAttrs = { ...attrs, state: 'leased', generation: attrs.generation + 1,
242
+ leaseId: randomUUID(), leaseOwner: request.owner, runId: request.runId, attemptId: request.attemptId };
243
+ delete nextAttrs.lastLeaseId;
244
+ delete nextAttrs.lastLeaseOwner;
245
+ const next: ResourceRecord = { ...row, attrs: nextAttrs as unknown as Record<string, unknown>,
240
246
  observedAt: at, ttlMs: request.ttlMs };
241
247
  rows[index] = next;
242
248
  this.write(rows);
@@ -252,9 +258,13 @@ export class ResourceLedger {
252
258
  if (index < 0) throw new ResourceLedgerError(404, 'not-found');
253
259
  const row = rows[index]!;
254
260
  const attrs = workerAttrs(row);
255
- if (!request.leaseId || attrs.leaseId !== request.leaseId || attrs.generation !== request.generation) throw new ResourceLedgerError(409, 'stale-worker-lease');
261
+ const lateIdleQuarantine = request.action === 'quarantine' && attrs.state === 'idle'
262
+ && attrs.lastLeaseId === request.leaseId && attrs.generation === request.generation;
263
+ if (!request.leaseId || (attrs.leaseId !== request.leaseId && !lateIdleQuarantine)
264
+ || attrs.generation !== request.generation) throw new ResourceLedgerError(409, 'stale-worker-lease');
256
265
  const permitted = request.action === 'sanitize' ? row.owner === request.owner
257
266
  : request.action === 'quarantine' ? row.owner === request.owner || attrs.leaseOwner === request.owner
267
+ || (lateIdleQuarantine && attrs.lastLeaseOwner === request.owner)
258
268
  : attrs.leaseOwner === request.owner;
259
269
  if (!permitted) {
260
270
  throw new ResourceLedgerError(403, 'not-owner');
@@ -266,7 +276,14 @@ export class ResourceLedger {
266
276
  const state: PodWorkerState = request.action === 'renew' ? 'leased' : request.action === 'release' ? 'sanitizing'
267
277
  : request.action === 'sanitize' ? 'idle' : 'quarantined';
268
278
  const nextAttrs: PodWorkerLeaseAttrs = { ...attrs, state, ...(request.reason ? { reason: request.reason } : {}) };
269
- if (state === 'idle') { delete nextAttrs.leaseId; delete nextAttrs.leaseOwner; delete nextAttrs.runId; delete nextAttrs.attemptId; delete nextAttrs.reason; }
279
+ if (state === 'idle') {
280
+ nextAttrs.lastLeaseId = attrs.leaseId;
281
+ nextAttrs.lastLeaseOwner = attrs.leaseOwner;
282
+ delete nextAttrs.leaseId; delete nextAttrs.leaseOwner; delete nextAttrs.runId; delete nextAttrs.attemptId; delete nextAttrs.reason;
283
+ } else if (state === 'quarantined') {
284
+ delete nextAttrs.lastLeaseId;
285
+ delete nextAttrs.lastLeaseOwner;
286
+ }
270
287
  const ttlMs = state === 'idle' ? attrs.idleTtlMs : request.ttlMs ?? row.ttlMs;
271
288
  const next: ResourceRecord = { ...row, attrs: nextAttrs as unknown as Record<string, unknown>, observedAt: now, ttlMs };
272
289
  rows[index] = next;
@@ -25,6 +25,7 @@ import { drainPendingUserInput } from '../session/pending-input.js';
25
25
  import type { StreamWithToolsHandlers } from '../llm.js';
26
26
  import { debug, redactSecretText, withAmbientSessionScope } from '../debug/log.js';
27
27
  import { applyDeferredTools } from '../session-runtime/tier-flip.js';
28
+ import { isResearchAgentIntent } from '../tool-hints/signals.js';
28
29
  import { buildResearchDateSystemMessage, resolveSessionSurfaceProfile } from '../session-runtime/index.js';
29
30
  import type {
30
31
  CoreTurnContext,
@@ -32,6 +33,8 @@ import type {
32
33
  CoreTurnStopReason,
33
34
  } from './types.js';
34
35
 
36
+ const CORE_TURN_TOOL_RESULT_INLINE_LIMIT_BYTES = 50 * 1024;
37
+
35
38
  /** Classify an error thrown out of `streamLLMWithTools` into the
36
39
  * Core-turn stop-reason set. Abort wins over everything else;
37
40
  * credential rejection (`isAuthRejectionError`) is distinct from a
@@ -101,6 +104,7 @@ function selectSurfaceUserText(ctx: CoreTurnContext): string | undefined {
101
104
  */
102
105
  export interface RunCoreTurnOptions {
103
106
  now?: () => number;
107
+ runResearch?: (request: string) => Promise<{ ok: boolean; output: string; error?: string }>;
104
108
  }
105
109
 
106
110
  export async function runCoreTurn(
@@ -127,12 +131,14 @@ export async function runCoreTurn(
127
131
 
128
132
  let accumulatedText = '';
129
133
  let dispatchCount = 0;
134
+ let finalPhaseAnswer = false;
130
135
 
131
136
  const handlers: StreamWithToolsHandlers = {
132
137
  onText: (delta, full) => {
133
138
  accumulatedText = full;
134
139
  ctx.callbacks?.onText?.(delta, full);
135
140
  },
141
+ ...(ctx.callbacks?.onStatus ? { onStatus: (line: string) => ctx.callbacks?.onStatus?.(line) } : {}),
136
142
  ...(ctx.callbacks?.onFinalAnswerSupplement
137
143
  ? { onFinalAnswerSupplement: (info: { answer: string; supplement: string; finalText: string }) => ctx.callbacks?.onFinalAnswerSupplement?.(info) }
138
144
  : {}),
@@ -213,7 +219,11 @@ export async function runCoreTurn(
213
219
  handlers.onUsage = (usage) => ctx.callbacks!.onUsage!(usage);
214
220
  }
215
221
  if (ctx.callbacks?.onTurnComplete) {
216
- handlers.onTurnComplete = (msgs) => ctx.callbacks!.onTurnComplete!(msgs);
222
+ handlers.onTurnComplete = (msgs) => {
223
+ const lastAssistant = [...msgs].reverse().find((message) => message.role === 'assistant');
224
+ finalPhaseAnswer = lastAssistant?.phase === 'final_answer';
225
+ ctx.callbacks!.onTurnComplete!(msgs);
226
+ };
217
227
  }
218
228
  if (ctx.callbacks?.onReasoning) {
219
229
  handlers.onReasoning = (event) => ctx.callbacks!.onReasoning!(event);
@@ -240,17 +250,47 @@ export async function runCoreTurn(
240
250
  const recentUserText = extractRecentUserText(ctx.messages);
241
251
  const surfaceUserText = selectSurfaceUserText(ctx);
242
252
  const surface = ctx.surfaceProfile ?? resolveSessionSurfaceProfile({ userText: surfaceUserText });
253
+ // Use the shared #31663 research-intent verdict. Surface labels are a
254
+ // presentation/routing result and may remain `chat` for a research turn.
255
+ const researchTurn = isResearchAgentIntent(surfaceUserText);
243
256
  const { messages, tools, stats } = applyDeferredTools(
244
257
  ctx.messages,
245
258
  ctx.tools,
246
259
  { enabled: deferredEnabled, ...(recentUserText ? { userText: recentUserText } : {}) },
247
260
  );
248
- if (surface.id === 'research/agent' && !messages.some((message) =>
261
+ if (researchTurn && !messages.some((message) =>
249
262
  message.role === 'system' && typeof message.content === 'string'
250
263
  && message.content.startsWith('Current local date:'))
251
264
  ) {
252
265
  messages.unshift(buildResearchDateSystemMessage());
253
266
  }
267
+ if (researchTurn && surfaceUserText?.trim()) {
268
+ debug.log('research.turn', 'tui-research-started', { sessionId: ctx.sessionId });
269
+ try {
270
+ const result = await (options.runResearch ?? (async (request) => {
271
+ // Keep the Bloom/skill pipeline out of ordinary and packaged TUI startup graphs.
272
+ const { researchTurnForGrounding, runResearchQuestionLadder } = await import('../auto-research/research-turn.js');
273
+ return researchTurnForGrounding(await runResearchQuestionLadder(request));
274
+ }))(surfaceUserText);
275
+ if (result.output.trim()) {
276
+ messages.unshift({
277
+ role: 'system',
278
+ content: `<bloom-research>\n${result.output.trim()}\n</bloom-research>\nUse this axis evidence and counterevidence in the answer; preserve uncertainty and distinguish sourced facts from inference.`,
279
+ });
280
+ }
281
+ debug.log('research.turn', 'tui-research-completed', {
282
+ sessionId: ctx.sessionId,
283
+ ok: result.ok,
284
+ outputChars: result.output.length,
285
+ fallbackReason: result.error,
286
+ });
287
+ } catch (error) {
288
+ debug.log('research.turn', 'tui-research-fallback', {
289
+ sessionId: ctx.sessionId,
290
+ reason: error instanceof Error ? error.message : String(error),
291
+ }, { level: 'warn' });
292
+ }
293
+ }
254
294
  if (debug.enabled) {
255
295
  debug.log('llm.request', 'tools-tier', {
256
296
  sessionId: ctx.sessionId,
@@ -288,8 +328,10 @@ export async function runCoreTurn(
288
328
  handlers,
289
329
  {
290
330
  tools,
291
- researchTurn: surface.id === 'research/agent',
331
+ researchTurn,
292
332
  signal: ctx.signal,
333
+ ...(ctx.requestSizeGuard ? { requestSizeGuard: ctx.requestSizeGuard } : {}),
334
+ toolResultInlineLimitBytes: CORE_TURN_TOOL_RESULT_INLINE_LIMIT_BYTES,
293
335
  ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}),
294
336
  ...(ctx.maxToolTurns !== undefined ? { maxTurns: ctx.maxToolTurns } : {}),
295
337
  ...(ctx.initialProvider !== undefined
@@ -299,6 +341,7 @@ export async function runCoreTurn(
299
341
  ...(ctx.budgetGrant !== undefined ? { budgetGrant: ctx.budgetGrant } : {}),
300
342
  ...(ctx.terminalToolNames !== undefined ? { terminalToolNames: ctx.terminalToolNames } : {}),
301
343
  ...(ctx.terminalPriorAnswerVisible !== undefined ? { terminalPriorAnswerVisible: ctx.terminalPriorAnswerVisible } : {}),
344
+ ...(ctx.terminalCompletionAccepted !== undefined ? { terminalCompletionAccepted: ctx.terminalCompletionAccepted } : {}),
302
345
  // ⭐⭐⭐ `B3`(2026-08-19 · 대표 지시 ②) — 도는 턴 «안»으로 들어오는 사용자 발화의 배수구.
303
346
  // ⛔ 종전엔 스트리밍 중 친 발화가 ***턴이 끝난 뒤***에야 나갔다.
304
347
  // ⭐ 이제 «다음 모델 요청을 만들기 직전»(루프 경계)에 이력으로 들어가고,
@@ -319,6 +362,7 @@ export async function runCoreTurn(
319
362
  return {
320
363
  stopReason: ctx.signal.aborted ? 'aborted' : 'end_turn',
321
364
  finalText,
365
+ ...(ctx.callbacks?.onTurnComplete ? { finalPhaseAnswer } : {}),
322
366
  };
323
367
  } catch (err) {
324
368
  const stopReason = classifyStopReason(err, ctx.signal);
@@ -46,6 +46,7 @@ import {
46
46
  SEAT_IDLE_NO_WORK_NOTICE, SEAT_TURN_CAP_CONTINUE_PROMPT, SEAT_TURN_CAP_TOOL_NOTICE,
47
47
  isEmptyMailListResult, isIdleWaitCall, type SeatTurnCapConfig,
48
48
  } from './seat-turn-cap.js';
49
+ import type { TuiChatContext } from './short-question.js';
49
50
 
50
51
  export {
51
52
  CHILD_LIVENESS_HEARTBEAT_ENV,
@@ -186,10 +187,64 @@ export const GOAL_FINAL_ITERATION_NOTE =
186
187
 
187
188
  /** 중간 답이 «최종 보고형»(미완 목록)인가 — 관측 전용(행동을 바꾸지 않는다). */
188
189
  const INTERIM_REPORT_SHAPED = /(?:보고할 수 없|하지\s?못했습니다|못\s?했습니다|완료되지 않았|검증되지 않았|확인하지 못했|not (?:yet )?(?:verified|completed)|cannot report)/i;
190
+ // TUI-FINAL-ANSWER-COMPLETION(S5 · 10-12 S5-01 실측) — «단순 상태·상황 질문 턴»의 결정론 판별.
191
+ // LLM 호출 0 — 질문 문면만으로 분류한다(AL-eb6797f3b7: 첫 조각은 결정론 분류만). 이 턴의 «완료»는
192
+ // 파일·시험이 아니라 완결 답변 자체다. 그 밖의 실제 골 턴(코딩·자리 운영·쓰기 지시)은 기존대로
193
+ // update_goal 증거 게이트를 지킨다 — 필요한 작업 도구와 update_goal 을 같은 턴에 쓰는 경로는 그대로다.
194
+ export async function isSimpleStatusQuestionTurn(
195
+ userText: string | undefined,
196
+ ctx: TuiChatContext = {},
197
+ ): Promise<boolean> {
198
+ if (!userText) return false;
199
+ const { classifyTuiChatIntent, isSeatOpsDirective } = await import('./short-question.js');
200
+ if (isSeatOpsDirective(userText)) return false;
201
+ const chat = classifyTuiChatIntent(userText, ctx);
202
+ if (chat.goalLoop || chat.route === '코딩·구현') return false;
203
+ if (chat.route === '조회') return true;
204
+ // 읽기·분석 은 «판정기가 잡지 못한 나머지 전부»의 기본 라우팅이기도 하다(reason 'read') —
205
+ // 작업 지시(예: 「네 편 영상 재촬영」)까지 상태 질문으로 들이면 진행 중인 골이
206
+ // 미완 진행 한 줄 답에 완결 답으로 끊긴다(TUI-GOAL-INTERIM-QUIET 반례). 물음 형태만 수용한다.
207
+ return chat.route === '읽기·분석' && chat.reason === 'short-question';
208
+ }
209
+
189
210
  export function isInterimReportShaped(text: string): boolean {
190
211
  return INTERIM_REPORT_SHAPED.test(text);
191
212
  }
192
213
 
214
+ // TUI-FACT-TOOL-REPEAT — 턴 안에서 같은 값을 보장하는 안정 read-only 도구만 억제한다.
215
+ // Registry-wide readOnly metadata는 없다(FU). Live/poll·stream-consuming 조회(MsgList,
216
+ // ChecklistList, PtyShellPoll, AgentOutput), 외부 조회와 쓰기 동작은 이 좁은 목록 밖이다.
217
+ const GOAL_LOOP_READ_ONLY_TOOL_NAMES: ReadonlySet<string> = new Set([
218
+ 'Read', 'Grep', 'Glob', 'ListDir', 'release_status', 'self_recall', 'ops_seats', 'decisions_pending', 'proact_meter',
219
+ ]);
220
+
221
+ /** TUI-FACT-TOOL-REPEAT — 중복 판정 키: 도구명 + 인자의 stable 직렬화(키 순서와 무관하게 같은 내용=같은 키). */
222
+ function goalLoopReadOnlyCallKey(name: string, args: Record<string, unknown>): string {
223
+ return `${name}:${stableSerializeToolArgs(args)}`;
224
+ }
225
+
226
+ function stableSerializeToolArgs(value: unknown): string {
227
+ if (value === null || typeof value !== 'object') return JSON.stringify(value) ?? String(value);
228
+ if (Array.isArray(value)) return `[${value.map(stableSerializeToolArgs).join(',')}]`;
229
+ const entries = Object.entries(value as Record<string, unknown>)
230
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
231
+ .map(([key, entry]) => `${JSON.stringify(key)}:${stableSerializeToolArgs(entry)}`);
232
+ return `{${entries.join(',')}}`;
233
+ }
234
+
235
+ type ReadOnlyRepeatCacheEntry =
236
+ | { kind: 'inflight'; pending: Promise<unknown> }
237
+ | { kind: 'ok'; result: unknown }
238
+ | { kind: 'error'; error: unknown };
239
+
240
+ /** TUI-FACT-TOOL-REPEAT — 오류 캐시 적중 시 재호출 없이 돌려주는 억제 안내: 실패 근거를 실어
241
+ * 이 도구를 다시 호출하지 말고, 이 실패를 설명하는 최종 답으로 종결하게 유도한다. */
242
+ function buildReadOnlyRepeatSuppressedNotice(name: string, error: unknown): string {
243
+ const reason = error instanceof Error ? error.message : String(error);
244
+ return `[tool repeat suppressed] ${name} 은(는) 이 턴에서 이미 같은 인자로 실패했습니다(오류: ${reason}). `
245
+ + `재시도는 억제되어 실제로 실행하지 않았습니다 — 이 도구를 다시 호출하지 말고, 이 실패 근거를 설명하는 최종 답을 지금 작성하세요.`;
246
+ }
247
+
193
248
  /** 목표 실행 계약 — 첫 turn 앞에 leading system 메시지로 주입. codex 자체 prompt.md /
194
249
  * ext-goal continuation.md 의 지속·anti-shrink·증거완료 언어 이식. ASCII + 한국어. */
195
250
  export const GOAL_SYSTEM_PREAMBLE = [
@@ -316,6 +371,8 @@ export function stripGoalRepeatReadbackPreface(text: string): string {
316
371
  export interface GoalLoopOptions {
317
372
  /** 목표 문구(관측·프레이밍용). 생략 시 마지막 user 메시지에서 추출. */
318
373
  objective?: string;
374
+ /** ACP 대화형 호출자는 false로 기존 provider 재호출 유지; 비대화형·직접 실행은 기본 단축. */
375
+ terminalCompletionShortcut?: boolean;
319
376
  /** across-turn 최대 반복. 폭주 방지 하드캡. 기본 8. (ralph max_iterations 류) */
320
377
  maxIterations?: number;
321
378
  /** 연속 무진전(동일 tool 시그니처 반복) 허용 횟수 → 초과 시 no_progress 종료로 caller 가
@@ -524,6 +581,12 @@ export async function runGoalLoop(
524
581
  // ✅ 진입 시점의 messages 에는 아직 그 기계 문장이 «없다» ⇒ 여기서 뽑은 값이 이 턴의 사람 문장이다.
525
582
  // ⛔ 고정 prefix 사전으로 「기계 문장인지」를 판별하지 «않는다» — 미등록·변형 프롬프트를 오판하기 때문이다.
526
583
  const surfaceUserText = ctx.userText ?? extractRecentUserText(ctx.messages);
584
+ // TUI-FINAL-ANSWER-COMPLETION(S5) — 이 턴이 «단순 상태·상황 질문»인가(결정론 분류 · LLM 호출 0).
585
+ // seatTurnCap 유무를 자리 TUI 판정 신호로 넘긴다 — 자리의 읽기·운영 지시는 기존대로 골 루프를 탄다.
586
+ const statusQuestionTurn = await isSimpleStatusQuestionTurn(
587
+ surfaceUserText,
588
+ { seat: opts.seatTurnCap != null },
589
+ );
527
590
  const harnessRunId = getHarnessRunId();
528
591
  const runAttribution = harnessRunId ? { runId: harnessRunId } : {};
529
592
 
@@ -570,6 +633,8 @@ export async function runGoalLoop(
570
633
  let intentStallReprompts = 0;
571
634
  // GOAL-LOOP-MIDRUN-STALL — 도구를 쓴 «뒤»의 말뿐인 턴 재촉은 런당 1회뿐이다.
572
635
  let intentStallMidrunUsed = false;
636
+ // TUI-FINAL-ANSWER-COMPLETION(S5) — 상태 질문 턴의 미완 보고형 답 재촉도 런당 1회뿐이다(④ 참조).
637
+ let statusQuestionInterimReprompted = false;
573
638
 
574
639
  debug.log('goal.loop', 'start', {
575
640
  sessionId: ctx.sessionId, ...runAttribution, objective, maxIterations, noProgressLimit,
@@ -638,7 +703,8 @@ export async function runGoalLoop(
638
703
  reportShaped, finalChars: lastResult.finalText.length,
639
704
  }, { level: 'debug' });
640
705
  } catch { /* 관측 실패가 루프를 막지 않는다 */ }
641
- // Only a real continuation is interim; terminal and last-iteration answers stay visible.
706
+ // Every non-empty reply that crosses a real iteration boundary is display-only interim;
707
+ // the renderer's shared verdict decides whether it folds, independent of this loop's continuation reason.
642
708
  if (lastResult.finalText.trim()) ctx.callbacks?.onGoalInterim?.(lastResult.finalText, iterations);
643
709
  const nextIteration = iterations + 1;
644
710
  const toolBudget = ctx.maxToolTurns ?? TOOL_LOOP_MAX_TURNS_DEFAULT;
@@ -758,6 +824,30 @@ export async function runGoalLoop(
758
824
  let turnNewMessages: LLMMessage[] = [];
759
825
  let dispatchCount = 0;
760
826
  toolCallsThisIteration = 0;
827
+ // TUI-FACT-TOOL-REPEAT — 이번 core 턴의 read-only 중복 억제 캐시. 턴 시작마다 새로 만든다
828
+ // (캐시는 현재 턴 밖으로 유지하지 않는다 — 다음 반복은 새 턴이라 같은 조회도 다시 실제 실행된다).
829
+ const readOnlyRepeatCache = new Map<string, ReadOnlyRepeatCacheEntry>();
830
+ let readOnlyRepeatGeneration = 0;
831
+ const invalidateReadOnlyRepeatCache = () => {
832
+ readOnlyRepeatGeneration += 1;
833
+ readOnlyRepeatCache.clear();
834
+ };
835
+ const dispatchEffect = (
836
+ name: string, args: Record<string, unknown>, dctx: Parameters<CoreTurnContext["dispatchTool"]>[2],
837
+ ack?: () => Promise<unknown>,
838
+ ) => {
839
+ // A write or external effect can change a later read in this same turn. Clear before dispatch,
840
+ // then clear again on settlement so an in-flight read cannot repopulate stale data.
841
+ invalidateReadOnlyRepeatCache();
842
+ let dispatched: Promise<unknown>;
843
+ try {
844
+ dispatched = Promise.resolve(seatDispatch(name, args, dctx, ack ? (() => ack()) : undefined));
845
+ } catch (error) {
846
+ invalidateReadOnlyRepeatCache();
847
+ return Promise.reject(error);
848
+ }
849
+ return dispatched.finally(invalidateReadOnlyRepeatCache);
850
+ };
761
851
  let iterInputTokens = 0;
762
852
  let iterOutputTokens = 0;
763
853
  let iterCacheReadTokens = 0;
@@ -851,6 +941,17 @@ export async function runGoalLoop(
851
941
  goalRepeatWithheld = '';
852
942
  ctx.callbacks?.onText?.(withheld, full);
853
943
  };
944
+ const flushNovelGoalRepeatWithheld = (full: string): void => {
945
+ if (goalRepeatWithheld === '') return;
946
+ const readback = stripGoalRepeatReadbackPreface(goalRepeatWithheld);
947
+ const normalized = goalRepeatStreamNormalize(readback);
948
+ const prior = goalRepeatPreviousAnswer;
949
+ const novel = normalized.startsWith(prior)
950
+ ? normalized.slice(prior.length)
951
+ : normalized;
952
+ goalRepeatWithheld = '';
953
+ if (novel.length > 0) ctx.callbacks?.onText?.(novel, full);
954
+ };
854
955
  const turnCtx: CoreTurnContext = {
855
956
  ...ctx,
856
957
  messages,
@@ -860,8 +961,12 @@ export async function runGoalLoop(
860
961
  ...(surfaceUserText !== undefined ? { userText: surfaceUserText } : {}),
861
962
  // TUI-GOAL-LOOP-FRICTION(#46·#63) — update_goal 은 도구 예산 거부를 받지 않고, 답과 함께 오면 그 턴으로 마감한다.
862
963
  terminalToolNames: [...(ctx.terminalToolNames ?? []), UPDATE_GOAL_TOOL_NAME],
863
- // TUI-H1-GOALLOOP-EMPTY-TAIL — 앞 iteration 의 답이 이미 화면에 있으면 «update_goal 만 → 빈 턴» 은 할 말이 없는
864
- // 것이다 — 재촉·경고 없이 빈 답으로 끝내고 아래 완료 판정이 앞 답으로 마감한다(중복 접기와 같은 길).
964
+ ...(opts.terminalCompletionShortcut !== false ? {
965
+ terminalCompletionAccepted: (name: string, args: Record<string, unknown>) => name === UPDATE_GOAL_TOOL_NAME
966
+ && args.status === 'complete' && typeof args.evidence === 'string' && args.evidence.trim().length > 0,
967
+ } : {}),
968
+ // The visible-answer hint also guards ACP's legacy empty-tail path; only
969
+ // the validated completion shortcut is caller-scoped.
865
970
  ...(previousFinalText.trim().length > 0 ? { terminalPriorAnswerVisible: true } : {}),
866
971
  // update_goal 은 종결 신호 — 실 dispatcher 로 새지 않게 가로채 ack 만 돌려준다.
867
972
  dispatchTool: (name, args, dctx) => {
@@ -885,9 +990,37 @@ export async function runGoalLoop(
885
990
  // 종결 신호는 예산 거부를 받지 않는다(#28503 terminalToolNames 계약과 같은 방향). 그 밖의 진행 선언
886
991
  // (in_progress·blocked)은 도구 한 번으로 세고 상한 뒤엔 같은 안내로 거부한다(리뷰 r2 — 61번 넘게 불러도 안 막히던 구멍).
887
992
  if ((args as { status?: unknown }).status === 'complete') return ack();
888
- return seatDispatch(name, args, dctx, ack);
993
+ return dispatchEffect(name, args, dctx, ack);
889
994
  }
890
- return seatDispatch(name, args, dctx);
995
+ // TUI-FACT-TOOL-REPEAT — update_goal 가로채기 판정 «뒤» read-only 실 실행 직전:
996
+ // 동일 read-only tool+args 는 이 턴에서 실제 실행 1회 이하(성공 결과 재사용 · 오류 재시도 억제).
997
+ // 쓰기·외부 효과 도구는 허용목록 밖이라 억제 없이 매번 실제 실행된다(경계 보존).
998
+ if (GOAL_LOOP_READ_ONLY_TOOL_NAMES.has(name)) {
999
+ const repeatKey = goalLoopReadOnlyCallKey(name, args);
1000
+ const cachedRepeat = readOnlyRepeatCache.get(repeatKey);
1001
+ if (cachedRepeat !== undefined) {
1002
+ try {
1003
+ debug.log('goal.loop', 'readonly-tool-repeat-suppressed', {
1004
+ sessionId: ctx.sessionId, ...runAttribution, iteration: iterations,
1005
+ tool: name, dispatch: dispatchCount, outcome: cachedRepeat.kind,
1006
+ }, { level: 'info' });
1007
+ } catch {
1008
+ // Observability must not change the suppressed result.
1009
+ }
1010
+ if (cachedRepeat.kind === 'inflight') return cachedRepeat.pending;
1011
+ if (cachedRepeat.kind === 'ok') return Promise.resolve(cachedRepeat.result);
1012
+ return Promise.resolve(buildReadOnlyRepeatSuppressedNotice(name, cachedRepeat.error));
1013
+ }
1014
+ const generation = readOnlyRepeatGeneration;
1015
+ const dispatchedRead = Promise.resolve(seatDispatch(name, args, dctx));
1016
+ readOnlyRepeatCache.set(repeatKey, { kind: 'inflight', pending: dispatchedRead });
1017
+ dispatchedRead.then(
1018
+ (result) => { if (generation === readOnlyRepeatGeneration) readOnlyRepeatCache.set(repeatKey, { kind: 'ok', result }); },
1019
+ (error) => { if (generation === readOnlyRepeatGeneration) readOnlyRepeatCache.set(repeatKey, { kind: 'error', error }); },
1020
+ );
1021
+ return dispatchedRead;
1022
+ }
1023
+ return dispatchEffect(name, args, dctx);
891
1024
  },
892
1025
  callbacks: {
893
1026
  ...ctx.callbacks,
@@ -902,6 +1035,13 @@ export async function runGoalLoop(
902
1035
  return;
903
1036
  }
904
1037
  goalRepeatWithholding = false;
1038
+ const combined = goalRepeatWithheld + delta;
1039
+ if (opts.terminalCompletionShortcut !== false && previousFinalText
1040
+ && stripGoalRepeatReadbackPreface(combined).startsWith(previousFinalText)) {
1041
+ goalRepeatWithheld = combined;
1042
+ flushNovelGoalRepeatWithheld(full);
1043
+ return;
1044
+ }
905
1045
  flushGoalRepeatWithheld(full);
906
1046
  }
907
1047
  ctx.callbacks?.onText?.(delta, full);
@@ -955,7 +1095,17 @@ export async function runGoalLoop(
955
1095
  const pureRepeat = normalized === goalRepeatPreviousAnswer
956
1096
  || GOAL_REPEAT_READBACK_PHRASES.some((phrase) => normalized.startsWith(phrase)
957
1097
  && normalized.slice(phrase.length).replace(GOAL_REPEAT_PREFACE_SEPS, '') === goalRepeatPreviousAnswer);
958
- if (!pureRepeat) flushGoalRepeatWithheld(normalized);
1098
+ if (!pureRepeat) {
1099
+ // A completion-only round may have skipped LLM onText because the prior
1100
+ // answer is already visible. Keep only its genuinely new suffix.
1101
+ if (opts.terminalCompletionShortcut !== false && previousFinalText
1102
+ && stripGoalRepeatReadbackPreface(goalRepeatWithheld).startsWith(previousFinalText)) {
1103
+ flushNovelGoalRepeatWithheld(goalRepeatWithheld);
1104
+ } else {
1105
+ // ACP keeps its legacy normalized iteration-flush behavior.
1106
+ flushGoalRepeatWithheld(normalized);
1107
+ }
1108
+ }
959
1109
  }
960
1110
  turnNewMessages = msgs;
961
1111
  ctx.callbacks?.onTurnComplete?.(msgs);
@@ -1018,13 +1168,22 @@ export async function runGoalLoop(
1018
1168
 
1019
1169
  // ①-0 #29 처방 — 자리 운영 턴은 빈 evidence 를 반려하지 않고 이 턴의 답을 증거로 받는다(관측 남김).
1020
1170
  // 답도 비었으면 받을 증거가 없다 — 종전 반려(evidence required)로 그대로 간다.
1021
- const lenientAnswer = opts.lenientCompletionEvidence === true
1022
- ? boundReadableText(lastResult.finalText, 200).text.trim()
1023
- : '';
1171
+ // TUI-FINAL-ANSWER-COMPLETION(S5) — 단순 상태 질문 턴도 같은 수용을 받는다: 이 턴의 «완료»는
1172
+ // 완결 답변 자체다. 빈 evidence 로 반려·재주입하면 답 뒤 빈 턴이 [NO FINAL SYNTHESIS] 로
1173
+ // 떨어져 최종 답이 비었다(10-12 S5-01 실측). 그 안내 문면 자체는 «증거»가 아니다.
1174
+ const lenientScope: 'seat' | 'status-question' | null = opts.lenientCompletionEvidence === true
1175
+ ? 'seat'
1176
+ : statusQuestionTurn && !lastResult.finalText.includes('[NO FINAL SYNTHESIS]')
1177
+ ? 'status-question'
1178
+ : null;
1179
+ const lenientAnswer = lenientScope === null
1180
+ ? ''
1181
+ : boundReadableText(lastResult.finalText, 200).text.trim();
1024
1182
  if (goalUpdate?.status === 'complete' && goalUpdate.evidence.trim().length === 0 && lenientAnswer.length > 0) {
1025
- goalUpdate.evidence = `(자리 운영 턴 — 답을 증거로 수용) ${lenientAnswer}`;
1183
+ goalUpdate.evidence = `${lenientScope === 'status-question' ? '(상태 질문 턴 — 완결 답을 증거로 수용)' : '(자리 운영 턴 — 답을 증거로 수용)'} ${lenientAnswer}`;
1026
1184
  debug.log('goal.loop', 'complete-evidence-lenient', {
1027
1185
  sessionId: ctx.sessionId, ...runAttribution, iterations, finalChars: lastResult.finalText.length,
1186
+ scope: lenientScope,
1028
1187
  }, { level: 'info' });
1029
1188
  }
1030
1189
 
@@ -1177,6 +1336,60 @@ export async function runGoalLoop(
1177
1336
  continue;
1178
1337
  }
1179
1338
 
1339
+ // An explicit provider final phase is a bounded terminal signal for a
1340
+ // substantial structured answer outside the coding executor. A finished
1341
+ // report must not reopen tools solely because update_goal was omitted.
1342
+ const structuredFinalAnswer = lastResult.finalPhaseAnswer === true
1343
+ && getHarnessRole() !== 'executor'
1344
+ && lastResult.finalText.trim().length >= 1_200
1345
+ && (lastResult.finalText.match(/^#{1,3}\s+\S+/gm)?.length ?? 0) >= 2
1346
+ && goalUpdate == null
1347
+ && rejectedTools.length === 0
1348
+ && !markerComplete
1349
+ && !markerBlocked
1350
+ && runTests.last?.ok !== false
1351
+ && !seatCapHit;
1352
+ if (structuredFinalAnswer) {
1353
+ debug.log('goal.loop', 'complete', {
1354
+ sessionId: ctx.sessionId, ...runAttribution, iterations, via: 'structured-final-phase',
1355
+ finalChars: lastResult.finalText.length,
1356
+ }, { level: 'info' });
1357
+ return finish(
1358
+ { finalText: lastResult.finalText, iterations, stopReason: 'goal_complete', goalComplete: true },
1359
+ { summary: 'Structured answer completed in the provider final phase.', changedFiles: [] },
1360
+ );
1361
+ }
1362
+
1363
+ // ③-5 TUI-FINAL-ANSWER-COMPLETION(S5) — 단순 상태 질문 턴의 완결한 최종 답 = 그 턴의 목표 달성이다.
1364
+ // structuredFinalAnswer 가 «대형 보고서»의 종결 신호라면, 이것은 그 «한 줄 답» 짝이다. «완료 신호는
1365
+ // update_goal 호출뿐»이라는 계약은 실제 골 턴(코딩·자리 운영·쓰기)의 것이다 — 상태 질문 턴에 그대로
1366
+ // 밀면 완결 답 뒤에 불필요한 update_goal 재촉이 이어붙고 빈 턴이 [NO FINAL SYNTHESIS] 로 떨어져
1367
+ // 최종 답이 비었다(10-12 S5-01 실측 · 0.2.28 TUI-NO-SYNTH-FALLBACK은 그 빈 답의 사람 말 안내일 뿐).
1368
+ // 결정론 분류(statusQuestionTurn) 턴에서 이번 반복이 도구·신호 없이 완결 답으로 끝났으면 추가 골
1369
+ // 도구 0으로 종결한다. 미완 보고형(isInterimReportShaped)과 [NO FINAL SYNTHESIS] 안내 문면은 완결 답이 아니다.
1370
+ const statusQuestionFinalAnswer = statusQuestionTurn
1371
+ && getHarnessRole() !== 'executor'
1372
+ && goalUpdate == null
1373
+ && rejectedTools.length === 0
1374
+ && !markerComplete
1375
+ && !markerBlocked
1376
+ && runTests.last?.ok !== false
1377
+ && !seatCapHit
1378
+ && lastResult.stopReason === 'end_turn'
1379
+ && lastResult.finalText.trim().length > 0
1380
+ && !isInterimReportShaped(lastResult.finalText)
1381
+ && !lastResult.finalText.includes('[NO FINAL SYNTHESIS]');
1382
+ if (statusQuestionFinalAnswer) {
1383
+ debug.log('goal.loop', 'complete', {
1384
+ sessionId: ctx.sessionId, ...runAttribution, iterations, via: 'status-question-final-answer',
1385
+ finalChars: lastResult.finalText.length,
1386
+ }, { level: 'info' });
1387
+ return finish(
1388
+ { finalText: lastResult.finalText, iterations, stopReason: 'goal_complete', goalComplete: true },
1389
+ { summary: '상태 질문 턴 완결 답 종결 — 추가 골 도구 0 (TUI-FINAL-ANSWER-COMPLETION S5)', changedFiles: [] },
1390
+ );
1391
+ }
1392
+
1180
1393
  // ② blocked(구조화 or 마커) — 3연속(hysteresis)일 때만 수용(조기 give-up 방지).
1181
1394
  if (goalUpdate?.status === 'blocked' || markerBlocked) {
1182
1395
  blockedStreak += 1;
@@ -1244,7 +1457,24 @@ export async function runGoalLoop(
1244
1457
 
1245
1458
  // ④ 순수 텍스트(도구 없음)로 끝났고 종결 신호도 없음 = 일상 답변(목표성 작업 아님).
1246
1459
  // 재주입하지 않고 그대로 수용해 trivial chat 을 이중 루프하지 않는다.
1460
+ // TUI-FINAL-ANSWER-COMPLETION(S5) — 단 하나의 예외: «단순 상태 질문» 턴의 미완 보고형 답
1461
+ // (예: 「아직 확인하지 못했습니다」)은 유효한 최종 답이 아니다. 런당 1회만 continuation 을
1462
+ // 재주입해 답을 완성하게 한다(④-0b «런당 1회» 관례와 같은 상한). 두 번째에도 그 모양이면
1463
+ // 이곳의 수용으로 그대로 끝난다 — 이중 루프 방지·maxIterations 하드캡 불변.
1247
1464
  if (!toolActivity) {
1465
+ if (statusQuestionTurn
1466
+ && !seatCapHit
1467
+ && lastResult.finalText.trim().length > 0
1468
+ && isInterimReportShaped(lastResult.finalText)
1469
+ && !lastResult.finalText.includes('[NO FINAL SYNTHESIS]')
1470
+ && !statusQuestionInterimReprompted) {
1471
+ statusQuestionInterimReprompted = true;
1472
+ debug.log('goal.loop', 'status-question-interim-reprompt', {
1473
+ sessionId: ctx.sessionId, ...runAttribution, iterations, finalChars: lastResult.finalText.length,
1474
+ }, { level: 'info' });
1475
+ reinject(GOAL_CONTINUATION_PROMPT);
1476
+ continue;
1477
+ }
1248
1478
  debug.log('goal.loop', 'text-only-accept', { sessionId: ctx.sessionId, ...runAttribution, iterations }, { level: 'info' });
1249
1479
  return finish({ finalText: lastResult.finalText, iterations, stopReason: lastResult.stopReason, goalComplete: false });
1250
1480
  }
@@ -84,6 +84,8 @@ export interface CoreTurnCallbacks {
84
84
  /** Streaming text delta — `full` is the accumulated text across the
85
85
  * entire turn (not just the current round). */
86
86
  onText?(delta: string, full: string): void;
87
+ /** Transient runtime status (for example, a stream retry notice). */
88
+ onStatus?(line: string): void;
87
89
  /** The final answer came back enriched with a runtime verification
88
90
  * supplement — forwarded from `StreamWithToolsHandlers.onFinalAnswerSupplement`. */
89
91
  onFinalAnswerSupplement?(info: { answer: string; supplement: string; finalText: string }): void;
@@ -142,6 +144,9 @@ export interface CoreTurnContext {
142
144
  surfaceProfile?: import('../session-runtime/index.js').SessionSurfaceProfile;
143
145
  /** Full prompt (system + history + current user blocks). */
144
146
  messages: LLMMessage[];
147
+ /** Optional provider request-size hook. Only providers with a measured
148
+ * serializer consume it; all others retain their existing request path. */
149
+ requestSizeGuard?: LLMOpts['requestSizeGuard'];
145
150
  /** Tool catalog the model may call this turn. Empty array means
146
151
  * "text-only" — the loop delegates to plain `streamLLM`. */
147
152
  tools: LLMToolSpec[];
@@ -166,6 +171,8 @@ export interface CoreTurnContext {
166
171
  /** TUI-H1-GOALLOOP-EMPTY-TAIL — 이 턴 «앞»에 사람에게 답을 이미 보였다. `streamLLMWithTools` 의
167
172
  * `terminalPriorAnswerVisible` 로 그대로 간다(종결 신호 뒤 빈 턴 = 경고 없이 빈 답). goal loop 가 넣는다. */
168
173
  terminalPriorAnswerVisible?: LLMOpts['terminalPriorAnswerVisible'];
174
+ /** Only a structurally valid goal completion may stop before the next provider request. */
175
+ terminalCompletionAccepted?: LLMOpts['terminalCompletionAccepted'];
169
176
  /** Optional model override (forwarded to `streamLLMWithTools`). */
170
177
  modelOverride?: string;
171
178
  /** TUI-400-AUTOHEAL-FALLBACK — 이 턴을 이 공급자부터 연다(`streamLLMWithTools` `initialProvider` · 폴백은 허용).
@@ -178,6 +185,8 @@ export interface CoreTurnContext {
178
185
  export interface CoreTurnResult {
179
186
  stopReason: CoreTurnStopReason;
180
187
  finalText: string;
188
+ /** The completed provider response explicitly marked its last assistant answer as final. */
189
+ finalPhaseAnswer?: boolean;
181
190
  /** `auth_rejected` 일 때만 — 공급자 오류 원문(비밀값 가림). 호스트가 처방 줄에 원문을 붙인다. */
182
191
  errorMessage?: string;
183
192
  }