elanous 0.2.31 → 0.2.34

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 (715) 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/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
  5. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
  8. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
  9. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
  13. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
  15. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
  16. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
  19. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
  30. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
  31. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
  37. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
  39. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
  41. package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
  44. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
  45. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
  46. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
  47. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
  48. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
  51. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
  63. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
  76. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
  80. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
  87. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
  91. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
  94. package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
  97. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
  114. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
  116. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
  117. package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
  123. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-0a07363b130182a1.js → page-398c0faa173203f7.js} +1 -1
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +9 -2
  279. package/docs/goal-context/README.md +1 -0
  280. package/graphs/default-loop.yaml +20 -3
  281. package/graphs/document-loop.yaml +21 -2
  282. package/graphs/implement-loop.yaml +11 -0
  283. package/graphs/journey/SCENARIOS.md +33 -0
  284. package/graphs/journey/recipes.yaml +1 -0
  285. package/graphs/journey/ta-journey.yaml +84 -0
  286. package/graphs/journey/units/author/author.yaml +20 -0
  287. package/graphs/journey/units/author/recipes.yaml +2 -0
  288. package/graphs/journey/units/green/green.yaml +20 -0
  289. package/graphs/journey/units/green/recipes.yaml +2 -0
  290. package/graphs/journey/units/pr/pr.yaml +20 -0
  291. package/graphs/journey/units/pr/recipes.yaml +2 -0
  292. package/graphs/journey/units/remember/recipes.yaml +2 -0
  293. package/graphs/journey/units/remember/remember.yaml +20 -0
  294. package/graphs/operate-loop.yaml +21 -2
  295. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  296. package/graphs/release-rehearsal/recipes.yaml +1 -1
  297. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  298. package/graphs/research-loop.yaml +23 -2
  299. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  300. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  301. package/graphs/units/entry/entry.yaml +50 -0
  302. package/graphs/units/entry/recipes.yaml +14 -0
  303. package/graphs/units/harvest/harvest.yaml +25 -0
  304. package/graphs/units/harvest/recipes.yaml +4 -0
  305. package/graphs/units/land/land.yaml +45 -0
  306. package/graphs/units/land/recipes.yaml +3 -0
  307. package/graphs/units/recipes.yaml +7 -0
  308. package/graphs/units/recover.yaml +39 -0
  309. package/graphs/units/reflect/recipes.yaml +3 -0
  310. package/graphs/units/reflect/reflect.yaml +15 -0
  311. package/graphs/units/task-agent-recover-review.yaml +17 -0
  312. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  313. package/graphs/units/verbs/make-doc.yaml +34 -0
  314. package/graphs/units/verbs/recipes.yaml +33 -0
  315. package/graphs/units/verbs/verify.yaml +55 -0
  316. package/graphs/work/recipes.yaml +2 -0
  317. package/graphs/work/research-report.yaml +28 -0
  318. package/package.json +1 -1
  319. package/scripts/ci-typecheck-changed.ts +95 -17
  320. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  321. package/scripts/graph-harvest-unit.ts +22 -0
  322. package/scripts/graph-units/journey-stub.ts +6 -0
  323. package/scripts/graph-units/land-enqueue.ts +78 -0
  324. package/scripts/graph-units/recover-plan.ts +15 -0
  325. package/scripts/graph-units/reflect-node.ts +88 -0
  326. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  327. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  328. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  329. package/scripts/graph-units/verbs-envelope.ts +139 -0
  330. package/scripts/hq/standby-snapshot.ts +25 -0
  331. package/scripts/measure-si-task-cpu.ts +143 -0
  332. package/scripts/public-export.ts +43 -1
  333. package/scripts/ratchets/test-interference-patterns.allowlist.txt +0 -2
  334. package/scripts/ratchets/train-side-invariants.sh +45 -0
  335. package/scripts/release-loop/auto-approve-node.ts +30 -16
  336. package/scripts/release-loop/gate-closure.ts +5 -1
  337. package/scripts/release-loop/gate-diff.ts +1 -1
  338. package/scripts/release-loop/gate-node.ts +498 -31
  339. package/scripts/release-loop/gate-partial.ts +3 -3
  340. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  341. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  342. package/scripts/release-loop/gate-triage-node.ts +5 -2
  343. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  344. package/scripts/release-loop/known-issues-node.ts +77 -8
  345. package/scripts/release-loop/preflight.ts +93 -7
  346. package/scripts/release-loop/prepare-node.ts +102 -4
  347. package/scripts/release-loop/publish-node.ts +60 -9
  348. package/scripts/release-loop/resume-cap.ts +56 -0
  349. package/scripts/release-loop/resume-release.ts +114 -15
  350. package/scripts/release-loop/resume.ts +24 -1
  351. package/scripts/release-loop/tui-sim-node.ts +8 -2
  352. package/scripts/release-loop/unattended-release.ts +8 -2
  353. package/src/acp/core-turn-bridge.ts +36 -9
  354. package/src/acp/elanous-extensions.ts +3 -0
  355. package/src/acp/reasoning-thought-buffer.ts +45 -0
  356. package/src/acp/server.ts +3 -0
  357. package/src/acp/tool-trace.ts +186 -11
  358. package/src/agent/self-ambient-cache.ts +156 -0
  359. package/src/agent/self-ambient.ts +8 -1
  360. package/src/agent/task-notification.ts +5 -0
  361. package/src/agent-substrate/acp-reviewer.ts +52 -12
  362. package/src/agent-substrate/pr-reviewer.ts +3 -1
  363. package/src/agent-substrate/review-finding-key.ts +53 -0
  364. package/src/agent-substrate/self-review-cli.ts +126 -5
  365. package/src/ask-user-question/pending-questions.ts +1 -1
  366. package/src/ask-user-question/tool.ts +22 -0
  367. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  368. package/src/autopilot/pr-manager.ts +213 -46
  369. package/src/capture/frame-state-detect.ts +39 -0
  370. package/src/capture/tui-self-report.ts +134 -6
  371. package/src/chat/index.ts +61 -15
  372. package/src/chat/pickers/modal-runtime.ts +6 -0
  373. package/src/chat/pickers/modals.ts +8 -2
  374. package/src/chat/tool-render/dispatch.ts +62 -10
  375. package/src/cli/ask-bare.ts +1 -0
  376. package/src/cli/control-cli.ts +24 -7
  377. package/src/cli/guardian-cli.ts +10 -0
  378. package/src/cli/import-cli.ts +12 -0
  379. package/src/cli/light-entry-route.ts +35 -0
  380. package/src/cli/llm-detect-cli.ts +23 -1
  381. package/src/cli/log-event-names.ts +10 -0
  382. package/src/cli/msg-cli.ts +1 -0
  383. package/src/cli/pod-cli.ts +14 -3
  384. package/src/cli/pr-cli.ts +140 -41
  385. package/src/cli/pr-land-base-read.ts +36 -0
  386. package/src/cli/pr-land-heavy-remote.ts +81 -25
  387. package/src/cli/pr-land-overlap-evidence.ts +200 -18
  388. package/src/cli/pr-land-pod-shadow-job.ts +26 -3
  389. package/src/cli/pr-land-recovery.ts +64 -0
  390. package/src/cli/pr-land-refusal.ts +20 -5
  391. package/src/cli/pty-takeover-cli.ts +94 -19
  392. package/src/cli/release-cli.ts +120 -33
  393. package/src/cli/release-run-if-ready.ts +29 -28
  394. package/src/cli/release-single-flight.ts +178 -0
  395. package/src/cli/seat-cli.ts +37 -0
  396. package/src/cli/setup-cli.ts +40 -1
  397. package/src/cli/sim-cli.ts +18 -0
  398. package/src/cli/tasks-cli.ts +149 -5
  399. package/src/context-bus/ops-events.ts +6 -2
  400. package/src/control/control-status.ts +8 -3
  401. package/src/control-plane/ledger.ts +5 -3
  402. package/src/control-plane/server.ts +5 -3
  403. package/src/core-turn/run-core-turn.ts +1 -0
  404. package/src/core-turn/run-goal-loop.ts +21 -0
  405. package/src/core-turn/short-question.ts +5 -1
  406. package/src/core-turn/types.ts +3 -0
  407. package/src/dashboard/acp-active-model.ts +42 -1
  408. package/src/dashboard/background-jobs-status.ts +66 -0
  409. package/src/dashboard/index.ts +153 -111
  410. package/src/dashboard/input/agent-wake.ts +242 -0
  411. package/src/dashboard/input/chat-main-entry-runtime.ts +5 -0
  412. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  413. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  414. package/src/dashboard/input/external-input-host.ts +23 -9
  415. package/src/dashboard/input/mouse-wiring.ts +108 -11
  416. package/src/dashboard/input/seat-autowake.ts +56 -3
  417. package/src/dashboard/log-click-runtime.ts +118 -2
  418. package/src/dashboard/seat-boot-preamble.ts +1 -1
  419. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  420. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  421. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  422. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  423. package/src/dashboard/turn-preamble.ts +163 -41
  424. package/src/dashboard/turn-session-layers.ts +4 -2
  425. package/src/dashboard/turn-start-segments.ts +222 -0
  426. package/src/dashboard/turn-stream-formatter.ts +34 -1
  427. package/src/dashboard/turn-stream-runtime.ts +2 -0
  428. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  429. package/src/display/prompt-row-owner.ts +146 -0
  430. package/src/display/resize-listener.ts +33 -2
  431. package/src/domains/guardian-tick.ts +54 -2
  432. package/src/domains/outbound-alert.ts +3 -2
  433. package/src/extractors.ts +3 -1
  434. package/src/fold-stack.ts +4 -2
  435. package/src/git-fs/index.ts +263 -36
  436. package/src/git-fs/retry.ts +4 -0
  437. package/src/git-fs/runner.ts +2 -0
  438. package/src/graph-runner/runner.ts +114 -44
  439. package/src/grok/credential.ts +5 -0
  440. package/src/harness/gate-reserve.ts +87 -0
  441. package/src/harness/harness-cli-command.ts +39 -10
  442. package/src/harness/harness-incidents.ts +17 -0
  443. package/src/harness/harness-pod-dispatch.ts +38 -1
  444. package/src/harness/harness-queue.ts +15 -0
  445. package/src/harness/harness-salvage-cli.ts +14 -2
  446. package/src/index.ts +198 -12
  447. package/src/input/external-input-queue.ts +34 -9
  448. package/src/intake-plane/already-built-hint.ts +89 -0
  449. package/src/knowhow/pack.ts +199 -0
  450. package/src/light-cli.ts +95 -0
  451. package/src/llm/route-decision.ts +36 -0
  452. package/src/llm/tool-loop-steered-rejection.ts +8 -0
  453. package/src/llm-request-shape.ts +209 -0
  454. package/src/llm.ts +221 -276
  455. package/src/loops/budget.ts +95 -0
  456. package/src/loops/msg-wake.ts +8 -2
  457. package/src/loops/orchestrator/tick.ts +24 -2
  458. package/src/loops/orchestrator/traffic.ts +132 -1
  459. package/src/maturity/feature-maturity.ts +1 -1
  460. package/src/mss/logging/log-store.ts +4 -5
  461. package/src/mss/logging/render-categories.ts +5 -0
  462. package/src/nexus/api/graphs-api.ts +22 -3
  463. package/src/nexus/api/http-server.ts +1 -1
  464. package/src/nexus/api/ops-api.ts +12 -0
  465. package/src/oauth/claude-pty-maturity.ts +66 -0
  466. package/src/oauth/codex-access-mirror.ts +55 -0
  467. package/src/oauth/fallback-chain.ts +1 -1
  468. package/src/onboarding/first-run.ts +5 -3
  469. package/src/onboarding/non-interactive.ts +64 -13
  470. package/src/onboarding.ts +10 -2
  471. package/src/ops/overview-collect.ts +36 -1
  472. package/src/ops/overview.ts +70 -2
  473. package/src/pr-tool/census.ts +41 -8
  474. package/src/pr-tool/inflight-registry.ts +296 -0
  475. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  476. package/src/pty-shell/herdr-agent-report.ts +442 -0
  477. package/src/pty-shell/pty-control-ipc.ts +5 -5
  478. package/src/pty-shell/pty-manifest.ts +12 -3
  479. package/src/pty-shell/pty-write-outcome.ts +24 -6
  480. package/src/pty-shell/tui-run-state.ts +151 -6
  481. package/src/release-loop/checklist.ts +79 -5
  482. package/src/release-loop/feature-store.ts +19 -2
  483. package/src/release-loop/placement.ts +10 -3
  484. package/src/release-loop/rehearsal.ts +205 -25
  485. package/src/release-loop/rubric.ts +16 -2
  486. package/src/seat-loop/traffic-signal.ts +2 -1
  487. package/src/self-dev/ask-launch-flow.ts +13 -0
  488. package/src/self-dev/draft-residue.ts +243 -24
  489. package/src/self-dev/draft-sweep.ts +52 -3
  490. package/src/self-dev/graph-journey-nodes.ts +10 -6
  491. package/src/self-dev/graph-journey-route.ts +60 -6
  492. package/src/self-dev/orchestrate.ts +79 -3
  493. package/src/self-dev/run-supervisor.ts +107 -12
  494. package/src/self-dev/run-types.ts +5 -1
  495. package/src/self-dev/shard-plan.ts +11 -3
  496. package/src/self-dev/shard-run.ts +103 -10
  497. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  498. package/src/self-implement/follow-up-placement.ts +79 -0
  499. package/src/self-implement/gate-artifacts.ts +15 -4
  500. package/src/self-implement/gate-baseline.ts +145 -10
  501. package/src/self-implement/gate-cli.ts +7 -2
  502. package/src/self-implement/gate-remote.ts +35 -6
  503. package/src/self-implement/goal-author-identity.ts +66 -0
  504. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  505. package/src/self-implement/goal-author.ts +4 -120
  506. package/src/self-implement/graph-overlay-yaml.ts +17 -2
  507. package/src/self-implement/graph-unit-flatten.ts +103 -0
  508. package/src/self-implement/graph-unit-resolver.ts +107 -0
  509. package/src/self-implement/graph-yaml.ts +151 -1
  510. package/src/self-implement/headless-elanous-driver.ts +1 -0
  511. package/src/self-implement/host-regate.ts +36 -4
  512. package/src/self-implement/knowhow-pack.ts +103 -0
  513. package/src/self-implement/orchestrator.ts +109 -11
  514. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  515. package/src/self-implement/review-mustfix-class.ts +203 -0
  516. package/src/self-implement/run-ledger.ts +16 -14
  517. package/src/self-implement/run-stop.ts +8 -2
  518. package/src/self-implement/seams.ts +32 -1
  519. package/src/self-implement/stop-autoheal.ts +25 -1
  520. package/src/session/chat.ts +27 -0
  521. package/src/session-runtime/index.ts +22 -267
  522. package/src/session-runtime/retry-policy.ts +2 -1
  523. package/src/shell-runner/background-surface.ts +15 -5
  524. package/src/skills/tools/agent.ts +39 -6
  525. package/src/skills/tools/list-dir.ts +11 -0
  526. package/src/skills/tools/schedule-wakeup.ts +457 -0
  527. package/src/skills/tools/shell.ts +245 -3
  528. package/src/status/bar.ts +26 -0
  529. package/src/steward/digest-delivery.ts +118 -0
  530. package/src/steward/hold-hygiene.ts +120 -0
  531. package/src/steward/release-day.ts +7 -3
  532. package/src/steward/triage.ts +47 -4
  533. package/src/surface/shell-runner-boot.ts +5 -2
  534. package/src/task-agent/harvest-unit.ts +141 -0
  535. package/src/task-agent/live-moves.ts +98 -12
  536. package/src/task-agent/parent-host.ts +93 -3
  537. package/src/task-agent/postland-card.ts +80 -1
  538. package/src/task-agent/rejudge-on-head.ts +112 -26
  539. package/src/task-agent/repair-branch-cas.ts +4 -1
  540. package/src/task-agent/repair-cycle.ts +16 -3
  541. package/src/task-agent/run-identity.ts +4 -3
  542. package/src/task-agent/shadow.ts +12 -2
  543. package/src/task-agent/task-hand.ts +76 -5
  544. package/src/task-agent/work-order-build.ts +22 -0
  545. package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
  546. package/src/task-orchestrator/surfaces/pod-command-job.ts +67 -12
  547. package/src/task-orchestrator/surfaces/pod-lease.ts +98 -0
  548. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  549. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  550. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -18
  551. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +10 -6
  552. package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
  553. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +548 -0
  554. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
  555. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  556. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +158 -3
  557. package/src/task-orchestrator/surfaces/self-implement-pod.ts +230 -43
  558. package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
  559. package/src/tool-runtime/truncation-store.ts +4 -0
  560. package/src/tui/chat/execution-badge.ts +5 -1
  561. package/src/tui/input-lag-probe.ts +230 -0
  562. package/src/tui-client/dashboard-session.ts +10 -1
  563. package/src/tui.ts +4 -0
  564. package/src/user-config/coercion.ts +36 -0
  565. package/src/user-config.ts +18 -41
  566. package/src/ux-sim/scenario.ts +314 -0
  567. package/src/version/packed-revision.json +1 -1
  568. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  571. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  572. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  573. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  577. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  579. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  580. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  587. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  588. package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
  591. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  595. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  599. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  600. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  602. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  605. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  612. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  619. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  620. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  622. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  627. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  628. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  635. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2ebb8fd59b9461f9.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  706. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  713. package/apps/pwa/out/_next/static/css/3f5fc6f96e2cf7b2.css +0 -1
  714. package/src/cli/g6a-registration-probe.ts +0 -16
  715. /package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
package/src/llm.ts CHANGED
@@ -48,7 +48,8 @@ import {
48
48
  type ProviderFallbackAttempt,
49
49
  type ProviderFallbackTerminalVerdict,
50
50
  } from './session-runtime/retry-policy.js';
51
- import { fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
51
+ import { ApiHttpError, fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
52
+ import { isShapeRelevantRejection, summarizeCodexRequestShape } from './llm-request-shape.js';
52
53
  import { BedrockProvider, isBedrockCompatibleModel, makeBedrockProvider } from './llm/bedrock-provider.js';
53
54
  import { OPEN_WEIGHT_TOOL_DISCIPLINE } from './llm/open-weight-discipline.js';
54
55
  import { makeZaiCodingPlanProvider, zaiCodingPlanAvailable } from './llm/zai-coding-plan.js';
@@ -61,8 +62,6 @@ import { undoTurnRuntime } from './tool-runtime/undo-turn-runtime.js';
61
62
  import { listSnapshots } from './undo-turn/index.js';
62
63
  // Zero-dep spec module (no tool-runtime registry) — safe for this hot path.
63
64
  import { takeHydratedTools } from './skills/tools/tool-search-spec.js';
64
- import { dispatchAskUserQuestion } from './ask-user-question/index.js';
65
- import type { AskUserQuestionResult } from './ask-user-question/index.js';
66
65
  import { isPlanModeActive } from './plan-mode/session.js';
67
66
  import { mintTurnUri } from './mss/uri/builder.js';
68
67
  import type { TurnUri } from './mss/uri/brand.js';
@@ -406,6 +405,10 @@ export interface LLMOpts {
406
405
  * ③ 종결 신호를 받은 뒤의 빈 턴 포기에도 이미 쓴 답이 있으면 `[NO FINAL SYNTHESIS]` 를 붙이지 않는다.
407
406
  * 비우면(기본) 종전 동작 그대로. */
408
407
  terminalToolNames?: readonly string[];
408
+ /** TUI-H1-GOALLOOP-EMPTY-TAIL — 호출자가 이 스트림 «앞»에 사람에게 답을 이미 보였다(예: goal loop 의 앞 iteration).
409
+ * 그러면 종결 신호 뒤 빈 턴은 이 스트림에 쓴 답이 없어도 재촉·`[NO FINAL SYNTHESIS]` 없이 빈 답으로 끝낸다.
410
+ * 비우면(기본) 종전대로 — 답이 «어디에도» 없을 때의 경고는 그대로 보인다. */
411
+ terminalPriorAnswerVisible?: boolean;
409
412
  /** Prompt-caching toggle. Honored by Anthropic (attaches
410
413
  * cache_control markers on system + tools + 2nd-to-last history
411
414
  * message) and OpenAI (passes stream_options.include_usage so
@@ -425,12 +428,9 @@ export interface LLMOpts {
425
428
  * every tool-loop turn gets a stable checkpoint identity without
426
429
  * forcing existing callers to thread the brand through. */
427
430
  turnUri?: TurnUri;
428
- /** Chat session id forwarded to the AskUserQuestion bridge when the
429
- * tool-loop self-dispatches a doom-loop intervention prompt. Lets
430
- * PWA / iOS peers receive the prompt natively via the ACP
431
- * `elanous/ask/*` envelope instead of the raw `[ASK USER]` text
432
- * fallback. Absent for CLI / startup-script callers without a chat
433
- * session context. */
431
+ /** Chat session id (context compaction · provider sticky routing).
432
+ * Absent for CLI / startup-script callers without a chat session
433
+ * context. */
434
434
  sessionId?: string;
435
435
  /** Server-side built-in tools the provider should advertise to the
436
436
  * model alongside the caller-supplied `tools`. Each provider has
@@ -1586,6 +1586,7 @@ type ResponsesInputItem =
1586
1586
  export interface MessagesToResponsesInputOpts {
1587
1587
  acceptToolImages?: boolean;
1588
1588
  acceptUserMessageImages?: boolean;
1589
+ onOrphanToolResult?: (callId: string) => void;
1589
1590
  }
1590
1591
 
1591
1592
  /** Exported for tests. Converts the unified LLMMessage shape into the
@@ -1603,21 +1604,23 @@ export function messagesToResponsesInput(
1603
1604
  // P-3 §6.9 — user-message image gating (default true; current gpt-5
1604
1605
  // family all vision-capable per allowlist).
1605
1606
  const acceptUserImages = opts.acceptUserMessageImages ?? true;
1606
- // First pass — collect every tool_result.tool_use_id that ever
1607
- // appears across the message list. Second pass below uses this set
1608
- // to drop orphan tool_use blocks (assistant invoked a tool but no
1609
- // matching tool_result followed). Orphans happen when the runtime
1607
+ // First pass — collect both sides of each tool round. Second pass
1608
+ // drops either side when its partner is absent from retained history.
1609
+ // Orphan tool_use blocks happen when the runtime
1610
1610
  // pre-empts dispatch (e.g. W5-G early force-synthesis fires
1611
1611
  // immediately after the assistant's tool_use stream completes but
1612
1612
  // before dispatchTool runs) — codex Responses API hard-rejects
1613
1613
  // function_call without function_call_output ("No tool output
1614
1614
  // found for function call X" → 400).
1615
1615
  const seenToolResultIds = new Set<string>();
1616
+ const seenToolUseIds = new Set<string>();
1616
1617
  for (const m of messages) {
1617
1618
  if (!Array.isArray(m.content)) continue;
1618
1619
  for (const b of m.content) {
1619
1620
  if (b && typeof b === 'object' && b.type === 'tool_result' && b.tool_use_id) {
1620
1621
  seenToolResultIds.add(b.tool_use_id);
1622
+ } else if (m.role === 'assistant' && b && typeof b === 'object' && b.type === 'tool_use' && b.id) {
1623
+ seenToolUseIds.add(b.id);
1621
1624
  }
1622
1625
  }
1623
1626
  }
@@ -1695,6 +1698,13 @@ export function messagesToResponsesInput(
1695
1698
  call_id: b.id,
1696
1699
  });
1697
1700
  } else if (b.type === 'tool_result') {
1701
+ // A restored/truncated session can retain an output after its
1702
+ // assistant call was removed. Codex rejects that wire item with
1703
+ // "No tool call found for function call output" on every retry.
1704
+ if (!seenToolUseIds.has(b.tool_use_id)) {
1705
+ opts.onOrphanToolResult?.(b.tool_use_id);
1706
+ continue;
1707
+ }
1698
1708
  // Image-pipeline P3 (2026-05-05) — when the caller opted in
1699
1709
  // (acceptToolImages, set by Codex provider for gpt-5 family)
1700
1710
  // AND the tool_result content carries image bytes, emit the
@@ -2195,6 +2205,31 @@ export async function* streamCodexResponsesEvents(
2195
2205
  // applies the same tool/SSE conventions
2196
2206
  const promptCache = extra.promptCache !== false;
2197
2207
  const cacheKey = promptCache ? computePromptCacheKey(body.model, body.instructions) : undefined;
2208
+ // TUI-OBS-400-SHAPE(#69) — 전송 객체·문자열을 한 번 만들어 둔다: 4xx 거절 때 «실제로 보낸 것» 의 모양을 잰다.
2209
+ const wireBody: Record<string, unknown> = {
2210
+ ...body,
2211
+ stream: true,
2212
+ // store=true wave: when caller opts in, the backend persists the
2213
+ // response and the next request can thread `previous_response_id`
2214
+ // to send only the delta input items. Default still false so any
2215
+ // caller that doesn't opt in (tests building bodies directly)
2216
+ // sees the legacy wire shape.
2217
+ store: body.store === true,
2218
+ ...(body.tool_choice ? { tool_choice: body.tool_choice } : {}),
2219
+ ...(body.previousResponseId ? { previous_response_id: body.previousResponseId } : {}),
2220
+ ...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
2221
+ // Reasoning opt-in (gpt-5 family). When the caller sets
2222
+ // body.reasoning we mirror it onto the wire AND append the
2223
+ // include directive that lets multi-turn requests thread the
2224
+ // model's encrypted reasoning context. Omit both when absent
2225
+ // so non-reasoning models / opt-out users see the legacy
2226
+ // wire shape unchanged.
2227
+ ...(body.reasoning ? {
2228
+ reasoning: body.reasoning,
2229
+ include: ['reasoning.encrypted_content'],
2230
+ } : {}),
2231
+ };
2232
+ const wireJson = JSON.stringify(wireBody);
2198
2233
  const response = await fetchApiWithRetry(
2199
2234
  url,
2200
2235
  {
@@ -2212,33 +2247,14 @@ export async function* streamCodexResponsesEvents(
2212
2247
  // Codex". See getCodexUserAgent (oauth/codex.ts).
2213
2248
  'User-Agent': getCodexUserAgent(),
2214
2249
  },
2215
- body: JSON.stringify({
2216
- ...body,
2217
- stream: true,
2218
- // store=true wave: when caller opts in, the backend persists the
2219
- // response and the next request can thread `previous_response_id`
2220
- // to send only the delta input items. Default still false so any
2221
- // caller that doesn't opt in (tests building bodies directly)
2222
- // sees the legacy wire shape.
2223
- store: body.store === true,
2224
- ...(body.tool_choice ? { tool_choice: body.tool_choice } : {}),
2225
- ...(body.previousResponseId ? { previous_response_id: body.previousResponseId } : {}),
2226
- ...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
2227
- // Reasoning opt-in (gpt-5 family). When the caller sets
2228
- // body.reasoning we mirror it onto the wire AND append the
2229
- // include directive that lets multi-turn requests thread the
2230
- // model's encrypted reasoning context. Omit both when absent
2231
- // so non-reasoning models / opt-out users see the legacy
2232
- // wire shape unchanged.
2233
- ...(body.reasoning ? {
2234
- reasoning: body.reasoning,
2235
- include: ['reasoning.encrypted_content'],
2236
- } : {}),
2237
- }),
2250
+ body: wireJson,
2238
2251
  signal,
2239
2252
  },
2240
2253
  retryOptsFor('codex', 'Codex API', extra.remainingFallbacks),
2241
- );
2254
+ ).catch((err: unknown) => {
2255
+ observeCodexRequestRejection(err, wireBody, wireJson);
2256
+ throw err;
2257
+ });
2242
2258
  debug.log('llm.response.status', `codex ${response.status}`, {
2243
2259
  url, status: response.status, elapsedMs: Date.now() - startedAt,
2244
2260
  });
@@ -2376,6 +2392,19 @@ export async function* streamCodexResponsesEvents(
2376
2392
  }
2377
2393
  }
2378
2394
 
2395
+ /** TUI-OBS-400-SHAPE(#69) — Codex 가 요청을 4xx(401·403·429 제외)로 거절하면 보낸 요청의 «모양» 만 남긴다.
2396
+ * Codex 400 은 `{"detail":"Bad Request"}` 뿐이라 크기·메시지 수·도구 짝 깨짐을 여기서 잰다.
2397
+ * ⛔ 본문·프롬프트·도구 인자/출력·키는 싣지 않는다(수·바이트·종류·call_id 해시 앞 8자만).
2398
+ * 관측 실패는 오류 계약을 바꾸지 않는다 — 호출부는 원래 오류를 그대로 던진다. */
2399
+ function observeCodexRequestRejection(err: unknown, wireBody: Record<string, unknown>, wireJson: string): void {
2400
+ if (!(err instanceof ApiHttpError) || !isShapeRelevantRejection(err.status)) return;
2401
+ try {
2402
+ debug.log('llm.codex', 'request-rejected-shape', summarizeCodexRequestShape(wireBody, wireJson, err.status, err.bodyText));
2403
+ } catch {
2404
+ // Observability must not interfere with the provider error contract.
2405
+ }
2406
+ }
2407
+
2379
2408
  function toolNames(raw: unknown): string[] | undefined {
2380
2409
  if (!Array.isArray(raw)) return undefined;
2381
2410
  return raw.map(item => {
@@ -3997,6 +4026,13 @@ export const PROVIDERS: Record<string, LLMProvider> = {
3997
4026
  streamChat: (messages, opts = {}) => makeCodexProvider({ provider: 'openai-codex' }).streamChat!(messages, opts),
3998
4027
  chat: (messages, opts = {}) => makeCodexProvider({ provider: 'openai-codex' }).chat!(messages, opts),
3999
4028
  },
4029
+ glm: {
4030
+ name: 'glm',
4031
+ get defaultModel() { return configuredZaiProvider().defaultModel; },
4032
+ available: () => zaiCodingPlanAvailable(),
4033
+ streamChat: (messages, opts = {}) => configuredZaiProvider().streamChat!(messages, opts),
4034
+ chat: (messages, opts = {}) => configuredZaiProvider().chat!(messages, opts),
4035
+ },
4000
4036
  anthropic: AnthropicProvider,
4001
4037
  local: LocalProvider,
4002
4038
  gemini: GeminiProvider,
@@ -4011,6 +4047,11 @@ export const PROVIDERS: Record<string, LLMProvider> = {
4011
4047
  bedrock: BedrockProvider, // 명시 선택 전용 — 자동 순서·폴백 체인에 «안» 넣는다(src/llm/bedrock-provider.ts)
4012
4048
  };
4013
4049
 
4050
+ function configuredZaiProvider(): LLMProvider {
4051
+ const { getUserConfig } = require('./user-config.js') as typeof import('./user-config.js');
4052
+ return makeZaiCodingPlanProvider(getUserConfig().llm);
4053
+ }
4054
+
4014
4055
  const AUTOMATIC_PROVIDER_ORDER = ['grok', 'anthropic', 'gemini', 'local'] as const;
4015
4056
  const PROVIDER_DECISION_ORDER = ['grok', 'anthropic', 'openai', 'gemini', 'local', 'openrouter'] as const;
4016
4057
  const SUBSCRIPTION_DECISION_ORDER = ['openai-codex', 'grok'] as const;
@@ -4400,6 +4441,16 @@ function providerByName(name: string): LLMProvider | undefined {
4400
4441
  return PROVIDERS[name] ?? automaticProviderCandidates().find((candidate) => candidate.name === name);
4401
4442
  }
4402
4443
 
4444
+ function firstAvailableFallbackProvider(attempted: ReadonlySet<string>, opts: LLMOpts): LLMProvider | undefined {
4445
+ // A candidate may lose its credential between chain enumeration and the
4446
+ // switch. Keep scanning the ordered chain instead of stopping at that slot.
4447
+ for (const name of remainingFallbackProviderNames(attempted, opts)) {
4448
+ const candidate = providerByName(name);
4449
+ if (candidate?.available()) return candidate;
4450
+ }
4451
+ return undefined;
4452
+ }
4453
+
4403
4454
  function finalizeStreamingProviderModel(provider: LLMProvider, model: string): { provider: LLMProvider; model: string } {
4404
4455
  if (!isKnownProviderName(provider.name)) return { provider, model };
4405
4456
 
@@ -4802,8 +4853,11 @@ export async function streamLLM(
4802
4853
 
4803
4854
  const err: any = consumed.error;
4804
4855
  if (err instanceof OverloadFailoverError && !opts.provider) {
4805
- const switched = providerByName('grok');
4806
- if (switched && !attemptedProviders.has(switched.name) && switched.available() && full.length === 0) {
4856
+ const switched = activeProvider.name === 'openai-codex'
4857
+ ? firstAvailableFallbackProvider(attemptedProviders, opts)
4858
+ : providerByName('grok');
4859
+ if (switched && !attemptedProviders.has(switched.name)
4860
+ && (activeProvider.name === 'openai-codex' || switched.available()) && full.length === 0) {
4807
4861
  debug.log('llm.router', 'overload-failover', {
4808
4862
  blockedProvider: activeProvider.name,
4809
4863
  fallbackProvider: switched.name,
@@ -4998,6 +5052,14 @@ export interface StreamWithToolsHandlers {
4998
5052
  * before the `onText('', enriched)` re-emit so presentation hosts can
4999
5053
  * keep the user answer to `answer` and send `supplement` to logs. */
5000
5054
  onFinalAnswerSupplement?(info: { answer: string; supplement: string; finalText: string }): void;
5055
+ /** 검증 보충 — final-answer supplement attachment point. Called after the
5056
+ * final answer is settled (and after any finalization-snapshot enrichment)
5057
+ * so callers can append verification-recency / loop-closure wording after
5058
+ * the final answer. Return a non-empty string to append it to the final
5059
+ * answer output (it will be joined after `finalText` and the combined
5060
+ * supplement surfaces via `onFinalAnswerSupplement`); return
5061
+ * undefined/null/empty to keep the prior behavior unchanged. */
5062
+ onAppendFinalAnswerSupplement?(req: FinalAnswerSupplementAttachmentRequest): string | null | undefined;
5001
5063
  /** Optional: notify when a tool_call is about to fire (for log line,
5002
5064
  * HUD segment, etc). */
5003
5065
  onToolCall?(call: { id: string; name: string; args: Record<string, unknown> }): void;
@@ -5856,44 +5918,15 @@ function buildAutoUndoRepairNotice(result: { output?: string; restoredId?: strin
5856
5918
  ].filter(Boolean).join('\n');
5857
5919
  }
5858
5920
 
5859
- // Fallback chat text used only when the AskUserQuestion bridge isn't
5860
- // reachable (no resolver, no sessionId, dispatch error). The marker
5861
- // `[ASK USER]` is preserved so `isUserInterventionRequired` downstream
5862
- // still skips force-synthesis — that gate predates the bridge route and
5863
- // other surfaces (TUI) still rely on the marker as a hard-stop signal.
5864
- function buildAutoUndoAskUserNotice(reason: DoomLoopReason, detail?: string | null): string {
5865
- const why = reason === 'plan-mode'
5866
- ? 'Auto-undo was skipped because plan mode is active.'
5867
- : reason === 'no-undo-available'
5868
- ? 'Auto-undo was skipped because no undo snapshot is available.'
5869
- : reason === 'undo-failed'
5870
- ? 'Auto-undo was attempted but the undo runtime failed.'
5871
- : 'Retry policy did not authorize auto-undo for this failure.';
5872
- return [
5873
- '[ASK USER] The same tool call kept failing — stopping to avoid wasting more turns.',
5874
- why,
5875
- detail ? `Detail: ${detail}` : '',
5876
- 'Reply with how to proceed (retry, change approach, or stop).',
5877
- ].filter(Boolean).join(' ');
5878
- }
5879
-
5880
- // ── Doom-loop → AskUserQuestion routing ─────────────────────────
5921
+ // ── Doom-loop self-heal ─────────────────────────────────────────
5881
5922
  //
5882
- // When the tool-loop trips the doom-loop gate (same tool error 3x) it
5883
- // previously emitted a raw `[ASK USER]` chat message describing what
5884
- // went wrong. With the AskUserQuestion bridge (PR #2611 PWA, #2612
5885
- // iOS, #2613 multi-option fan-out) live across PWA + iOS surfaces, we
5886
- // can self-dispatch a structured prompt instead so the user sees a
5887
- // modal with retry / different-approach / stop options rather than
5888
- // raw English instructions intended for the LLM.
5889
- //
5890
- // Falls back to the legacy `[ASK USER]` chat text when:
5891
- // - no `sessionId` plumbed (CLI / startup script callers),
5892
- // - no resolver wired (TUI-only or dispatch error), or
5893
- // - the bridge throws (peer disconnected, surface mismatch).
5894
- //
5895
- // The fallback marker `[ASK USER]` is preserved so the downstream
5896
- // `isUserInterventionRequired` gate continues to skip force-synthesis.
5923
+ // When the tool-loop trips the doom-loop gate (same tool error 3x) and
5924
+ // auto-undo cannot run, the loop heals itself instead of asking the user
5925
+ // (대표 10-17 — doom-loop is not a user-facing notice: in 40 h of runs it
5926
+ // tripped 3 times and the AskUser prompt was answered 0 times, each one
5927
+ // sitting 5 min until timeout). First trip → a «change approach» note for
5928
+ // the model and the turn continues; a second trip in the same turn → the
5929
+ // turn ends with a plain stop text (no question to the user).
5897
5930
 
5898
5931
  export type DoomLoopReason = 'plan-mode' | 'no-undo-available' | 'undo-failed' | 'policy';
5899
5932
 
@@ -5983,174 +6016,35 @@ function stringifyDoomFailureDetail(value: unknown): string {
5983
6016
  }
5984
6017
 
5985
6018
  export type DoomLoopRouteOutcome =
5986
- | { kind: 'retry'; interventionClass: DoomLoopInterventionClass }
5987
6019
  | { kind: 'guidance'; userMessage: string; interventionClass: DoomLoopInterventionClass }
5988
- | { kind: 'stop'; hardStopText: string; interventionClass: DoomLoopInterventionClass }
5989
- | { kind: 'fallback'; hardStopText: string; interventionClass: DoomLoopInterventionClass };
5990
-
5991
- export interface DoomLoopRouteOpts {
5992
- reason: DoomLoopReason;
5993
- /** Explicit evidence only. Omission means the intervention class is unknown. */
6020
+ | { kind: 'stop'; hardStopText: string; interventionClass: DoomLoopInterventionClass };
6021
+
6022
+ /** Visible text when the turn ends on a second doom trip. Deliberately not a
6023
+ * question and without the `[ASK USER]` marker — nobody is asked. */
6024
+ export const DOOM_LOOP_SELF_HEAL_STOP_TEXT =
6025
+ '같은 도구 호출이 방법을 바꾼 뒤에도 계속 실패해 이번 턴을 여기서 마칩니다.';
6026
+
6027
+ export interface DoomLoopSelfHealInput {
6028
+ /** 1 = first trip in this turn, 2+ = tripped again after the guidance. */
6029
+ attempt: number;
6030
+ tool?: string;
6031
+ fingerprint: string;
5994
6032
  interventionClass?: DoomLoopInterventionClass | null;
5995
- detail?: string | null;
5996
- doomWindow: string[];
5997
- sessionId?: string;
5998
- signal?: AbortSignal;
5999
- /** Override the AskUser gate timeout (ms). Defaults to
6000
- * DOOM_ASK_TIMEOUT_MS. Primarily a test seam. */
6001
- timeoutMs?: number;
6002
- }
6003
-
6004
- export function buildDoomLoopAskRequest(opts: DoomLoopRouteOpts): Record<string, unknown> {
6005
- const interventionClass = normalizeDoomLoopInterventionClass(opts.interventionClass);
6006
- const why = opts.reason === 'plan-mode'
6007
- ? 'plan mode is active so auto-undo was skipped'
6008
- : opts.reason === 'undo-failed'
6009
- ? `auto-undo was attempted but failed (${opts.detail ?? 'no detail'})`
6010
- : `auto-undo was not authorized by the retry policy (${opts.detail ?? 'no detail'})`;
6011
- const lastFingerprint = opts.doomWindow[opts.doomWindow.length - 1] ?? 'unknown';
6012
- return {
6013
- interventionClass,
6014
- questions: [
6015
- {
6016
- id: 'doom_loop_next_step',
6017
- header: 'Loop blocked',
6018
- question:
6019
- 'The same tool call kept failing after 3 attempts — '
6020
- + `${why}. How should I proceed?\n\nLast failure: ${lastFingerprint}`,
6021
- options: [
6022
- {
6023
- label: 'Retry once more',
6024
- description: 'Reset the retry tracker and let me try the same approach one more time.',
6025
- },
6026
- {
6027
- label: 'Different approach',
6028
- description: 'Type guidance in Other and I will follow it on the next turn.',
6029
- },
6030
- {
6031
- label: 'Stop here',
6032
- description: 'Halt this run. I will summarize what was tried and what was blocked.',
6033
- },
6034
- ],
6035
- includeOther: true,
6036
- },
6037
- ],
6038
- };
6039
- }
6040
-
6041
- export function interpretDoomLoopAskResult(
6042
- result: AskUserQuestionResult,
6043
- interventionClass: DoomLoopInterventionClass = 'unknown',
6044
- ): DoomLoopRouteOutcome {
6045
- if (result.cancelled === true) {
6046
- return {
6047
- kind: 'stop',
6048
- interventionClass,
6049
- hardStopText:
6050
- '[ASK USER] The same tool call kept failing and you cancelled the prompt — stopping this run.',
6051
- };
6052
- }
6053
- const answer = result.answers?.['doom_loop_next_step'];
6054
- const picked = Array.isArray(answer) ? (answer[0] ?? '') : (answer ?? '');
6055
- const otherText = result.otherText?.['doom_loop_next_step']?.trim();
6056
-
6057
- if (picked.startsWith('Retry')) {
6058
- return { kind: 'retry', interventionClass };
6059
- }
6060
- if (picked.startsWith('Different') || picked === 'Other') {
6061
- const guidance = otherText && otherText.length > 0
6062
- ? otherText
6063
- : 'Please try a different approach to the same goal — the previous tool call kept failing.';
6064
- return { kind: 'guidance', userMessage: guidance, interventionClass };
6065
- }
6066
- if (picked.startsWith('Stop')) {
6067
- return {
6068
- kind: 'stop',
6069
- interventionClass,
6070
- hardStopText: '[ASK USER] Stopped at your request after the repeated tool failure.',
6071
- };
6072
- }
6073
- return {
6074
- kind: 'stop',
6075
- interventionClass,
6076
- hardStopText:
6077
- '[ASK USER] The same tool call kept failing and the response was unrecognized — stopping this run.',
6078
- };
6079
6033
  }
6080
6034
 
6081
- // Doom-loop AskUser gate timeout — the doom-loop HITL prompt awaits an
6082
- // operator answer with NO timeout of its own (TUI modal `await modal.promise`
6083
- // and the ACP bridge `Promise.race([pushAskRequest, cancellation])` both lack
6084
- // a timer). In an autonomous drive there is no operator to answer, so the
6085
- // dispatch region freezes indefinitely — between tool-loop turns, invisible to
6086
- // the stream idle-watchdog (armed only inside the stream loop) and to the
6087
- // goal-loop (which awaits the hung iteration). This was the 16-minute freeze in
6088
- // RESEARCH-autonomous-runaway-discipline-2026-07-19 (R2). Bound the wait: after
6089
- // this budget, fall back to the same auto-undo notice used when no session /
6090
- // no cap-able peer is present. Generous enough that a present operator answers
6091
- // first; short enough that an absent one doesn't stall the run for long.
6092
- const DOOM_ASK_TIMEOUT_MS = 5 * 60_000;
6093
-
6094
- export async function routeDoomLoopToAskUser(opts: DoomLoopRouteOpts): Promise<DoomLoopRouteOutcome> {
6095
- const interventionClass = normalizeDoomLoopInterventionClass(opts.interventionClass);
6096
- if (!opts.sessionId) {
6035
+ export function decideDoomLoopSelfHeal(input: DoomLoopSelfHealInput): DoomLoopRouteOutcome {
6036
+ const interventionClass = normalizeDoomLoopInterventionClass(input.interventionClass);
6037
+ if (input.attempt <= 1) {
6097
6038
  return {
6098
- kind: 'fallback',
6039
+ kind: 'guidance',
6099
6040
  interventionClass,
6100
- hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
6101
- };
6102
- }
6103
- try {
6104
- const dispatchCtx: { sessionId: string; signal?: AbortSignal } = { sessionId: opts.sessionId };
6105
- if (opts.signal) dispatchCtx.signal = opts.signal;
6106
- const timeoutMs = opts.timeoutMs ?? DOOM_ASK_TIMEOUT_MS;
6107
- const TIMED_OUT = Symbol('doom-ask-timeout');
6108
- let askTimer: ReturnType<typeof setTimeout> | undefined;
6109
- const raced = await Promise.race([
6110
- dispatchAskUserQuestion(buildDoomLoopAskRequest(opts), dispatchCtx),
6111
- new Promise<typeof TIMED_OUT>((res) => {
6112
- askTimer = setTimeout(() => res(TIMED_OUT), timeoutMs);
6113
- }),
6114
- ]);
6115
- if (askTimer) clearTimeout(askTimer);
6116
- if (raced === TIMED_OUT) {
6117
- debug.log('llm.tool-loop.retry', 'doom-loop-ask-timeout', {
6118
- reason: opts.reason,
6119
- interventionClass,
6120
- timeoutMs,
6121
- }, { level: 'warn' });
6122
- return {
6123
- kind: 'fallback',
6124
- interventionClass,
6125
- hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
6126
- };
6127
- }
6128
- const r = raced;
6129
- if (!r.result) {
6130
- debug.log('llm.tool-loop.retry', 'doom-loop-ask-route-failed', {
6131
- error: r.output,
6132
- reason: opts.reason,
6133
- interventionClass,
6134
- }, { level: 'error' });
6135
- return {
6136
- kind: 'fallback',
6137
- interventionClass,
6138
- hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
6139
- };
6140
- }
6141
- return interpretDoomLoopAskResult(r.result, interventionClass);
6142
- } catch (err) {
6143
- debug.log('llm.tool-loop.retry', 'doom-loop-ask-route-failed', {
6144
- error: err instanceof Error ? err.message : String(err),
6145
- reason: opts.reason,
6146
- interventionClass,
6147
- }, { level: 'error' });
6148
- return {
6149
- kind: 'fallback',
6150
- interventionClass,
6151
- hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
6041
+ userMessage:
6042
+ `The same ${input.tool ?? 'tool'} call failed 3 times in a row (last failure: ${input.fingerprint}). `
6043
+ + 'Do not call it again with the same arguments. Change approach — a different tool or different '
6044
+ + 'arguments, or first verify the precondition that keeps failing — or state plainly what is blocked.',
6152
6045
  };
6153
6046
  }
6047
+ return { kind: 'stop', interventionClass, hardStopText: DOOM_LOOP_SELF_HEAL_STOP_TEXT };
6154
6048
  }
6155
6049
 
6156
6050
  interface AutoNarrowedInspection {
@@ -8164,9 +8058,10 @@ export function billingRouteForProvider(provider: string | undefined, model: str
8164
8058
  // local 은 호출이 «일어났다면» 언제나 local 이다 — 주소가 env 가 아니라 config rotation 에 있어도(자격 판정은 env 만 본다).
8165
8059
  if (name === 'local') return 'local';
8166
8060
  try {
8061
+ // A recorded rotation decision is the authoritative route for that Codex call;
8062
+ // auth-kind inference alone can otherwise relabel credit spend as subscription/API.
8063
+ if (name === 'openai-codex' && codexCreditSpendReason()) return 'credit';
8167
8064
  const auth = authKindForProvider(name, model);
8168
- // CREDIT-BILLING-LABEL(10-14) — codex 회전이 크레딧 소진을 정한 호출은 구독이 아니라 크레딧이다.
8169
- if (auth === 'oauth' && name === 'openai-codex' && codexCreditSpendReason()) return 'credit';
8170
8065
  return auth === 'oauth' ? 'subscription' : auth === 'local' ? 'local' : auth === 'apikey' ? 'api' : 'unknown';
8171
8066
  } catch {
8172
8067
  return 'unknown';
@@ -8196,6 +8091,41 @@ export function logAgentTurnUsage(model: string, usage: LLMUsage, providerNameOr
8196
8091
  } catch { /* usage observation must not change the turn */ }
8197
8092
  }
8198
8093
 
8094
+ /** 검증 보충 — final-answer supplement attachment point.
8095
+ * Request passed to `StreamWithToolsHandlers.onAppendFinalAnswerSupplement`
8096
+ * after the final answer is settled: `answer` is the visible answer text and
8097
+ * `finalText` is the current final answer output (including any
8098
+ * finalization-snapshot enrichment from the onFinalAnswerSupplement
8099
+ * foundation). */
8100
+ export interface FinalAnswerSupplementAttachmentRequest {
8101
+ answer: string;
8102
+ finalText: string;
8103
+ }
8104
+
8105
+ /** Callback type for the attachment point. Return a non-empty string to have
8106
+ * it appended after the final answer; undefined/null/empty keeps the final
8107
+ * answer output unchanged. */
8108
+ export type FinalAnswerSupplementAttachment = (
8109
+ req: FinalAnswerSupplementAttachmentRequest,
8110
+ ) => string | null | undefined;
8111
+
8112
+ /** Final-answer supplement attachment point: call the optional
8113
+ * `onAppendFinalAnswerSupplement` handler and return the final answer text
8114
+ * with its supplement appended (or the original text when the handler is
8115
+ * absent or yields nothing). No numeric thresholds are applied. */
8116
+ export function attachFinalAnswerSupplement(
8117
+ handlers: { onAppendFinalAnswerSupplement?: FinalAnswerSupplementAttachment },
8118
+ req: FinalAnswerSupplementAttachmentRequest,
8119
+ ): string {
8120
+ const provider = handlers.onAppendFinalAnswerSupplement;
8121
+ if (!provider) return req.finalText;
8122
+ const supplement = provider(req);
8123
+ if (typeof supplement !== 'string' || supplement.trim().length === 0) return req.finalText;
8124
+ const base = req.finalText;
8125
+ if (base.length === 0 || base.endsWith('\n')) return base + supplement.trim();
8126
+ return base + '\n\n' + supplement.trim();
8127
+ }
8128
+
8199
8129
  export async function streamLLMWithTools(
8200
8130
  messages: LLMMessage[],
8201
8131
  handlers: StreamWithToolsHandlers,
@@ -8519,6 +8449,8 @@ export async function streamLLMWithTools(
8519
8449
  // broken dispatch forever. Window=3 mirrors opencode's
8520
8450
  // session/processor.ts DOOM_LOOP_THRESHOLD.
8521
8451
  const toolErrorDoomTracker = new DoomLoopTracker(3);
8452
+ // Doom-loop self-heal attempts in this turn (guidance first, then stop).
8453
+ let doomSelfHealAttempts = 0;
8522
8454
  // A (RESEARCH-autonomous-runaway-discipline-2026-07-19 R1) — the error tracker
8523
8455
  // above only fires on *failing* calls; identical *successful* calls (the model
8524
8456
  // re-reading / re-grepping the same file over and over — the grep-thrash that
@@ -8604,6 +8536,8 @@ export async function streamLLMWithTools(
8604
8536
  }
8605
8537
  }
8606
8538
  let turnText = '';
8539
+ // TUI-TURN-NARRATION — 이 라운드에 받은 추론 요약 글자 수(내용은 남기지 않는다).
8540
+ let turnReasoningChars = 0;
8607
8541
  turnReasoningDetails = undefined;
8608
8542
  const pendingCalls: Array<{
8609
8543
  id: string;
@@ -8741,6 +8675,7 @@ export async function streamLLMWithTools(
8741
8675
  fullText = fullText.slice(0, fullText.length - turnText.length);
8742
8676
  turnText = '';
8743
8677
  }
8678
+ turnReasoningChars = 0;
8744
8679
  retryDisplay.arm();
8745
8680
  turnReasoningDetails = undefined;
8746
8681
  evCount = 0;
@@ -8769,8 +8704,11 @@ export async function streamLLMWithTools(
8769
8704
  } catch (err) {
8770
8705
  if (idleTimer) clearTimeout(idleTimer);
8771
8706
  if (err instanceof OverloadFailoverError && !opts.provider) {
8772
- const switched = providerByName('grok');
8773
- if (switched && !attemptedProviders.has(switched.name) && switched.available() && evCount === 0) {
8707
+ const switched = activeProvider.name === 'openai-codex'
8708
+ ? firstAvailableFallbackProvider(attemptedProviders, opts)
8709
+ : providerByName('grok');
8710
+ if (switched && !attemptedProviders.has(switched.name)
8711
+ && (activeProvider.name === 'openai-codex' || switched.available()) && evCount === 0) {
8774
8712
  debug.log('llm.router', 'overload-failover', {
8775
8713
  turn,
8776
8714
  blockedProvider: activeProvider.name,
@@ -8900,6 +8838,7 @@ export async function streamLLMWithTools(
8900
8838
  // OpenAI-compat `delta.reasoning_content` field — same
8901
8839
  // consumer-side semantics as summary_delta, no part index.
8902
8840
  // Callers that don't render reasoning skip silently.
8841
+ if (ev.kind !== 'summary_part_added') turnReasoningChars += ev.delta.length;
8903
8842
  if (ev.kind === 'summary_part_added') {
8904
8843
  handlers.onReasoning?.({
8905
8844
  kind: 'summary_part_added',
@@ -8976,7 +8915,7 @@ export async function streamLLMWithTools(
8976
8915
 
8977
8916
  // hang 진단 — for-await(SSE 스트림) 정상 종료 확정. 이 로그가 없으면 codex SSE 스트림 hang.
8978
8917
  emitRetryDisplayStep(retryDisplay.settle(turnText));
8979
- debug.log('llm.stream', 'consume-end', { turn, evCount, lastEvType, textChars: turnText.length, pendingCalls: pendingCalls.length });
8918
+ debug.log('llm.stream', 'consume-end', { turn, evCount, lastEvType, textChars: turnText.length, reasoningChars: turnReasoningChars, pendingCalls: pendingCalls.length });
8980
8919
  const turnInfo = {
8981
8920
  turn,
8982
8921
  durationMs: Date.now() - turnStartedAt,
@@ -9022,13 +8961,17 @@ export async function streamLLMWithTools(
9022
8961
  verificationLoopState,
9023
8962
  finalization,
9024
8963
  );
9025
- if (finalText !== visibleText) {
8964
+ // 검증 보충 — final-answer supplement attachment point: let the caller
8965
+ // append verification-recency / loop-closure wording after the final
8966
+ // answer (on top of the onFinalAnswerSupplement foundation from PR #27520).
8967
+ const attachedText = attachFinalAnswerSupplement(handlers, { answer: visibleText.trim(), finalText });
8968
+ if (attachedText !== visibleText) {
9026
8969
  const answer = visibleText.trim();
9027
- handlers.onFinalAnswerSupplement?.({ answer, supplement: finalText.slice(answer.length).trim(), finalText });
8970
+ handlers.onFinalAnswerSupplement?.({ answer, supplement: attachedText.slice(answer.length).trim(), finalText: attachedText });
9028
8971
  }
9029
- if (finalText !== fullText) handlers.onText('', finalText);
9030
- emitTurnComplete(finalText);
9031
- return finalText;
8972
+ if (attachedText !== fullText) handlers.onText('', attachedText);
8973
+ emitTurnComplete(attachedText);
8974
+ return attachedText;
9032
8975
  }
9033
8976
 
9034
8977
  // No tool calls + empty text = model stalled. Re-prompt up to
@@ -9037,12 +8980,15 @@ export async function streamLLMWithTools(
9037
8980
  if (pendingCalls.length === 0 && turnText.length === 0) {
9038
8981
  // TUI-GOAL-LOOP-FRICTION(#63) — 종결 신호(update_goal)를 이미 받았고 답도 이미 썼다 = 할 말이 없는 게 맞다.
9039
8982
  // 빈 턴을 «정체»로 보고 재촉·`[NO FINAL SYNTHESIS]` 를 붙이지 않고 그 답으로 끝낸다.
9040
- if (terminalSignalDispatched && lastToolRoundText.trim().length > 0) {
9041
- const answer = lastToolRoundText;
8983
+ // TUI-H1-GOALLOOP-EMPTY-TAIL — 답이 이 스트림 «앞»에 이미 보였어도 같다(opts.terminalPriorAnswerVisible —
8984
+ // 예: Bash → «끝» → 재주입 → update_goal 만 → 빈 턴). 이 스트림에 답이 없으면 빈 문자열로 끝내고 화면은
8985
+ // 건드리지 않는다(onText 생략 · emitTurnComplete 는 빈 답을 이력에 안 싣는다). 마감은 호출자(goal loop) 몫.
8986
+ if (terminalSignalDispatched && (lastToolRoundText.trim().length > 0 || opts.terminalPriorAnswerVisible === true)) {
8987
+ const answer = lastToolRoundText.trim().length > 0 ? lastToolRoundText : '';
9042
8988
  debug.log('goal.loop', 'empty-turn-after-terminal-signal', {
9043
8989
  turn, emptyRetries, answerChars: answer.length,
9044
8990
  }, { level: 'info' });
9045
- if (answer !== fullText) handlers.onText('', answer);
8991
+ if (answer.length > 0 && answer !== fullText) handlers.onText('', answer);
9046
8992
  emitTurnComplete(answer);
9047
8993
  return answer;
9048
8994
  }
@@ -10659,41 +10605,36 @@ export async function streamLLMWithTools(
10659
10605
  debug.log('llm.tool-loop.retry', 'doom-loop-detected', {
10660
10606
  turn, tool: doomToolName, window: doomWindow,
10661
10607
  }, { level: 'warn' });
10662
- const applyAskOutcome = async (reason: DoomLoopReason, detail: string | null) => {
10608
+ const applySelfHeal = (reason: DoomLoopReason, detail: string | null) => {
10663
10609
  const interventionClass = classifyDoomLoopIntervention({
10664
10610
  detail: [detail, doomFailureDetail].filter(Boolean).join('\n'), doomWindow,
10665
10611
  });
10666
- const askDispatchOpts: DoomLoopRouteOpts = {
10667
- reason, detail, doomWindow, interventionClass,
10668
- };
10669
- if (opts.sessionId) askDispatchOpts.sessionId = opts.sessionId;
10670
- if (opts.signal) askDispatchOpts.signal = opts.signal;
10671
- const outcome = await routeDoomLoopToAskUser(askDispatchOpts);
10672
- if (outcome.kind === 'retry') {
10673
- toolErrorDoomTracker.reset();
10674
- postToolResultUserNote =
10675
- 'The previous tool call kept failing 3 times in a row. Retry the same approach once more — the user reset the doom-loop tracker.';
10676
- debug.log('llm.tool-loop.retry', 'doom-loop-ask-retry', {
10677
- turn, reason, interventionClass: outcome.interventionClass,
10678
- });
10679
- } else if (outcome.kind === 'guidance') {
10612
+ doomSelfHealAttempts += 1;
10613
+ const fingerprint = doomWindow[doomWindow.length - 1] ?? 'unknown';
10614
+ const outcome = decideDoomLoopSelfHeal({
10615
+ attempt: doomSelfHealAttempts, tool: doomToolName, fingerprint, interventionClass,
10616
+ });
10617
+ debug.log('llm.tool-loop.retry', 'doom-loop-self-heal', {
10618
+ turn,
10619
+ tool: doomToolName,
10620
+ attempt: doomSelfHealAttempts,
10621
+ action: outcome.kind,
10622
+ fingerprint,
10623
+ reason,
10624
+ interventionClass: outcome.interventionClass,
10625
+ }, { level: 'warn' });
10626
+ if (outcome.kind === 'guidance') {
10680
10627
  toolErrorDoomTracker.reset();
10681
10628
  postToolResultUserNote = outcome.userMessage;
10682
- debug.log('llm.tool-loop.retry', 'doom-loop-ask-guidance', {
10683
- turn, reason, interventionClass: outcome.interventionClass,
10684
- });
10685
10629
  } else {
10686
10630
  hardStopText = outcome.hardStopText;
10687
- debug.log('llm.tool-loop.retry', outcome.kind === 'fallback' ? 'doom-loop-ask-fallback' : 'doom-loop-ask-stop', {
10688
- turn, reason, interventionClass: outcome.interventionClass, window: doomWindow,
10689
- });
10690
10631
  }
10691
10632
  };
10692
10633
  if (retryDecision.action === 'auto-undo') {
10693
10634
  if (isPlanModeActive()) {
10694
- await applyAskOutcome('plan-mode', retryDecision.reason);
10635
+ applySelfHeal('plan-mode', retryDecision.reason);
10695
10636
  } else if (listSnapshots().length === 0) {
10696
- await applyAskOutcome('no-undo-available', 'UndoTurn: no snapshots available');
10637
+ applySelfHeal('no-undo-available', 'UndoTurn: no snapshots available');
10697
10638
  } else {
10698
10639
  try {
10699
10640
  const undoResult = await undoTurnRuntime.run({}, { surface: 'tui' });
@@ -10707,11 +10648,11 @@ export async function streamLLMWithTools(
10707
10648
  window: doomWindow,
10708
10649
  });
10709
10650
  } catch (err) {
10710
- await applyAskOutcome('undo-failed', err instanceof Error ? err.message : String(err));
10651
+ applySelfHeal('undo-failed', err instanceof Error ? err.message : String(err));
10711
10652
  }
10712
10653
  }
10713
10654
  } else {
10714
- await applyAskOutcome('policy', retryDecision.reason);
10655
+ applySelfHeal('policy', retryDecision.reason);
10715
10656
  }
10716
10657
  }
10717
10658
  if (executionDoomDetectedThisTurn && !hardStopText) {
@@ -10911,8 +10852,8 @@ export async function streamLLMWithTools(
10911
10852
  if (postToolResultUserNote) {
10912
10853
  // Appended after the tool_result user turn so the wire order is
10913
10854
  // assistant(tool_use) → user(tool_result) → user(intervention).
10914
- // This is the "retry" or "guidance" branch of the doom-loop ASK
10915
- // route — see routeDoomLoopToAskUser above.
10855
+ // Also carries the doom-loop self-heal guidance — see
10856
+ // decideDoomLoopSelfHeal above.
10916
10857
  history.push({ role: LOOP_SELF_NOTE_ROLE, content: postToolResultUserNote });
10917
10858
  }
10918
10859
  // 신호뿐인 턴 · 섞인 턴(정상 디스패치 · 부분 거부 · 통째 거부의 수신 확인) 모두 — 종결 신호가 이 턴에 «받아들여졌다».
@@ -11590,6 +11531,10 @@ function makeCodexProvider(cfg: UCLLMConfig): LLMProvider {
11590
11531
  const { instructions, input } = messagesToResponsesInput(messages, {
11591
11532
  acceptToolImages: codexAcceptToolImages,
11592
11533
  acceptUserMessageImages: codexAcceptUserImages,
11534
+ onOrphanToolResult: (callId) => {
11535
+ try { debug.log('llm.codex', 'orphan-tool-output-dropped', { callId }); }
11536
+ catch { /* observation must not block the request */ }
11537
+ },
11593
11538
  });
11594
11539
  const tools = toCodexResponsesTools(opts.tools, opts.serverTools);
11595
11540
  // Codex backend rejects max_output_tokens + temperature — omit.