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
@@ -6,13 +6,14 @@ import { constants, copyFileSync, existsSync, readFileSync, renameSync, writeFil
6
6
  import { join } from 'node:path';
7
7
  import { debug } from '../../src/debug/log.js';
8
8
  import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
9
- import { lastJsonObject, runGraph, type GraphRunState } from '../../src/graph-runner/runner.js';
9
+ import { lastJsonObject, runGraph, verifyReleaseCommandRoot, type GraphRunState } from '../../src/graph-runner/runner.js';
10
10
  import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
11
11
  import { releaseRunUniverse } from './release-universe.js';
12
12
  import { isReleaseVersion } from './release-version.js';
13
13
  import { changedFilesBetween, clearPartialPlan, planPartialRegate, writePartialPlan } from './gate-partial.js';
14
- import { gitClosureTree, testsReachingChanged, type ClosureTree } from './gate-closure.js';
15
- import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeWaiver, type AcceptedRegression } from './resume.js';
14
+ import { gitClosureTree, testsReachingChanged, TRACEABLE_RELEASE_JSON, type ClosureTree } from './gate-closure.js';
15
+ import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeGatePodPool, releaseResumeWaiver, type AcceptedRegression } from './resume.js';
16
+ import { reserveReleaseResumeAttempt } from './resume-cap.js';
16
17
 
17
18
  const GRAPH = join(import.meta.dir, '../../graphs/release/release-loop.yaml');
18
19
 
@@ -33,6 +34,20 @@ export interface ResumeReleaseDeps {
33
34
  ledgerRoot?: string;
34
35
  /** GATE-REUSE-BY-DIFF: the tip tree for the import closure — default read from git objects of the tip commit. */
35
36
  closureTree?: (commit: string) => ClosureTree;
37
+ /** Source observation before the first resumed node. */
38
+ onSource?: (line: string) => void;
39
+ }
40
+
41
+ export interface ResumeReleaseOptions {
42
+ runId: string; from: string; partial?: boolean; waive?: string; reason?: string;
43
+ acceptedRegressions?: AcceptedRegression[]; gateExecutor?: string; gateHost?: string; gatePodPool?: string;
44
+ commandRoot?: string;
45
+ }
46
+
47
+ export interface ResumeReleasePlan {
48
+ runId: string; version: string; fromNode: string; commandRoot: string; tip: TipRefresh;
49
+ partial: PartialOutcome; gatePlan: { mode: 'not-run' | 'partial' | 'full'; reason?: string };
50
+ nextAttempt: number; attemptLimit: 2; preflight: 'passed';
36
51
  }
37
52
 
38
53
  /** CLI entry files: a production file that only names one (help text, a goal's command line) does not run it. */
@@ -66,6 +81,10 @@ function safeRunId(runId: string): string {
66
81
 
67
82
  /** Point the saved version-release output at the current release/<v> tip (fast-forward of the recorded commit only). */
68
83
  export function refreshReleaseBranchTip(runId: string, deps: ResumeReleaseDeps = {}, from?: string, waiverCommit?: string): TipRefresh {
84
+ return refreshReleaseBranchTipInternal(runId, deps, from, waiverCommit, false);
85
+ }
86
+
87
+ function refreshReleaseBranchTipInternal(runId: string, deps: ResumeReleaseDeps, from: string | undefined, waiverCommit: string | undefined, dryRun: boolean): TipRefresh {
69
88
  const root = deps.root ?? effectiveInstanceRoot();
70
89
  const statePath = join(root, 'graph-runs', 'release-loop', `${safeRunId(runId)}.json`);
71
90
  const state = JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState;
@@ -89,8 +108,14 @@ export function refreshReleaseBranchTip(runId: string, deps: ResumeReleaseDeps =
89
108
  const git = deps.git ?? gitRunner(deps.repo ?? process.cwd());
90
109
  const advertised = git(['ls-remote', '--heads', 'origin', `refs/heads/${branch}`]).split(/\s+/)[0] ?? '';
91
110
  if (!/^[0-9a-f]{40}$/i.test(advertised)) throw new Error(`${branch} is not on origin — this run was not cut as a release branch`);
92
- git(['fetch', 'origin', `+refs/heads/${branch}:refs/remotes/origin/${branch}`]);
93
- const to = git(['rev-parse', '--verify', `refs/remotes/origin/${branch}^{commit}`]);
111
+ let to: string;
112
+ if (dryRun) {
113
+ // Use the advertised object id directly: a preflight must not create/update local remote-tracking refs.
114
+ to = advertised;
115
+ } else {
116
+ git(['fetch', 'origin', `+refs/heads/${branch}:refs/remotes/origin/${branch}`]);
117
+ to = git(['rev-parse', '--verify', `refs/remotes/origin/${branch}^{commit}`]);
118
+ }
94
119
  if (waiverCommit && (recorded.toLowerCase() !== waiverCommit.toLowerCase() || to.toLowerCase() !== waiverCommit.toLowerCase() || advertised.toLowerCase() !== waiverCommit.toLowerCase())) {
95
120
  throw new Error('release branch moved — re-gate the new tip before waiving a node');
96
121
  }
@@ -114,6 +139,7 @@ export function refreshReleaseBranchTip(runId: string, deps: ResumeReleaseDeps =
114
139
  }
115
140
  const stamp = (deps.now?.() ?? new Date()).toISOString().replace(/[:.]/g, '-');
116
141
  const backup = `${statePath}.before-tip-${stamp}-${process.pid}-${to.slice(0, 12)}.bak`;
142
+ if (dryRun) return { version, branch, from: recorded, to, changed: true, statePath };
117
143
  // Exclusive: a retry never overwrites an earlier backup.
118
144
  copyFileSync(statePath, backup, constants.COPYFILE_EXCL);
119
145
  const refreshed = { ...output, commit: to, refreshedFrom: recorded };
@@ -134,10 +160,10 @@ export type PartialOutcome = { requested: false }
134
160
 
135
161
  /** Build (or clear) the partial re-gate plan for the new tip. Fail-closed: any doubt leaves a full gate.
136
162
  * GATE-REUSE-BY-DIFF: `--from gate` on a moved tip plans by default (`partial: undefined`); `partial: false` opts out. */
137
- function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean }, deps: ResumeReleaseDeps): PartialOutcome {
163
+ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean }, deps: ResumeReleaseDeps, dryRun = false): PartialOutcome {
138
164
  const root = deps.root ?? effectiveInstanceRoot();
139
165
  // Any resume starts from no plan: one without a partial plan (from whatever node) never inherits an older plan.
140
- clearPartialPlan(root, tip.version);
166
+ if (!dryRun) clearPartialPlan(root, tip.version);
141
167
  const auto = opts.partial === undefined;
142
168
  // The current graph checks public export before gate. A moved tip must resume there, so its gate still needs
143
169
  // the diff plan; in older saved graphs export-check followed gate and cannot consume one.
@@ -182,6 +208,18 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
182
208
  catch (error) { return fallback(`tip tree unreadable: ${String(error instanceof Error ? error.message : error).slice(0, 200)}`); }
183
209
  const tracked = new Set(tree.files);
184
210
  const tests = tree.files.filter((file) => GATE_TEST.test(file));
211
+ if (changed.includes(TRACEABLE_RELEASE_JSON)) {
212
+ // The one JSON exception is safe only while both the production reader and a test name this exact file at the tip.
213
+ // A renamed, computed or unreadable reader returns to the full gate instead of trusting a stale dependency map.
214
+ const reader = tree.read('scripts/release-loop/known-issues-node.ts');
215
+ if (!reader || !/readFileSync\(join\(import\.meta\.dir,\s*['"]known-issues-0\.2\.33-approved\.json['"]\)/.test(reader)) {
216
+ return fallback('known-issues JSON reader not statically verified — full gate');
217
+ }
218
+ const readerClosure = testsReachingChanged(tree, ['scripts/release-loop/known-issues-node.ts'], tests, { cliEntries: CLI_ENTRIES });
219
+ if (!readerClosure.ok || readerClosure.reached === 0) return fallback('known-issues JSON production reader reaches no verified test — full gate');
220
+ const jsonClosure = testsReachingChanged(tree, [TRACEABLE_RELEASE_JSON], tests, { cliEntries: CLI_ENTRIES });
221
+ if (!jsonClosure.ok || jsonClosure.reached === 0) return fallback('known-issues JSON reaches no verified test — full gate');
222
+ }
185
223
  const planned = planPartialRegate({ version: tip.version, priorCommit: tip.from, forCommit: tip.to, changedFiles: changed,
186
224
  priorFailures: prior.failures as string[], priorErrors: (prior.errors ?? []) as string[],
187
225
  existsAtTip: (file) => tracked.has(file),
@@ -201,9 +239,9 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
201
239
  }
202
240
  if (!clean) return fallback(`no clean gate verdict for ${tip.from.slice(0, 12)} — full gate`);
203
241
  }
204
- const path = writePartialPlan(root, planned.plan);
242
+ const path = dryRun ? undefined : writePartialPlan(root, planned.plan);
205
243
  debug.log('release-loop.resume', 'partial-planned', { version: tip.version, priorCommit: tip.from, commit: tip.to, files: planned.plan.files.length,
206
- tests: tests.length, auto, path, ...(planned.closure ? { reached: planned.closure.reached, opaque: planned.closure.opaque } : {}) });
244
+ tests: tests.length, auto, ...(path ? { path } : {}), dryRun, ...(planned.closure ? { reached: planned.closure.reached, opaque: planned.closure.opaque } : {}) });
207
245
  return { requested: true, applied: true, files: planned.plan.files.length, priorCommit: tip.from,
208
246
  ...(auto ? { auto: true as const } : {}), ...(planned.closure ? { closure: planned.closure } : {}) };
209
247
  }
@@ -217,34 +255,87 @@ function savedGraphPath(statePath: string): string | undefined {
217
255
  }
218
256
 
219
257
  /** Refresh the branch tip, then restart the failed run at `from` with the saved graph snapshot. */
220
- export async function resumeReleaseRun(opts: { runId: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: AcceptedRegression[]; gateExecutor?: string; gateHost?: string }, deps: ResumeReleaseDeps = {}): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
258
+ export async function resumeReleaseRun(opts: ResumeReleaseOptions, deps: ResumeReleaseDeps = {}): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
221
259
  // The lock root is the OP seat's (opSeatLockRoot), never the injected ledger root: a different `deps.root` must not
222
260
  // move this run onto a separate lock inode from the steward resync and the unattended release.
223
261
  return withOpSeatFlock(() => resumeReleaseRunLocked(opts, deps));
224
262
  }
225
263
 
226
- async function resumeReleaseRunLocked(opts: { runId: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: AcceptedRegression[]; gateExecutor?: string; gateHost?: string }, deps: ResumeReleaseDeps): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
264
+ /** Validate a resume without changing the saved run, attempt ledger, or partial-gate plan. */
265
+ export async function planResumeReleaseRun(opts: ResumeReleaseOptions, deps: ResumeReleaseDeps = {}): Promise<ResumeReleasePlan> {
266
+ return withOpSeatFlock(() => planResumeReleaseRunLocked(opts, deps));
267
+ }
268
+
269
+ async function planResumeReleaseRunLocked(opts: ResumeReleaseOptions, deps: ResumeReleaseDeps): Promise<ResumeReleasePlan> {
270
+ if (opts.from === 'version-release') throw new Error('--from version-release would cut again — resume at a later node');
271
+ deps = { ...deps, root: releaseRunUniverse({ root: deps.root }) };
272
+ const statePath = join(deps.root!, 'graph-runs', 'release-loop', `${safeRunId(opts.runId)}.json`);
273
+ const savedRun = JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState;
274
+ if (savedRun.graphId !== 'release-loop' || savedRun.runId !== opts.runId) throw new Error(`run identity mismatch: ${statePath}`);
275
+ if (opts.gateHost !== undefined && opts.gateExecutor === undefined) throw new Error('--gate-host requires --gate-executor host');
276
+ const hasOverrides = opts.waive !== undefined || opts.reason !== undefined || opts.acceptedRegressions !== undefined
277
+ || opts.gateExecutor !== undefined || opts.gatePodPool !== undefined;
278
+ const original = hasOverrides ? savedRun : undefined;
279
+ if (original && opts.gateExecutor !== undefined) releaseResumeGateExecutor(original, { from: opts.from, executor: opts.gateExecutor, host: opts.gateHost });
280
+ if (original && opts.gatePodPool !== undefined) releaseResumeGatePodPool(original, { from: opts.from, pool: opts.gatePodPool });
281
+ const waiver = original && (opts.waive !== undefined || opts.reason !== undefined) ? releaseResumeWaiver(original, opts) : undefined;
282
+ if (original && opts.acceptedRegressions !== undefined && !waiver)
283
+ releaseResumeAcceptedRegressions(original, opts.acceptedRegressions, opts.from);
284
+ const attempt = reserveReleaseResumeAttempt(savedRun, deps.root!, { now: deps.now, checkOnly: true, noDecision: true });
285
+ let waiverCommit: string | undefined;
286
+ if (waiver) {
287
+ const output = lastJsonObject(savedRun.nodes.find((node) => node.nodeId === 'version-release')?.output);
288
+ const version = output?.version, recorded = output?.commit;
289
+ if (typeof version !== 'string' || typeof recorded !== 'string' || !isReleaseVersion(version) || !/^[0-9a-f]{40}$/i.test(recorded)) throw new Error('release waiver requires a recorded release commit');
290
+ const git = deps.git ?? gitRunner(deps.repo ?? process.cwd());
291
+ const branch = `release/${version}`;
292
+ const advertised = git(['ls-remote', '--heads', 'origin', `refs/heads/${branch}`]).split(/\s+/)[0];
293
+ if (advertised?.toLowerCase() !== recorded.toLowerCase()) throw new Error('release branch moved — re-gate the new tip before waiving a node');
294
+ waiverCommit = recorded;
295
+ }
296
+ const tip = refreshReleaseBranchTipInternal(opts.runId, deps, opts.from, waiverCommit, true);
297
+ const commandRoot = verifyReleaseCommandRoot(opts.commandRoot ?? process.cwd(), tip.to, deps.git);
298
+ const partial = preparePartial(tip, opts, deps, true);
299
+ const fromIndex = savedRun.path.indexOf(opts.from);
300
+ const gateIndex = savedRun.path.indexOf('gate');
301
+ const gateWillRun = fromIndex >= 0 && gateIndex >= fromIndex;
302
+ const gatePlan = !gateWillRun ? { mode: 'not-run' as const }
303
+ : partial.requested && partial.applied ? { mode: 'partial' as const }
304
+ : { mode: 'full' as const, reason: partial.requested ? partial.reason : opts.partial === false ? 'partial recheck disabled' : 'no partial plan applies' };
305
+ return { runId: opts.runId, version: tip.version, fromNode: opts.from, commandRoot, tip, partial,
306
+ gatePlan, nextAttempt: attempt.attempt, attemptLimit: 2, preflight: 'passed' };
307
+ }
308
+
309
+ async function resumeReleaseRunLocked(opts: ResumeReleaseOptions, deps: ResumeReleaseDeps): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
227
310
  if (opts.from === 'version-release') throw new Error('--from version-release would cut again — resume at a later node');
228
311
  // RELEASE-LEDGER-UNIVERSE: decide the universe once; the run lookup and every resumed node use it.
229
312
  deps = { ...deps, root: releaseRunUniverse({ root: deps.root }) };
230
313
  const statePath = join(deps.root!, 'graph-runs', 'release-loop', `${safeRunId(opts.runId)}.json`);
314
+ const savedRun = JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState;
231
315
  let waiverCommit: string | undefined;
232
316
  if (opts.gateHost !== undefined && opts.gateExecutor === undefined) throw new Error('--gate-host requires --gate-executor host');
233
- const original = opts.waive !== undefined || opts.reason !== undefined || opts.acceptedRegressions !== undefined || opts.gateExecutor !== undefined
234
- ? JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState : undefined;
317
+ const original = opts.waive !== undefined || opts.reason !== undefined || opts.acceptedRegressions !== undefined || opts.gateExecutor !== undefined || opts.gatePodPool !== undefined
318
+ ? savedRun : undefined;
235
319
  // GATE-HOST-EXECUTOR: checked before the tip refresh writes anything; the runner checks it again under the resume lock.
236
320
  const gateExecutor = original && opts.gateExecutor !== undefined
237
321
  ? releaseResumeGateExecutor(original, { from: opts.from, executor: opts.gateExecutor, host: opts.gateHost }) : undefined;
322
+ const gatePodPool = original && opts.gatePodPool !== undefined
323
+ ? releaseResumeGatePodPool(original, { from: opts.from, pool: opts.gatePodPool }) : undefined;
238
324
  if (gateExecutor) debug.log('release-loop.resume', 'gate-executor', { runId: opts.runId, from: opts.from, executor: gateExecutor.set.gateExecutor, host: gateExecutor.set.gateRemote ?? null, previous: gateExecutor.previous });
325
+ if (gatePodPool) debug.log('release-loop.resume', 'gate-pod-pool', {
326
+ runId: opts.runId, from: opts.from, pool: gatePodPool.set.gatePodPool, previous: gatePodPool.previous,
327
+ });
239
328
  const waiver = original && (opts.waive !== undefined || opts.reason !== undefined)
240
329
  ? releaseResumeWaiver(original, opts) : undefined;
241
330
  if (waiver) debug.log('release-loop.resume', 'waiver', { runId: opts.runId, node: waiver.nodeId, reason: waiver.reason, unmeasured: waiver.unmeasured ?? null });
242
331
  const acceptedRegressions = original && opts.acceptedRegressions !== undefined && !waiver
243
332
  ? releaseResumeAcceptedRegressions(original, opts.acceptedRegressions, opts.from) : undefined;
333
+ if (savedRun.graphId !== 'release-loop' || savedRun.runId !== opts.runId) throw new Error(`run identity mismatch: ${statePath}`);
334
+ // Validate request arguments before the cap, then block the third attempt before tip refresh.
335
+ reserveReleaseResumeAttempt(savedRun, deps.root!, { now: deps.now, checkOnly: true });
244
336
  // A waived verdict may reuse its original commit. A moved tip still requires a full re-gate.
245
337
  if (waiver) {
246
- const saved = JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState;
247
- const versionRecord = saved.nodes.find((node) => node.nodeId === 'version-release');
338
+ const versionRecord = savedRun.nodes.find((node) => node.nodeId === 'version-release');
248
339
  const output = lastJsonObject(versionRecord?.output);
249
340
  const version = output?.version;
250
341
  const recorded = output?.commit;
@@ -257,13 +348,21 @@ async function resumeReleaseRunLocked(opts: { runId: string; from: string; parti
257
348
  }
258
349
  // Check the refreshed tip before refresh writes a new version-release record or backup.
259
350
  const tip = refreshReleaseBranchTip(opts.runId, deps, opts.from, waiverCommit);
351
+ const commandRoot = verifyReleaseCommandRoot(opts.commandRoot ?? process.cwd(), tip.to, deps.git);
260
352
  const partial = preparePartial(tip, opts, deps);
353
+ // A failed preflight does not consume one of the two release resume attempts.
354
+ const attempt = reserveReleaseResumeAttempt(savedRun, deps.root!, { now: deps.now });
355
+ debug.log('release-loop.resume', 'attempt', { runId: opts.runId, attempt: attempt.attempt, limit: 2, ledger: attempt.path });
261
356
  // Resume the graph at the path it was started from (its snapshot is used); only tests inject another path.
262
357
  const graphPath = deps.graphPath ?? savedGraphPath(tip.statePath) ?? GRAPH;
358
+ const savedSource = JSON.parse(readFileSync(tip.statePath, 'utf8')) as GraphRunState;
359
+ deps.onSource?.(`레시피 출처: graph=${graphPath} · graph sha=${savedSource.graphSnapshot?.graphSha?.slice(0, 12) ?? 'legacy'} · recipes sha=${savedSource.graphSnapshot?.recipesSha?.slice(0, 12) ?? 'legacy'} · command-root=${commandRoot} · 컷 tip=${tip.to.slice(0, 12)}`);
263
360
  const state = await (deps.graph ?? runGraph)(graphPath, { resumeRunId: opts.runId, fromNodeId: opts.from, pinChildUniverse: true,
361
+ releaseCommandSource: { root: commandRoot, cutTip: tip.to, ...(deps.git ? { git: deps.git } : {}) },
264
362
  ...(waiver ? { releaseWaiver: { ...waiver, requestedRegressions: opts.acceptedRegressions ?? [] } } : {}),
265
363
  ...(acceptedRegressions ? { releaseAcceptedRegressions: { requested: opts.acceptedRegressions!, acceptedRegressions } } : {}),
266
364
  ...(gateExecutor ? { releaseGateExecutor: { executor: gateExecutor.set.gateExecutor, ...(opts.gateHost !== undefined ? { host: opts.gateHost } : {}) } } : {}),
365
+ ...(gatePodPool ? { releaseGatePodPool: gatePodPool.set.gatePodPool } : {}),
267
366
  deps: { root: deps.root, ...(deps.runBash ? { runBash: deps.runBash } : {}) } });
268
367
  return { tip, partial, state };
269
368
  }
@@ -137,6 +137,28 @@ export interface GateExecutorOverride {
137
137
  previous: { gateExecutor: unknown; gateRemote: unknown };
138
138
  }
139
139
 
140
+ /** RESUME-GATE-POOL-OVERRIDE — replace the saved pool for a gate that will be re-run. */
141
+ export interface GatePodPoolOverride {
142
+ kind: 'gate-pod-pool';
143
+ at: string;
144
+ from: string;
145
+ set: { gatePodPool: string };
146
+ previous: { gatePodPool: unknown };
147
+ }
148
+
149
+ export function releaseResumeGatePodPool(state: GraphRunState, opts: { from: string; pool: unknown; at?: string }): GatePodPoolOverride {
150
+ const input = state.input;
151
+ if (!input || typeof input !== 'object' || Array.isArray(input) || typeof (input as { version?: unknown }).version !== 'string') throw new Error('release run has no input');
152
+ if (typeof opts.pool !== 'string' || !opts.pool.trim()) throw new Error('--gate-pod-pool must not be empty');
153
+ const start = state.path.indexOf(opts.from);
154
+ if (start < 0) throw new Error(`--from ${opts.from} is not a node on the saved path`);
155
+ const gate = state.path.indexOf('gate');
156
+ if (gate >= 0 && start > gate) throw new Error('--gate-pod-pool needs a resume that re-runs gate (--from gate or earlier)');
157
+ const saved = input as { gatePodPool?: unknown };
158
+ return { kind: 'gate-pod-pool', at: opts.at ?? new Date().toISOString(), from: opts.from,
159
+ set: { gatePodPool: opts.pool.trim() }, previous: { gatePodPool: saved.gatePodPool ?? null } };
160
+ }
161
+
140
162
  /**
141
163
  * Switch the gate executor of a resumed release run. Not a waiver: the gate node runs again (the restart must be at or
142
164
  * before gate) and produces a normal verdict; only where its sweep runs changes.
@@ -156,7 +178,8 @@ export function releaseResumeGateExecutor(state: GraphRunState, opts: { from: st
156
178
  // A restart after gate keeps the recorded verdict — switching its executor there would record a choice nothing used.
157
179
  if (gate >= 0 && start > gate) throw new Error('--gate-executor needs a resume that re-runs gate (--from gate or earlier)');
158
180
  // Back to pod: restore the gateRemote the run started with (an earlier host override replaced it).
159
- const firstHost = choice.executor === 'pod' ? state.inputOverrides?.find((item) => item.kind === 'gate-executor' && item.set.gateRemote !== undefined) : undefined;
181
+ const firstHost = choice.executor === 'pod' ? state.inputOverrides?.find((item): item is GateExecutorOverride =>
182
+ item.kind === 'gate-executor' && item.set.gateRemote !== undefined) : undefined;
160
183
  const restored = firstHost ? firstHost.previous.gateRemote : undefined;
161
184
  return {
162
185
  kind: 'gate-executor', at: opts.at ?? new Date().toISOString(), from: opts.from,
@@ -16,7 +16,7 @@ import { SPAWN_SYNC_MAX_BUFFER } from '../../src/util/spawn-sync-output.js';
16
16
  import { copyFileSync, existsSync, mkdtempSync, openSync, symlinkSync } from 'node:fs';
17
17
  import { tmpdir } from 'node:os';
18
18
  import { basename, join, resolve } from 'node:path';
19
- import { parseTuiRegress, regressWarning, tuiChecks, tuiVerdict, type TuiCheck, type TuiRegress } from './tui-node-checks';
19
+ import { parseTuiRegress, regressWarning, tuiChecks, tuiVerdict, validatedTuiRegress, type TuiCheck, type TuiRegress } from './tui-node-checks';
20
20
 
21
21
  const log = (msg: string) => process.stderr.write(`[tui-node] ${msg}\n`);
22
22
  const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
@@ -83,7 +83,13 @@ export function measureTuiRegress(worktree: string, runner: typeof spawnSync = s
83
83
  export function tuiNodeOutput(commit: string, attempts: Array<{ checks: TuiCheck[]; png?: string }>, regress: TuiRegress, failure?: string) {
84
84
  const last = attempts.at(-1);
85
85
  const verdict = !last ? 'error' : tuiVerdict(last.checks) === 'fail' ? 'fail' : attempts.length > 1 ? 'flaky' : 'pass';
86
- return { verdict, commit, attempts: attempts.length, checks: last?.checks ?? [], png: last?.png, regress, ...(failure ? { error: failure } : {}) };
86
+ const measured = validatedTuiRegress(regress);
87
+ const regressSummary = 'unmeasured' in measured
88
+ ? `regress unmeasured: ${measured.unmeasured}`
89
+ : `regress ${measured.pass} pass / ${measured.fail} fail${measured.fail ? ` (${measured.results.filter((r) => !r.ok).map((r) => r.id).join(',')})` : ''}`;
90
+ const checks = last?.checks ?? [];
91
+ const summary = `TUI ${verdict}: basic ${checks.filter((check) => check.pass).length}/${checks.length} · ${regressSummary}`;
92
+ return { verdict, summary, commit, attempts: attempts.length, checks, png: last?.png, regress: measured, ...(failure ? { error: failure } : {}) };
87
93
  }
88
94
 
89
95
  async function main(): Promise<number> {
@@ -10,6 +10,7 @@ import { isLandingFreezeRefusal, readLandingFreeze, LandingFrozenError } from '.
10
10
  import { debug } from '../../src/debug/log.js';
11
11
  import { runGraph, type GraphRunState } from '../../src/graph-runner/runner.js';
12
12
  import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
13
+ import { ReleaseRunClaimConflict, findActiveReleaseRun } from '../../src/cli/release-single-flight.js';
13
14
  import { releaseRunUniverse } from './release-universe.js';
14
15
  import { baseVersion, isStableVersion, nextPrereleaseVersion, type PrereleaseKind } from './release-version.js';
15
16
  import { publishAtError } from './publish-at.js';
@@ -19,6 +20,8 @@ const VERSION = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
19
20
  const GRAPH = join(import.meta.dir, '../../graphs/release/release-loop.yaml');
20
21
 
21
22
  export interface ReleaseLoopConfig {
23
+ /** Mid-cycle full-gate rehearsal, hours before cut (default 12; 0 disables). */
24
+ rehearsalHardIntervalHours?: number;
22
25
  gatePodPool?: string;
23
26
  gatePodBunCache?: string;
24
27
  gatePodShards?: number;
@@ -138,7 +141,7 @@ export function buildReleaseRunInput(version: string, deps: UnattendedReleaseDep
138
141
 
139
142
  /** Fail closed at the entry boundary, before any graph node can change a release. */
140
143
  export async function runUnattendedRelease(
141
- opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
144
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
142
145
  deps: UnattendedReleaseDeps = {},
143
146
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
144
147
  // A dry run only builds the input and mutates nothing, so it neither creates nor waits on the OP-seat lock.
@@ -149,7 +152,7 @@ export async function runUnattendedRelease(
149
152
  }
150
153
 
151
154
  async function runUnattendedReleaseLocked(
152
- opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
155
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
153
156
  deps: UnattendedReleaseDeps,
154
157
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
155
158
  // RELEASE-BRANCH (10-06): the default cut is a release branch, so main keeps landing and the run no longer needs a
@@ -188,6 +191,9 @@ async function runUnattendedReleaseLocked(
188
191
  if (beforeGraph && !opts.forceFreeze) throw new LandingFrozenError(beforeGraph);
189
192
  // RELEASE-LEDGER-UNIVERSE: one universe for the run ledger, the release ledger and every node subprocess.
190
193
  const root = releaseRunUniverse({ root: deps.ledgerRoot });
194
+ // Resume and fresh runs share the OP-seat flock. Recheck under that flock so a
195
+ // resume that began after CLI preflight cannot slip between the ledger scan and graph start.
196
+ if (!opts.forceNew && findActiveReleaseRun(version, root)) throw new ReleaseRunClaimConflict();
191
197
  const state = await (deps.graph ?? runGraph)(GRAPH, { input, pinChildUniverse: true, deps: { root } });
192
198
  // A freeze switched on while the graph ran stops gate or publish inside it. Only a failed gate/publish node whose own
193
199
  // record is the freeze refusal is reported as the freeze; any other failure keeps its own reason.
@@ -54,6 +54,7 @@ import { readOriginSessionMeta } from './origin-session-meta.js';
54
54
  import { isFactQuestion } from './fact-question.js';
55
55
  import { classifyTuiChatIntent, formatTuiRouteLine, isSeatOpsDirective, type TuiChatRoute } from '../core-turn/short-question.js';
56
56
  import { HARNESS_ROLE_ENV } from '../harness/harness-space.js';
57
+ import { createReasoningThoughtBuffer } from './reasoning-thought-buffer.js';
57
58
 
58
59
  const FACT_QUESTION_INSTRUCTION = '사실·최신 정보 질문이다. WebSearch 를 1~2회 쓰고 검색 결과(제목·스니펫·URL)로 답하라. 출처 링크를 붙여라. 셸·브라우저·파일 도구는 검색 결과로 부족할 때만. 도구 예산에 닿으면 지금까지 근거로 답하고 끝에 «더 찾아볼까요?»를 붙여라.';
59
60
 
@@ -67,8 +68,9 @@ const QUICK_TOOLS: Record<QuickTuiRoute, readonly string[]> = {
67
68
  '조회': ['decisions_pending', 'ops_seats', 'ops_status', 'release_status', 'logs_query', 'context_now', 'memory_recall', 'Read'],
68
69
  '설정 변경': ['DashboardConfigGet', 'DashboardConfigSet', 'LlmListAvailableModels', 'prompt_getRuntimeConfig', 'prompt_setRuntimeConfig', 'view_getConfig', 'view_applyRuntimeConfig', 'view_saveConfig', 'memory_recall'],
69
70
  // MsgList is a read-only ledger listing (never acks); MsgPost · MsgAck · RunShell · Bash stay out (TUI-QUICK-ROUTE-EXPLICIT-CMD).
70
- '조사': ['WebSearch', 'OmniSearch', 'Grep', 'Glob', 'Read', 'fact_check', 'memory_recall', 'MsgList'],
71
- '상시 일': ['schedule_manage', 'schedule_list', 'schedule_create', 'schedule_update', 'session_manage', 'ops_status', 'memory_recall'],
71
+ '조사': ['WebSearch', 'OmniSearch', 'Grep', 'Glob', 'Read', 'fact_check', 'memory_recall', 'MsgList', 'Agent'],
72
+ // ScheduleWakeup (H5) wakes this TUI in-process; schedule_manage is OS cron — both belong to «상시 일».
73
+ '상시 일': ['schedule_manage', 'schedule_list', 'schedule_create', 'schedule_update', 'ScheduleWakeup', 'session_manage', 'ops_status', 'memory_recall'],
72
74
  };
73
75
 
74
76
  export function toolsForTuiRoute(tools: readonly LLMToolSpec[], route: QuickTuiRoute): LLMToolSpec[] {
@@ -248,7 +250,7 @@ export function bridgeCoreTurnToAcp(
248
250
  })
249
251
  : { route: '코딩·구현' as const, reason: harness ? 'harness' : 'legacy', goalLoop: true };
250
252
  const tools = !route.goalLoop && route.route !== '코딩·구현' && route.route !== '읽기·분석'
251
- ? toolsForTuiRoute(availableTools, route.route)
253
+ ? toolsForTuiRoute(availableTools, route.route) // bridgeCoreTurnToAcp applies route allowlists here.
252
254
  : availableTools;
253
255
  if (deps.tuiRouting) {
254
256
  debug.log('chat.route', 'decided', { route: route.route, reason: route.reason, goalLoop: route.goalLoop, seat, seatKnown });
@@ -317,6 +319,7 @@ export function bridgeCoreTurnToAcp(
317
319
  let finalSupplement: { answer: string; supplement: string; finalText: string } | null = null;
318
320
  // turnFamily 는 관측용으로만 유지(goal loop 아밍 판정은 위 사실 질문 판정 앞에서 한다).
319
321
  const turnModel = modelOverride ?? getUserConfig().llm.model;
322
+ let resolvedRoute: { provider: string; model: string } | null = null;
320
323
  const turnFamily = getModelFamily(turnModel);
321
324
  if (armGoalLoop) {
322
325
  // 관측 — 어느 family/모델에서 across-turn goal-loop 가 아밍됐나(전-family 개방 검증).
@@ -380,6 +383,16 @@ export function bridgeCoreTurnToAcp(
380
383
  return approvedDispatch(name, args, dispatchCtx);
381
384
  }
382
385
  : approvedDispatch;
386
+ // TUI-TURN-NARRATION 조각 2 — 추론 요약을 «문단» 단위로 모아 ACP `agent_thought_chunk`
387
+ // (`_meta.reasoning: true`)로 보낸다. 대시보드가 흐린 💭 한 줄로 그린다(`acp-chat.ts`).
388
+ // ⛔ 전에는 debug.log 로만 남아 화면엔 «무엇을 하는지»가 0줄이었다(결함 #87).
389
+ const reasoningThoughts = createReasoningThoughtBuffer((text) => {
390
+ debug.log('llm.reasoning', 'thought-emitted', { sessionId: turnCtx.sessionId, chars: text.length });
391
+ void turnCtx.pushSessionUpdate(
392
+ { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text } },
393
+ { reasoning: true },
394
+ );
395
+ });
383
396
  const dispatchResult = await runTurnDispatch({
384
397
  sessionId: turnCtx.sessionId,
385
398
  ...(originSessionId ? { originSessionId } : {}),
@@ -401,6 +414,7 @@ export function bridgeCoreTurnToAcp(
401
414
  // contract is synchronous onText. Chunks are delivered in
402
415
  // order because `sessionUpdate` is serialized per-
403
416
  // connection on the ACP SDK side.
417
+ if (delta.length > 0) reasoningThoughts.flush();
404
418
  streamedTextSum += delta;
405
419
  void turnCtx.push(delta);
406
420
  },
@@ -418,20 +432,31 @@ export function bridgeCoreTurnToAcp(
418
432
  toolKinds.add(call.name);
419
433
  observeToolBudget();
420
434
  }
435
+ reasoningThoughts.flush();
421
436
  void turnCtx.pushToolCall(call);
422
437
  },
423
438
  onToolResult: (call) => { void turnCtx.pushToolResult(call); },
439
+ // 실제로 응답한 공급자·모델을 기억한다 — 폴백 체인이 넘기면(예 codex → grok) 턴 모델(turnModel)과 달라진다.
440
+ // streamLLMWithTools 가 스트림을 (다시) 열 때마다 부른다 → 사용량 직전 값 = 그 사용량을 낸 쪽.
441
+ onResolvedProvider: (provider, model) => { resolvedRoute = { provider, model }; },
424
442
  // 턴 모델(라우팅 결과)을 실어 보낸다 — 대시보드 턴 지표가 설정 모델로 ctx·단가를 잡지 않게.
425
- onUsage: (usage) => { void turnCtx.pushUsage({ ...usage, model: usage.model ?? turnModel }); },
426
- // Codex Responses API reasoning summary stream. Currently
427
- // surfaced via forensic only (debug.log) — acts as the
428
- // "did the model actually emit reasoning?" verification
429
- // signal before we wire the dashboard UI in a fast-follow.
443
+ // ⭐ 폴백이면 «넘어간» 모델·공급자를 싣는다(TUI-MODEL-BADGE-ACTUAL · 완료 배지가 읽는다 · 상태줄·/model 은 후속 TUI-MODEL-BADGE-SOURCE).
444
+ onUsage: (usage) => {
445
+ void turnCtx.pushUsage({
446
+ ...usage,
447
+ model: usage.model ?? resolvedRoute?.model ?? turnModel,
448
+ ...(resolvedRoute ? { routeProvider: resolvedRoute.provider } : {}),
449
+ });
450
+ },
451
+ // Codex Responses API reasoning summary stream. Surfaced to the
452
+ // dashboard as `agent_thought_chunk` via `reasoningThoughts`
453
+ // (TUI-TURN-NARRATION 조각 2) ⊕ the forensic debug.log below.
430
454
  // The forensic line carries the streamed delta and the
431
455
  // running summary index so a single grep gives the
432
456
  // reasoning trace in order. summary_part_added marks the
433
457
  // paragraph boundary; summary_delta is the text within.
434
458
  onReasoning: (event) => {
459
+ reasoningThoughts.onEvent(event);
435
460
  if (debug.enabled) {
436
461
  if (event.kind === 'summary_delta') {
437
462
  debug.log('llm.reasoning', 'codex.summary.delta', {
@@ -447,6 +472,7 @@ export function bridgeCoreTurnToAcp(
447
472
  }
448
473
  },
449
474
  onTurnComplete: async (newMessages) => {
475
+ reasoningThoughts.flush();
450
476
  // Surface runtime-injected synthesis to ACP. emitTurnComplete
451
477
  // pushes the final assistant text (which may be the W5-E/F/G
452
478
  // force-synthesis output) into history. Compare to what was
@@ -580,7 +606,8 @@ export function bridgeCoreTurnToAcp(
580
606
  }
581
607
  },
582
608
  },
583
- });
609
+ // 오류·취소로 끝나 onTurnComplete 가 안 불려도 마지막 추론 문단을 내보낸다(#28964 리뷰 FU-1 · 빈 버퍼면 무동작).
610
+ }).finally(() => reasoningThoughts.flush());
584
611
  // ⭐ 인증 거절은 코어 턴이 «던지지 않고» 돌려준다 — 여기서 안 읽으면 서버는 end_turn 을 내고
585
612
  // TUI 엔 «✔ 완료»만 남는다(TUI 결함 #22). 던져서 실패 경로(prompt-failed · 오류 줄)로 보낸다.
586
613
  const stopReason = (dispatchResult as { stopReason?: unknown } | null | undefined)?.stopReason;
@@ -81,6 +81,9 @@ export interface ElanousUiUsagePayload {
81
81
  provider?: 'anthropic' | 'openai';
82
82
  /** 그 턴이 실제로 요청한 모델(라우팅 결과 — 설정 모델과 다를 수 있다). */
83
83
  model?: string;
84
+ /** 이 사용량을 낸 «실제» 공급자(폴백 체인이 넘겼으면 넘어간 쪽 · 예 `grok`). `provider` 는 과금 계열 축이라 따로 둔다
85
+ * (TUI-MODEL-BADGE-ACTUAL · 10-16). */
86
+ routeProvider?: string;
84
87
  inputTokens?: number;
85
88
  outputTokens?: number;
86
89
  cacheReadInputTokens?: number;
@@ -0,0 +1,45 @@
1
+ // TUI-TURN-NARRATION 조각 2 — 추론 요약(reasoning summary)을 화면 한 줄로 낸다.
2
+ //
3
+ // 🩸 왜 있나 (결함 #87 · 2026-10-18): gpt-6 계열 TUI 턴은 도구 사이에 글을 0자 낸다
4
+ // (`llm.stream consume-end` `textChars=0`). 그런데 추론 요약은 라운드마다 24~37자씩 «온다»
5
+ // (`reasoningChars`). `core-turn-bridge` 의 `onReasoning` 이 debug.log 로만 남기고
6
+ // 화면으로 안 보내서, 사용자는 «무엇을 하는지» 한 줄도 못 봤다.
7
+ // 대시보드는 이미 `agent_thought_chunk` ⊕ `_meta.reasoning` 을 흐린 💭 줄로 그린다
8
+ // (`dashboard/chat/acp-chat.ts`) — 빠진 것은 «주는 자리» 하나였다.
9
+ //
10
+ // ⭐ 델타를 그대로 흘리지 않고 «문단» 단위로 모은다 — 델타마다 보내면 한 생각이 여러 줄로 찢긴다.
11
+ // 문단 경계 = 다음 `summary_part_added` · 도구 호출 · 답 글 시작 · 턴 끝.
12
+
13
+ export type ReasoningEvent =
14
+ | { kind: 'summary_part_added'; summaryIndex?: number }
15
+ | { kind: 'summary_delta'; delta: string; summaryIndex?: number };
16
+
17
+ export interface ReasoningThoughtBuffer {
18
+ onEvent(event: ReasoningEvent): void;
19
+ /** 모은 문단을 내보낸다(비었으면 아무것도 안 한다). */
20
+ flush(): void;
21
+ }
22
+
23
+ /** 요약 문단은 짧다(실측 24~37자). 폭주 방어로만 자른다. */
24
+ const MAX_THOUGHT_CHARS = 400;
25
+
26
+ export function createReasoningThoughtBuffer(emit: (text: string) => void): ReasoningThoughtBuffer {
27
+ let buf = '';
28
+ const flush = (): void => {
29
+ const text = buf.trim();
30
+ buf = '';
31
+ if (text.length === 0) return;
32
+ emit(text.length > MAX_THOUGHT_CHARS ? `${text.slice(0, MAX_THOUGHT_CHARS)}…` : text);
33
+ };
34
+ return {
35
+ onEvent(event) {
36
+ if (event.kind === 'summary_part_added') {
37
+ flush();
38
+ return;
39
+ }
40
+ // 모으는 단계에서도 상한을 지킨다 — 문단 경계 없이 긴 스트림이 와도 버퍼가 무한히 크지 않게.
41
+ if (buf.length <= MAX_THOUGHT_CHARS) buf += event.delta.slice(0, MAX_THOUGHT_CHARS + 1 - buf.length);
42
+ },
43
+ flush,
44
+ };
45
+ }
package/src/acp/server.ts CHANGED
@@ -838,6 +838,8 @@ export interface AcpTurnContext {
838
838
  pushUsage: (usage: {
839
839
  provider?: 'anthropic' | 'openai';
840
840
  model?: string;
841
+ /** 실제로 응답한 공급자(폴백이면 넘어간 쪽). */
842
+ routeProvider?: string;
841
843
  inputTokens?: number;
842
844
  outputTokens?: number;
843
845
  cacheReadInputTokens?: number;
@@ -1839,6 +1841,7 @@ function wireAcpConnection(
1839
1841
  id: `turn:${Date.now()}`,
1840
1842
  ...(usage.provider !== undefined ? { provider: usage.provider } : {}),
1841
1843
  ...(usage.model !== undefined ? { model: usage.model } : {}),
1844
+ ...(usage.routeProvider !== undefined ? { routeProvider: usage.routeProvider } : {}),
1842
1845
  ...(usage.inputTokens !== undefined ? { inputTokens: usage.inputTokens } : {}),
1843
1846
  ...(usage.outputTokens !== undefined ? { outputTokens: usage.outputTokens } : {}),
1844
1847
  ...(usage.cacheReadInputTokens !== undefined