elanous 0.2.34 → 0.2.36

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 (802) 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/chunks/{abb4b98b.163e0f56e84ae35d.js → 053a429e.9a63436527cc751c.js} +1 -1
  4. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +287 -0
  5. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +64 -0
  11. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +36 -0
  12. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +149 -0
  15. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.js → 2683.c9773a0c589b031b.js} +4 -4
  20. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +24 -0
  21. package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.js → 275-02ea4c2a33980422.js} +3 -3
  22. package/apps/pwa/out/_next/static/chunks/{ffdc3a04.b9c23c1b28dd4a96.js → 2812ca6a.3b9f4a7a08885744.js} +1 -1
  23. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +24 -0
  26. package/apps/pwa/out/_next/static/chunks/{9550.d5f76828f972058c.js → 2986.45d7652e4f13557e.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/{8817.61bb7ffbba502ecb.js → 3136.30aaaa5fa03662a3.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{9131-fce7256c4180c4a5.js → 3148-98efd4869d660a87.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{3498.cf2a15a8a9e5b926.js → 3155.2587a55196ecb394.js} +3 -3
  31. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{3103.84470c8445962f04.js → 3324.a09703033abcbd2f.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +8 -0
  36. package/apps/pwa/out/_next/static/chunks/3410.7f9af5ab77cbe65f.js +115 -0
  37. package/apps/pwa/out/_next/static/chunks/{3819.163d4777f0a597f6.js → 3538.a445e50bb359d068.js} +2 -2
  38. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +286 -0
  40. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/{3414.172ad4ca2d9b08e8.js → 3727.7949ccaacaa71242.js} +2 -2
  42. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +74 -0
  45. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.js → 3a3d9966.cc4d4585a2708e7c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +104 -0
  51. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{6740.43de73fc427c9fe2.js → 4286.b70c4520306817e8.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/4304.e9b2512834a9e23e.js +23 -0
  54. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{8548.036c344973968847.js → 4615.8525eb0add35eba6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/{3411-f87314c6c66ebc73.js → 5085-bce4904931767ca6.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +93 -0
  59. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/{3110.0a7065f25c841818.js → 528.38ce20ef8aa251ff.js} +16 -16
  61. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +122 -0
  62. package/apps/pwa/out/_next/static/chunks/{1644.35dd25240ae24e4b.js → 552.b7d061ad91eeac51.js} +2 -2
  63. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{3837.722e053fb9f321ad.js → 5711.957b095705c12560.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/{2124.ed5bf480cea7f85b.js → 575.d929793a53f27c4b.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{7562.948255cbc3e79d33.js → 599.c39c571b6733f2a2.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +79 -0
  71. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/{5446.edf141cff9ef647d.js → 6925.562d532110879886.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/{7005.1623d2aea78eb85f.js → 6943.c6b24124853a47b2.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.js → 7481.39f7a4654907bf6e.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/{2554.3b5e200f5f5cfcd6.js → 771.c3cdb6c1f7f47c02.js} +16 -16
  92. package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{3121.779fafe3e44612c5.js → 7891.03f910124a737985.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +62 -0
  100. package/apps/pwa/out/_next/static/chunks/{9a8cb466.cc9fc9e6e46038aa.js → 873d6c12.09bd499f57171543.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/{7431.3051e9b8a4372d2d.js → 8904.7d51af2dc033965c.js} +2 -2
  102. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +90 -0
  104. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +94 -0
  105. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{1895-60ed0e341c658bd4.js → 9250-072df22eaadaa6b5.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +77 -0
  111. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{2547.dd27303624cb4da8.js → 9514.131c52cc75fe6439.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9f31e478.fefcbcd3c388ebc5.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/{page-4fb31eb476dcbad3.js → page-083747f1d4518f61.js} +1 -1
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{5014f970-22bef0b5210f7d60.js → ccae1c4b-0cf414f5eff1b10d.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{4fa33ebd.21c1bd5b294496e6.js → ceba0382.650712b56b85b582.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/da5ecc5c-b005ad8cac737d57.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +1 -0
  183. package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → uC-N0emedeNOFuaBQFv-I}/_buildManifest.js +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/bin/elanous.mjs +3 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/05-authoring-lessons.jsonl +47 -0
  283. package/docs/goal-context/README.md +7 -0
  284. package/graphs/catalog/catalog.yaml +1 -1
  285. package/graphs/default-loop.yaml +63 -4
  286. package/graphs/document-loop.yaml +51 -3
  287. package/graphs/implement-loop.yaml +77 -4
  288. package/graphs/journey/ta-journey.yaml +11 -1
  289. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  290. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  291. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  292. package/graphs/operate-loop.yaml +51 -3
  293. package/graphs/release/recipes.yaml +6 -0
  294. package/graphs/release/release-loop.yaml +17 -4
  295. package/graphs/research-loop.yaml +137 -3
  296. package/graphs/test-diet/test-diet.yaml +3 -0
  297. package/graphs/wizard/recipes.yaml +44 -0
  298. package/graphs/wizard/wizard-loop.yaml +44 -0
  299. package/graphs/work/research-report.yaml +2 -0
  300. package/package.json +1 -1
  301. package/scripts/ci-typecheck-changed.ts +139 -5
  302. package/scripts/coord-role-pack.ts +19 -6
  303. package/scripts/first10-gate.ts +416 -0
  304. package/scripts/fleet/wsl-node-setup.sh +432 -0
  305. package/scripts/hq/standby-snapshot.ts +17 -12
  306. package/scripts/release-loop/docs-land-node.ts +21 -5
  307. package/scripts/release-loop/docs-node.ts +204 -8
  308. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  309. package/scripts/release-loop/gate-node.ts +427 -72
  310. package/scripts/release-loop/gate-partial.ts +65 -11
  311. package/scripts/release-loop/gate-radius-live.ts +177 -0
  312. package/scripts/release-loop/gate-radius-shadow.ts +1 -1
  313. package/scripts/release-loop/node-verdict.ts +14 -1
  314. package/scripts/release-loop/npm-publish-node.ts +66 -12
  315. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  316. package/scripts/release-loop/pwa-remote.ts +166 -0
  317. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  318. package/scripts/release-loop/resume-cap.ts +14 -34
  319. package/scripts/release-loop/resume-release.ts +78 -15
  320. package/scripts/release-loop/traffic-node.ts +59 -0
  321. package/scripts/release-loop/traffic-transition.ts +159 -0
  322. package/scripts/release-loop/unattended-release.ts +2 -0
  323. package/scripts/rhythm/daily.ts +137 -3
  324. package/scripts/test-diet/lib.ts +6 -1
  325. package/scripts/test-diet/node.ts +194 -13
  326. package/scripts/ux-sim.ts +92 -0
  327. package/skills/README.md +1 -0
  328. package/src/acp/core-turn-bridge.ts +48 -6
  329. package/src/agent/delegate-hint.ts +16 -0
  330. package/src/agent/runner.ts +82 -2
  331. package/src/agent/self-ambient-cache.ts +8 -0
  332. package/src/agent/task-notification.ts +56 -10
  333. package/src/agent/types.ts +4 -0
  334. package/src/agent-substrate/acp-reviewer.ts +39 -4
  335. package/src/agent-substrate/pr-reviewer.ts +72 -3
  336. package/src/agent-substrate/review-intent.ts +29 -2
  337. package/src/agent-substrate/review-observation.ts +3 -0
  338. package/src/agent-substrate/self-review-cli.ts +229 -28
  339. package/src/autopilot/mission-codebase-gate.ts +141 -12
  340. package/src/autopilot/pr-manager.ts +240 -41
  341. package/src/boot/daemon-tools/self-implement.ts +1 -0
  342. package/src/budget/run-usage-rollup.ts +1 -0
  343. package/src/budget/usage-outcomes.ts +8 -4
  344. package/src/capture/tui-self-report.ts +102 -0
  345. package/src/chat/goal-continue-verdict.ts +41 -0
  346. package/src/chat/index.ts +30 -6
  347. package/src/chat/internal-turn-origin.ts +1 -0
  348. package/src/chat/paste-fold.ts +86 -0
  349. package/src/chat/pickers/modal-runtime.ts +10 -27
  350. package/src/chat/tool-render/block.ts +32 -0
  351. package/src/chat/tool-render/dispatch.ts +2 -20
  352. package/src/chat/tool-render/result-text.ts +98 -0
  353. package/src/chat/turn-typeahead.ts +70 -7
  354. package/src/cli/agent-cli.ts +13 -2
  355. package/src/cli/config-audit.ts +119 -0
  356. package/src/cli/doctor-cli.ts +26 -1
  357. package/src/cli/guardian-cli.ts +10 -0
  358. package/src/cli/herdr-cli.ts +34 -0
  359. package/src/cli/light-entry-route.ts +50 -7
  360. package/src/cli/log-event-names.ts +2 -0
  361. package/src/cli/make-cli.ts +247 -11
  362. package/src/cli/msg-cli.ts +117 -3
  363. package/src/cli/pod-cli.ts +77 -3
  364. package/src/cli/pr-cli.ts +34 -18
  365. package/src/cli/pr-land-base-read.ts +11 -2
  366. package/src/cli/pr-land-heavy-remote.ts +6 -3
  367. package/src/cli/pr-land-overlap-evidence.ts +23 -4
  368. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  369. package/src/cli/pr-land-recovery.ts +117 -1
  370. package/src/cli/pty-takeover-cli.ts +8 -7
  371. package/src/cli/release-checklist-read-cli.ts +79 -0
  372. package/src/cli/release-cli.ts +92 -106
  373. package/src/cli/release-single-flight.ts +1 -1
  374. package/src/cli/remote-resolve.ts +1 -1
  375. package/src/cli/root-tui-entry.ts +48 -0
  376. package/src/cli/sim-cli.ts +22 -0
  377. package/src/cli/tasks-card-show.ts +162 -0
  378. package/src/cli/tasks-cli.ts +1065 -338
  379. package/src/cli/tasks-read-cli.ts +197 -0
  380. package/src/cli/usage-cli.ts +13 -11
  381. package/src/clipboard/history.ts +179 -13
  382. package/src/config.ts +8 -1
  383. package/src/core-turn/run-core-turn.ts +4 -2
  384. package/src/core-turn/run-goal-loop.ts +73 -16
  385. package/src/core-turn/types.ts +6 -1
  386. package/src/dashboard/chat/acp-chat.ts +8 -0
  387. package/src/dashboard/context/keys.ts +8 -31
  388. package/src/dashboard/index.ts +280 -59
  389. package/src/dashboard/input/agent-wake.ts +7 -1
  390. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
  391. package/src/dashboard/input/chat-main-slash-command.ts +4 -2
  392. package/src/dashboard/input/goal-continue.ts +210 -0
  393. package/src/dashboard/input/goal-interim.ts +2 -0
  394. package/src/dashboard/input/internal-turn.ts +2 -8
  395. package/src/dashboard/input/seat-autowake.ts +9 -7
  396. package/src/dashboard/input/turn-autoheal.ts +52 -0
  397. package/src/dashboard/render/theme-resolver.ts +33 -4
  398. package/src/dashboard/seat-boot-preamble.ts +132 -5
  399. package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
  400. package/src/dashboard/slash-runtime/dashboard-handlers.ts +3 -2
  401. package/src/dashboard/slash-runtime/model-choices.ts +15 -0
  402. package/src/dashboard/stale-install-check.ts +3 -99
  403. package/src/debug/batch-queue.ts +119 -0
  404. package/src/debug/tui-log-tag.ts +67 -0
  405. package/src/display/agent-surface.ts +7 -0
  406. package/src/domains/schedule-registry.ts +16 -2
  407. package/src/domains/standalone-log-sink.ts +15 -2
  408. package/src/esc-abort-gate.ts +69 -0
  409. package/src/git-fs/idle-refresh.ts +76 -0
  410. package/src/git-fs/index.ts +18 -7
  411. package/src/git-fs/worktree.ts +137 -5
  412. package/src/graph-kinds/registry.ts +2 -2
  413. package/src/graph-runner/graph-cli.ts +18 -0
  414. package/src/graph-runner/runner.ts +173 -21
  415. package/src/graph-wizard/generate.ts +108 -4
  416. package/src/graph-wizard/steps.ts +15 -0
  417. package/src/grok/credential.ts +10 -3
  418. package/src/grounding/proactive-ground.ts +86 -0
  419. package/src/harness/control-inbox.ts +49 -1
  420. package/src/harness/harness-cli-command.ts +163 -35
  421. package/src/harness/harness-incidents.ts +85 -1
  422. package/src/harness/launch-utterance-ledger.ts +208 -0
  423. package/src/harness/pod-control-send.ts +33 -5
  424. package/src/harness/self-send-remote.ts +69 -0
  425. package/src/harness/self-send-routing-guard.ts +6 -0
  426. package/src/harness/self-send-target.ts +4 -3
  427. package/src/impl-discipline/detector.ts +16 -4
  428. package/src/impl-discipline/system-prompt.ts +11 -0
  429. package/src/impl-discipline/types.ts +2 -2
  430. package/src/index.ts +822 -154
  431. package/src/input-core/context-key-runtime.ts +21 -0
  432. package/src/intake-plane/already-built-hint.ts +4 -2
  433. package/src/intake-plane/requirement-funnel.ts +29 -1
  434. package/src/light-cli.ts +32 -11
  435. package/src/llm/opengateway-models.ts +11 -0
  436. package/src/llm/provider-credentials.ts +14 -0
  437. package/src/llm/provider-detect.ts +8 -1
  438. package/src/llm/runtime-model-family.ts +2 -1
  439. package/src/llm-wellformed.ts +70 -0
  440. package/src/llm.ts +247 -59
  441. package/src/loops/msg-wake.ts +35 -39
  442. package/src/loops/orchestrator/inbox.ts +59 -11
  443. package/src/loops/orchestrator/knowhow-pack.ts +364 -0
  444. package/src/loops/orchestrator/tick.ts +5 -1
  445. package/src/maturity/feature-maturity.ts +1 -1
  446. package/src/model-tier/llm-tier-map.ts +15 -1
  447. package/src/models/prompts.ts +17 -2
  448. package/src/msg/msg-post-office.ts +116 -0
  449. package/src/mss/logging/log-store.ts +79 -22
  450. package/src/native-tool-catalog.ts +15 -1
  451. package/src/nexus/api/decisions-route.ts +38 -18
  452. package/src/nexus/api/graph-wizard-api.ts +20 -2
  453. package/src/nexus/api/loop-resources.ts +13 -1
  454. package/src/nexus/boot/register-mcp-clients.ts +263 -38
  455. package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
  456. package/src/oauth/codex.ts +7 -0
  457. package/src/onboarding/first-run.ts +37 -6
  458. package/src/onboarding/web-first.ts +43 -11
  459. package/src/ops/overview-collect.ts +30 -9
  460. package/src/ops/overview.ts +22 -9
  461. package/src/persona/loader.ts +11 -0
  462. package/src/persona/types.ts +8 -0
  463. package/src/pr-tool/census.ts +261 -27
  464. package/src/prompt-library/session-guidance.ts +14 -0
  465. package/src/provider-summary.ts +8 -0
  466. package/src/pty-shell/herdr-agent-report.ts +118 -9
  467. package/src/pty-shell/herdr-prompt.ts +266 -0
  468. package/src/pty-shell/pty-control-ipc.ts +151 -8
  469. package/src/pty-shell/pty-manifest.ts +7 -0
  470. package/src/pty-shell/pty-special-keys.ts +42 -2
  471. package/src/pty-shell/stale-install-check.ts +99 -0
  472. package/src/pty-shell/tui-run-state.ts +14 -2
  473. package/src/release-loop/auto-start.ts +20 -2
  474. package/src/release-loop/checklist.ts +100 -4
  475. package/src/release-loop/landed-but-yellow.ts +129 -5
  476. package/src/release-loop/light-rc.ts +1 -0
  477. package/src/release-loop/rehearsal.ts +37 -21
  478. package/src/repl/index.ts +192 -17
  479. package/src/repl/ops-msg-bridge.ts +32 -0
  480. package/src/seat-loop/knowhow-lint.ts +1 -1
  481. package/src/self-dev/ask-launch-flow.ts +44 -5
  482. package/src/self-dev/cli-help-text.ts +17 -0
  483. package/src/self-dev/decompose-proposal.ts +172 -20
  484. package/src/self-dev/decompose.ts +61 -0
  485. package/src/self-dev/dev-cli.ts +48 -12
  486. package/src/self-dev/dev-pipeline.ts +8 -2
  487. package/src/self-dev/draft-residue.ts +37 -1
  488. package/src/self-dev/draft-sweep.ts +137 -11
  489. package/src/self-dev/draft-triage-rules.ts +138 -0
  490. package/src/self-dev/fleet-reduce.ts +3 -2
  491. package/src/self-dev/glm-credential-guard.ts +77 -0
  492. package/src/self-dev/graph-front-nodes.ts +112 -0
  493. package/src/self-dev/graph-journey-nodes.ts +2 -0
  494. package/src/self-dev/graph-journey-route.ts +12 -2
  495. package/src/self-dev/harness-run-cli.ts +3 -15
  496. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  497. package/src/self-dev/orchestrate-cli.ts +68 -3
  498. package/src/self-dev/orchestrate.ts +116 -17
  499. package/src/self-dev/review-provider-fallback.ts +35 -1
  500. package/src/self-dev/run-supervisor.ts +55 -2
  501. package/src/self-dev/run-types.ts +1 -1
  502. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  503. package/src/self-dev/shard-aggregate.ts +42 -5
  504. package/src/self-dev/shard-run.ts +8 -1
  505. package/src/self-health/autoheal.ts +153 -0
  506. package/src/self-health/signatures.ts +6 -0
  507. package/src/self-implement/blocked-draft-policy.ts +20 -0
  508. package/src/self-implement/classify-shadow.ts +3 -7
  509. package/src/self-implement/device-first.ts +116 -0
  510. package/src/self-implement/doctor-visit.ts +257 -2
  511. package/src/self-implement/evidence-command-budget.ts +80 -0
  512. package/src/self-implement/gate-baseline.ts +56 -17
  513. package/src/self-implement/gate-cli.ts +1 -0
  514. package/src/self-implement/gate-remote.ts +31 -20
  515. package/src/self-implement/goal-author-cli.ts +1 -0
  516. package/src/self-implement/goal-author-decompose.ts +534 -45
  517. package/src/self-implement/goal-author.ts +282 -7
  518. package/src/self-implement/goal-elaborate.ts +449 -0
  519. package/src/self-implement/goal-refine.ts +273 -0
  520. package/src/self-implement/graph-overlay-yaml.ts +14 -3
  521. package/src/self-implement/graph-variant.ts +40 -6
  522. package/src/self-implement/headless-elanous-driver.ts +19 -3
  523. package/src/self-implement/off-diff-evidence.ts +58 -6
  524. package/src/self-implement/orchestrator.ts +370 -62
  525. package/src/self-implement/pod-warm-pool-profile.ts +1 -0
  526. package/src/self-implement/pwa-import-graph.ts +1 -1
  527. package/src/self-implement/rework-budget-judgment.ts +5 -8
  528. package/src/self-implement/rework-policy.ts +30 -0
  529. package/src/self-implement/run-ledger.ts +108 -0
  530. package/src/self-implement/run-stop.ts +10 -1
  531. package/src/self-implement/run-ttl.ts +38 -24
  532. package/src/self-implement/running-runs.ts +29 -1
  533. package/src/self-implement/scope-adjacency.ts +115 -0
  534. package/src/self-implement/seams.ts +187 -28
  535. package/src/self-implement/stop-autoheal.ts +87 -1
  536. package/src/self-implement/wiring-check.ts +358 -0
  537. package/src/session-runtime/index.ts +1 -1
  538. package/src/setup/llm-env-detect.ts +5 -0
  539. package/src/shell-env-bootstrap.ts +11 -4
  540. package/src/skills/runner.ts +4 -2
  541. package/src/skills/tools/agent.ts +408 -40
  542. package/src/skills/tools/msg-ask.ts +100 -0
  543. package/src/skills/tools/ops-ledger.ts +2 -1
  544. package/src/skills/tools/schedule-wakeup.ts +23 -4
  545. package/src/skills/tools/shell.ts +61 -6
  546. package/src/skills/tools/terminal-modal-inject.ts +1 -2
  547. package/src/skills/tools/terminal-modal.ts +10 -8
  548. package/src/skills/url-router.ts +41 -1
  549. package/src/smart-wizard/run.ts +66 -0
  550. package/src/status/bar.ts +34 -6
  551. package/src/status/status-provider-info.ts +37 -6
  552. package/src/steward/hold-hygiene.ts +24 -6
  553. package/src/steward/rejudge-tick.ts +10 -2
  554. package/src/steward/ta-repair-event-collect.ts +17 -6
  555. package/src/steward/triage-budget.ts +194 -0
  556. package/src/steward/triage.ts +20 -3
  557. package/src/task-agent/actions.ts +72 -2
  558. package/src/task-agent/green-sweep.ts +4 -0
  559. package/src/task-agent/land-queue.ts +21 -8
  560. package/src/task-agent/live-moves.ts +182 -10
  561. package/src/task-agent/mission.ts +30 -0
  562. package/src/task-agent/parent-host.ts +123 -3
  563. package/src/task-agent/rejudge-on-head.ts +15 -0
  564. package/src/task-agent/repair-cycle.ts +138 -32
  565. package/src/task-agent/repair-next-move.ts +31 -3
  566. package/src/task-agent/repair-outcomes.ts +29 -0
  567. package/src/task-agent/repair-worker.ts +14 -4
  568. package/src/task-agent/shadow.ts +48 -4
  569. package/src/task-agent/task-card-prefix.ts +2 -0
  570. package/src/task-agent/task-hand.ts +525 -57
  571. package/src/task-agent/task-parent-role-llm.ts +36 -0
  572. package/src/task-agent/tier-split.ts +196 -0
  573. package/src/task-agent/work-order-build.ts +2 -0
  574. package/src/task-agent/work-order.ts +3 -2
  575. package/src/task-orchestrator/generator-prompt.ts +60 -11
  576. package/src/task-orchestrator/surfaces/pod-account-broker.ts +42 -0
  577. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  578. package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
  579. package/src/task-orchestrator/surfaces/pod-command-job.ts +130 -11
  580. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
  581. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  582. package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
  583. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  584. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +19 -2
  585. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -4
  586. package/src/task-orchestrator/surfaces/pod-provenance.ts +82 -0
  587. package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
  588. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
  589. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
  590. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
  591. package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
  592. package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
  593. package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
  594. package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
  595. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  596. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
  597. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +7 -0
  598. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +521 -40
  599. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
  600. package/src/task-orchestrator/surfaces/self-implement-pod.ts +759 -50
  601. package/src/task-orchestrator/surfaces/self-implement.ts +65 -2
  602. package/src/tool-runtime/index.ts +15 -2
  603. package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
  604. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  605. package/src/tty-foreground.ts +155 -0
  606. package/src/tui/README.md +2 -0
  607. package/src/tui/chat/background-job-status.ts +54 -0
  608. package/src/tui/chat/goal-interim.ts +173 -0
  609. package/src/tui/chat/log-view.ts +267 -0
  610. package/src/tui/chat/self-health-status.ts +232 -0
  611. package/src/tui/entry.ts +695 -0
  612. package/src/tui/input/composer.ts +151 -0
  613. package/src/tui/seat-mail-boot.ts +59 -0
  614. package/src/tui/slash/compact-command.ts +7 -0
  615. package/src/tui/slash/compact.ts +94 -0
  616. package/src/tui/slash/new-session.ts +35 -0
  617. package/src/tui/slash/resume.ts +75 -0
  618. package/src/tui-client/local-chat-turn.ts +282 -0
  619. package/src/tui-client/local-harness-command.ts +63 -0
  620. package/src/tui-client/local-provider-command.ts +184 -0
  621. package/src/tui-client/next-dashboard-runtime.ts +8 -0
  622. package/src/tui-client/next-loop-command.ts +70 -0
  623. package/src/tui-client/next-wakeup.ts +191 -0
  624. package/src/tui.ts +37 -0
  625. package/src/ui/modal-adapter.ts +2 -2
  626. package/src/user-config.ts +4 -2
  627. package/src/ux-sim/classic-tui-seat-scenarios.ts +516 -0
  628. package/src/ux-sim/cli-config-audit-device.ts +121 -0
  629. package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
  630. package/src/ux-sim/event-monkey.ts +379 -0
  631. package/src/ux-sim/fake-bin.ts +87 -7
  632. package/src/ux-sim/fake-herdr.ts +238 -0
  633. package/src/ux-sim/fake-llm.ts +111 -6
  634. package/src/ux-sim/fault-glm-no-credential.ts +116 -0
  635. package/src/ux-sim/fault-nextmove-dispatch.ts +367 -0
  636. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  637. package/src/ux-sim/fault-scope-escape-lift.ts +216 -0
  638. package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
  639. package/src/ux-sim/goal-device.ts +619 -0
  640. package/src/ux-sim/in-process-cli.ts +22 -5
  641. package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
  642. package/src/ux-sim/mock-authoring-first-run.ts +97 -0
  643. package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
  644. package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
  645. package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
  646. package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
  647. package/src/ux-sim/next-tui-seat-scenarios.ts +631 -0
  648. package/src/ux-sim/onboarding-first-run-device.ts +269 -0
  649. package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
  650. package/src/ux-sim/subagent-tools-device.ts +81 -0
  651. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
  652. package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
  653. package/src/version/packed-revision.json +1 -1
  654. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
  655. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
  658. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
  660. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
  662. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
  663. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/2987-30cf9c2eb7b8bdd5.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
  681. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
  682. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
  683. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
  684. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
  685. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
  688. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
  695. package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
  696. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
  708. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
  711. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +0 -287
  717. package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
  722. package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
  725. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
  738. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
  740. package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
  795. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
  802. /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → uC-N0emedeNOFuaBQFv-I}/_ssgManifest.js +0 -0
@@ -172,7 +172,13 @@ export function createAgentWake(deps: AgentWakeDeps): AgentWakeController {
172
172
  return;
173
173
  }
174
174
  tryOpen(n, 'input-mounted');
175
- } catch { /* fail-soft: 깨움은 입력을 막지 않는다 */ }
175
+ } catch (error) {
176
+ // fail-soft: 깨움은 입력을 막지 않는다 — 다만 «조용히 죽은» 이유는 TF 가 봐야 한다(거부는 사유 로그).
177
+ log('tui.agent-wake', 'rejected', {
178
+ taskId: n.taskId, agent: n.agentName, state: n.state, trigger: 'input-mounted', reason: 'error',
179
+ detail: error instanceof Error ? error.message : String(error),
180
+ });
181
+ }
176
182
  });
177
183
  },
178
184
  };
@@ -15,6 +15,21 @@ import {
15
15
  import { isUnknownCodex400, repairCodexToolPairs, restoreRepairedHistory } from './compact-prepass-recovery.js';
16
16
  import type { LLMMessage } from '../../llm.js';
17
17
  import { isTuiRouteLine } from '../../core-turn/short-question.js';
18
+ import {
19
+ AutohealExhaustedError, autohealProviderFallbackMeta, autohealSignatureFor, decideAutohealStep,
20
+ formatAutohealAttemptLine, formatAutohealExhaustedNotice, type AutohealAttemptRecord,
21
+ } from '../../self-health/autoheal.js';
22
+
23
+ /** TUI-400-AUTOHEAL-FALLBACK — 400(대화 기록 어긋남)이면 사람에게 넘기기 전에 스스로 회복한다.
24
+ * ⛔ 없으면(호출부가 배선 안 함) 옛 동작 그대로 — 처방 한 줄만 보인다. */
25
+ export interface DashboardTurnAutoheal {
26
+ /** ① 새 백엔드(ACP) 세션 — 새 세션 id. 실패해도 기록은 이미 새로 짰으니 재시도는 한다. */
27
+ renewBackendSession(): Promise<string>;
28
+ /** ① 직전 기록의 짧은 요약 — 이미 있는 압축 요약을 쓴다(`summarizeForAutoheal`). 빈 문자열 = 요약 없음. */
29
+ summarizeHistory(prior: readonly unknown[]): Promise<string>;
30
+ /** ② `llm.fallbackChain` 의 다음 공급자 이름(지금 쓸 수 있는 것) — 없으면 null(② 를 건너뛰고 멈춘다). */
31
+ peekFallbackProvider(): string | null;
32
+ }
18
33
 
19
34
  export interface DashboardChatMainPlainTurnRuntimeDeps {
20
35
  userText: string;
@@ -119,6 +134,8 @@ export interface DashboardChatMainPlainTurnRuntimeDeps {
119
134
  onToolResult: (call: unknown) => void;
120
135
  onUsage: (usage: unknown) => void;
121
136
  onThought?: (text: string) => void;
137
+ /** ACP `_meta` — 자동 회복 ② 가 «다음 공급자로» 표지를 싣는다. */
138
+ meta?: Record<string, unknown>;
122
139
  }): Promise<unknown>;
123
140
  };
124
141
  autoTts: {
@@ -153,6 +170,8 @@ export interface DashboardChatMainPlainTurnRuntimeDeps {
153
170
  runActionEffects: (outcome: unknown) => Promise<void>;
154
171
  warningLine: (message: string) => string;
155
172
  pushErrorLine: (message: string) => void;
173
+ /** TUI-400-AUTOHEAL-FALLBACK — 자동 회복 배선(없으면 옛 동작). */
174
+ autoheal?: DashboardTurnAutoheal;
156
175
  /** 실패 지문이 맞은 오류: 화면엔 한국어 처방 한 줄, 원문은 여기(`/detail`)로. 없으면 원문을 그대로 낸다. */
157
176
  pushFailureNotice?: (notice: string, raw: string) => void;
158
177
  finalizeTurn: (status: 'completed' | 'interrupted' | 'failed', error?: string) => void;
@@ -178,6 +197,10 @@ export function selectDashboardChatErrorDetail(err: unknown): string {
178
197
  * without changing semantics. The orchestration stays dependency-
179
198
  * injected so future source flavors can reuse the same turn body.
180
199
  */
200
+ function safePeekFallbackProvider(autoheal: DashboardTurnAutoheal): string | null {
201
+ try { return autoheal.peekFallbackProvider(); } catch { return null; }
202
+ }
203
+
181
204
  export async function runDashboardChatMainPlainTurn(
182
205
  deps: DashboardChatMainPlainTurnRuntimeDeps,
183
206
  ): Promise<void> {
@@ -187,6 +210,13 @@ export async function runDashboardChatMainPlainTurn(
187
210
 
188
211
  let cleanupEsc = () => {};
189
212
  let stage = 'streaming-keys-attached';
213
+ // TUI-400-AUTOHEAL-FALLBACK — «자동 회복» 줄은 턴이 끝난 «뒤»에 기록에 남긴다:
214
+ // 스트림 중에 chatLines 에 넣으면 답 커밋(commitAssistantRenderState)이 답 구역째 덮어 지운다(라이브 실측 08:32).
215
+ // 도는 동안은 thinking 줄로 보인다.
216
+ const autohealLines: string[] = [];
217
+ const flushAutohealLines = (): void => {
218
+ for (const line of autohealLines.splice(0)) deps.pushChatLine(deps.warningLine(line));
219
+ };
190
220
 
191
221
  try {
192
222
  const abortCtrl = new AbortController();
@@ -350,6 +380,8 @@ export async function runDashboardChatMainPlainTurn(
350
380
  deps.debugLog?.('chat.compact-400-recovery', 'manual-recovery-required', {
351
381
  reason, historyMessages: deps.chat.history.length,
352
382
  });
383
+ // 자동 회복(TUI-400-AUTOHEAL-FALLBACK)이 배선돼 있으면 «손으로 /session new» 를 시키지 않는다 — 바깥 회복이 이어 한다.
384
+ if (deps.autoheal) return;
353
385
  deps.pushChatLine(deps.warningLine(
354
386
  'Codex 400으로 자동 복구를 멈췄습니다. 대화 이력을 확인한 뒤 /session new 로 새 세션을 시작하세요.',
355
387
  ));
@@ -466,10 +498,110 @@ export async function runDashboardChatMainPlainTurn(
466
498
  throw lastError;
467
499
  },
468
500
  };
501
+ // ⭐ TUI-400-AUTOHEAL-FALLBACK(대표 10-22) — 400(대화 기록 어긋남)으로 멈추지 않는다.
502
+ // ① 새 백엔드 세션 ⊕ 직전 요약 → ② fallbackChain 다음 공급자 → 상한(2)에서 이유 한 줄.
503
+ // ⛔ 답·도구 호출이 이미 흘렀으면 다시 보내지 않는다. 판정은 순수 `decideAutohealStep`.
504
+ const autohealSend: typeof deps.acpSession = {
505
+ send: async (opts) => {
506
+ const autoheal = deps.autoheal;
507
+ if (!autoheal) return recoverySend.send(opts);
508
+ let emitted = false;
509
+ let attemptIndex = 0;
510
+ const dispatchBefore = deps.readToolDispatchCount?.() ?? null;
511
+ const run = (meta?: Record<string, unknown>) => recoverySend.send({
512
+ ...opts,
513
+ ...(meta ? { meta: { ...(opts.meta ?? {}), ...meta } } : {}),
514
+ onText: (chunk) => {
515
+ if (isTuiRouteLine(chunk)) {
516
+ // 라우팅 줄은 모델 호출 «전»에 다리가 보낸다 — 재시도마다 또 그리지 않는다.
517
+ if (attemptIndex === 0) opts.onText(chunk);
518
+ return;
519
+ }
520
+ emitted = true;
521
+ opts.onText(chunk);
522
+ },
523
+ onToolCall: (call) => { emitted = true; opts.onToolCall(call); },
524
+ onToolResult: (call) => { emitted = true; opts.onToolResult(call); },
525
+ });
526
+ const attempts: AutohealAttemptRecord[] = [];
527
+ let lastError: unknown;
528
+ try { return await run(); } catch (err) { lastError = err; }
529
+ for (;;) {
530
+ const detail = selectDashboardChatErrorDetail(lastError);
531
+ const dispatchNow = deps.readToolDispatchCount?.() ?? null;
532
+ const decision = decideAutohealStep({
533
+ detail,
534
+ attemptsDone: attempts.length,
535
+ emitted,
536
+ toolDispatched: dispatchBefore !== null && dispatchNow !== null && dispatchNow !== dispatchBefore,
537
+ aborted: abortCtrl.signal.aborted,
538
+ fallbackProvider: attempts.length === 1 ? safePeekFallbackProvider(autoheal) : null,
539
+ });
540
+ if (decision.kind === 'stop') {
541
+ if (attempts.length === 0) {
542
+ if (decision.reason !== 'not-autoheal-signature') {
543
+ deps.debugLog?.('self-health.autoheal', 'skipped', { reason: decision.reason, signature: autohealSignatureFor(detail)?.id });
544
+ }
545
+ throw lastError;
546
+ }
547
+ deps.debugLog?.('self-health.autoheal', 'exhausted', {
548
+ attempts: attempts.length, reason: decision.reason, steps: attempts.map((a) => a.step),
549
+ }, { level: 'warn' });
550
+ throw new AutohealExhaustedError(lastError, attempts, decision.reason);
551
+ }
552
+ attemptIndex = decision.attempt;
553
+ let payload: Record<string, unknown> = { step: decision.step, attempt: decision.attempt };
554
+ let meta: Record<string, unknown> | undefined;
555
+ if (decision.step === 'new-session') {
556
+ const history = deps.chat.history;
557
+ const currentIndex = history.lastIndexOf(userMsg);
558
+ if (currentIndex < 0) {
559
+ deps.debugLog?.('self-health.autoheal', 'exhausted', { attempts: attempts.length, reason: 'history-changed', steps: [] }, { level: 'warn' });
560
+ throw lastError;
561
+ }
562
+ const prior = history.slice(0, currentIndex);
563
+ let summary = '';
564
+ try { summary = (await autoheal.summarizeHistory(prior)).trim(); } catch { /* 요약 없이도 새 세션으로 */ }
565
+ const system = prior.find((m) => (m as { role?: unknown })?.role === 'system');
566
+ history.splice(0, history.length,
567
+ ...(system ? [system] : []),
568
+ ...(summary ? [{ role: 'assistant', content: `Compacted conversation summary:
569
+
570
+ ${summary}` }] : []),
571
+ userMsg);
572
+ let sessionRenewed = false;
573
+ try { await autoheal.renewBackendSession(); sessionRenewed = true; } catch (error) {
574
+ deps.debugLog?.('self-health.autoheal', 'renew-failed', { error: redactSecretText(String(error)) }, { level: 'warn' });
575
+ }
576
+ payload = { ...payload, summaryChars: summary.length, priorMessages: prior.length, sessionRenewed };
577
+ } else {
578
+ payload = { ...payload, provider: decision.provider };
579
+ meta = autohealProviderFallbackMeta();
580
+ }
581
+ attempts.push({ step: decision.step, ...(decision.provider ? { provider: decision.provider } : {}) });
582
+ const attemptLine = formatAutohealAttemptLine(decision);
583
+ autohealLines.push(attemptLine);
584
+ try { deps.thinking.update(attemptLine); } catch { /* 표시가 회복을 막지 않는다 */ }
585
+ deps.draw();
586
+ deps.debugLog?.('self-health.autoheal', 'attempt', payload, { level: 'warn' });
587
+ if (abortCtrl.signal.aborted) throw lastError;
588
+ try {
589
+ const result = await run(meta);
590
+ deps.debugLog?.('self-health.autoheal', 'recovered', { step: decision.step, attempt: decision.attempt, ...(decision.provider ? { provider: decision.provider } : {}) });
591
+ return result;
592
+ } catch (err) {
593
+ lastError = err;
594
+ } finally {
595
+ // 시도 줄은 «도는 동안»만 — 끝 꼬리줄(✔/✘)이 그 문면을 물고 남지 않게 되돌린다(라이브 실측 08:36).
596
+ try { deps.thinking.update('Thinking'); } catch { /* 표시가 회복을 막지 않는다 */ }
597
+ }
598
+ }
599
+ },
600
+ };
469
601
  const streamResult = await runDashboardPlainTurnStream({
470
602
  userText,
471
603
  abortCtrl,
472
- acpSession: recoverySend,
604
+ acpSession: autohealSend,
473
605
  onText: (chunk, accumulated) => {
474
606
  logFirstToken(chunk);
475
607
  turnStreamRuntime.onText(chunk, accumulated);
@@ -513,6 +645,7 @@ export async function runDashboardChatMainPlainTurn(
513
645
  deps.applyAssistantRenderState(
514
646
  deps.commitAssistantRenderState(fullResponse, assistantStart, deps.chatLines.length),
515
647
  );
648
+ flushAutohealLines();
516
649
  if (debug.enabled) {
517
650
  debug.log('dashboard.chat.stream', 'plain-turn.commit-render-state', {
518
651
  fullResponseChars: fullResponse.length,
@@ -548,7 +681,10 @@ export async function runDashboardChatMainPlainTurn(
548
681
  if (routeFooter) deps.chatFooterLine.current = routeFooter;
549
682
  } catch (err: any) {
550
683
  finalStatus = 'failed';
551
- const detail = selectDashboardChatErrorDetail(err);
684
+ flushAutohealLines();
685
+ // TUI-ORPHAN-AUTO-RESUME-STOP E4 (10-23): autoheal wraps the provider error — its own message is the ACP
686
+ // «Internal error» shell, the real text (`Codex API 400 … call_id …`) lives on the original's RPC details.
687
+ const detail = selectDashboardChatErrorDetail(err instanceof AutohealExhaustedError ? err.original : err);
552
688
  const stackHead = typeof err?.stack === 'string'
553
689
  ? err.stack.split('\n').slice(0, 4).join('\n')
554
690
  : undefined;
@@ -564,7 +700,14 @@ export async function runDashboardChatMainPlainTurn(
564
700
  ? err?.message || String(err)
565
701
  : firstLine.length > 80 ? `${firstLine.slice(0, 80)}…` : firstLine;
566
702
  const failure = deps.pushFailureNotice ? matchFailureText(detail) : null;
567
- if (failure && deps.pushFailureNotice) {
703
+ if (err instanceof AutohealExhaustedError) {
704
+ // 자동 회복이 상한까지 갔다 — «/session new» 처방은 이미 해 봤으니 무엇을 해 봤고 왜 멈췄는지를 한 줄로.
705
+ const notice = formatAutohealExhaustedNotice(err.attempts, err.reason, { rawHint: '/detail open' });
706
+ if (failure) recordFailureSignatureMatch(failure, 'turn-error');
707
+ finalError = `자동 회복 ${err.attempts.length}회 실패`;
708
+ if (deps.pushFailureNotice) deps.pushFailureNotice(notice, detail);
709
+ else deps.pushErrorLine(`${notice}\n${detail}`);
710
+ } else if (failure && deps.pushFailureNotice) {
568
711
  recordFailureSignatureMatch(failure, 'turn-error');
569
712
  finalError = failure.cause;
570
713
  deps.pushFailureNotice(formatFailureNotice(failure, { rawHint: '/detail open' }), detail);
@@ -19,8 +19,10 @@ export function resolveDashboardChatMainSlashCommand(
19
19
 
20
20
  // Top-level alias: `/resume <id>` → `/session load <id>`.
21
21
  // Reuses the existing /session subcommand handler so the resume
22
- // flow stays in one place.
23
- if (cmdLower === 'resume') {
22
+ // flow stays in one place. A bare `/resume` is NOT rewritten: it must reach
23
+ // the `resume` handler that opens the session picker — rewriting it gave
24
+ // «usage: /session load <id-prefix>» and no picker (TUI-RESUME-PICKER · backlog #16).
25
+ if (cmdLower === 'resume' && args.length > 0) {
24
26
  cmdLower = 'session';
25
27
  args = ['load', ...rawArgs.filter(Boolean)];
26
28
  }
@@ -0,0 +1,210 @@
1
+ // ── 골 이어가기 `goal-continue` (TURN-END-BEFORE-GOAL · 0.2.36 · 2026-10-22 · 대표 P0 «classic·next 둘 다») ──────
2
+ //
3
+ // 🚨 무엇을 푸는가: 사용자가 목적·결과물을 준 일에서, 모델이 결과물 없이 «…하겠습니다 / …해야 합니다 /
4
+ // 제가 멈췄습니다» 로 턴을 «✔ 완료» 처리하고 멈춘다 — 사람이 다시 밀 때까지 정지(10-22 n8n 세션 실물 2회).
5
+ // ⭐ codex `on_thread_idle → continue_if_idle`(ext/goal extension.rs) 꼴: 턴이 끝났는데 «약속만 하고 끝난 답»이면
6
+ // H2 내부 턴 문(`startTurnIfIdle` · origin `goal-continue`)으로 스스로 다음 턴을 연다. 문은 새로 짓지 않는다.
7
+ // ⛔ 사람에게 묻고 끝난 답(«…할까요?» · «확인해 주세요» · «원하시면»)은 정당한 멈춤 — 열지 않는다.
8
+ // ⛔ 입력칸 버퍼·`injectKey`·pty 주입 0(대표 비침투). 판정은 화면에 그린 답 줄(classic `chatLines` · next 세션 답)만 읽는다.
9
+ //
10
+ // 켜짐: 기본 켜짐 · `ELANOUS_TUI_GOAL_CONTINUE=0|off|false` 면 끔 · 하니스 자식(ELANOUS_HARNESS_ROLE)은 끔.
11
+ // 상한: 사람 입력 없이 연속 K=3 · 같은 답 끝 구절(지문)로는 1회 · 상한 → 화면 한 줄 «사람 확인 필요» ⊕ 'cap'.
12
+ //
13
+ // 세 얼굴:
14
+ // 관측 = debug.log('tui.goal-continue', 'decided', { opened|rejected, reason, tail, consecutive }) · 'cap'
15
+ // 인지 = 턴 끝 ∧ 답 끝 구절이 약속형 ∧ 질문형 아님 ∧ 상한 안
16
+ // 힐링 = H2 로 «약속한 일을 지금 실행하라» 한 턴(화면 «↻ 자동 재개(goal-continue): …») · 상한 → 멈춤 ⊕ 'cap'
17
+
18
+ import type { TextInputInternalTurnYieldPort } from '../../chat/index.js';
19
+ import { debug } from '../../debug/log.js';
20
+ import type { StartTurnIfIdleOptions, StartTurnIfIdleResult } from './internal-turn.js';
21
+ import { classifyReplyTail, replyTailFromLines, type GoalContinueVerdict } from '../../chat/goal-continue-verdict.js';
22
+ export { classifyReplyTail, replyTailFromLines } from '../../chat/goal-continue-verdict.js';
23
+ export type { GoalContinueVerdict } from '../../chat/goal-continue-verdict.js';
24
+
25
+ export const GOAL_CONTINUE_ENV = 'ELANOUS_TUI_GOAL_CONTINUE';
26
+ export const DEFAULT_GOAL_CONTINUE_CAP = 3;
27
+ const HUMAN_ACTION = /로그인(?:이 필요|해 주세요)|결제(?:가 필요|해 주세요|해야 합니다)|(?:사람|사용자)의\s*(?:결정|승인)|(?:결정|승인)(?:이 필요|해 주세요)|권한이 필요|비밀번호를 입력해 주세요|위험\s*(?:승인|감수)(?:가 필요|를 직접)|직접\s*(?:선택|확인|승인)(?:해 주세요|이 필요)|\bhuman\s+(?:approval|decision|login|payment)\s+(?:is )?(?:required|needed)\b/iu;
28
+ const REMAINING_WORK = /(?:남은\s*(?:일|작업|것)|remaining work).{0,80}(?:아직|미완|남아\s*있|못\s*(?:했|하)|하지\s*못|not yet|unfinished|incomplete)/iu;
29
+ const NO_REMAINING_WORK = /(?:남은\s*(?:일|작업|것)(?:은|이)?\s*(?:없|완료|끝)|(?:모두|전부)\s*(?:완료|끝났)|\bno remaining work\b|\ball remaining work\b.{0,16}\b(?:done|complete|finished)\b)/iu;
30
+
31
+ function remainingWorkTail(tail: string | null): string | null {
32
+ if (!tail || NO_REMAINING_WORK.test(tail) || !REMAINING_WORK.test(tail)) return null;
33
+ const sentence = tail.split(/(?<=[.!?。?])\s+/u).reverse().find((part) => REMAINING_WORK.test(part));
34
+ return (sentence ?? tail).slice(-120);
35
+ }
36
+
37
+ export function goalContinueFingerprint(tail: string): string {
38
+ let h = 2166136261;
39
+ for (let i = 0; i < tail.length; i++) { h ^= tail.charCodeAt(i); h = Math.imul(h, 16777619); }
40
+ return (h >>> 0).toString(16);
41
+ }
42
+
43
+ /** next: 세션 메시지 중 «이번 턴이 만든» 마지막 답만.
44
+ * ① 보통 턴 = 턴 시작 때 길이(startIndex) 뒤에서 찾는다 — 이번 턴 답이 없으면 빈 배열(앞 턴 답으로 안 연다 · r3).
45
+ * ② 이번 턴에 자동 압축이 있었으면(startIndex 가 'after-last-user') 압축으로 줄어든 길이 대신
46
+ * «마지막 사람 메시지 뒤» 의 답만 본다 — 이번 턴 사람 글은 압축 뒤에도 마지막 사람 글이다(r5 must-fix). */
47
+ export function replyLinesOfThisTurn(messages: ReadonlyArray<{ role: string; content?: unknown }>, startIndex: number | 'after-last-user'): string[] {
48
+ let from: number;
49
+ if (startIndex === 'after-last-user') {
50
+ let lastUser = -1;
51
+ for (let i = messages.length - 1; i >= 0; i--) if (messages[i]!.role === 'user') { lastUser = i; break; }
52
+ if (lastUser < 0) return [];
53
+ from = lastUser + 1;
54
+ } else {
55
+ from = Math.max(0, startIndex);
56
+ }
57
+ const reply = messages.slice(from).filter((m) => m.role === 'assistant').at(-1);
58
+ return typeof reply?.content === 'string' ? reply.content.split('\n') : [];
59
+ }
60
+
61
+ export function formatGoalContinuePrompt(phrase: string): string {
62
+ return `[골 이어가기] 방금 답이 «${phrase}» 로 끝났다 — 약속만 하고 턴을 끝내지 말고, 그 일을 지금 도구로 실행해 결과물을 만든다. `
63
+ + '원래 사용자 요청 범위 안에서만 이어간다. 정말 사람 판단·권한이 필요하면 무엇이 필요한지 한 줄로 묻고 멈춘다.';
64
+ }
65
+
66
+ export function isGoalContinueEnabledByEnv(env: NodeJS.ProcessEnv = process.env): boolean {
67
+ if (env.ELANOUS_HARNESS_ROLE?.trim()) return false;
68
+ const v = (env[GOAL_CONTINUE_ENV] ?? '').trim().toLowerCase();
69
+ return !(v === '0' || v === 'off' || v === 'false');
70
+ }
71
+
72
+ // ── 배선 컨트롤러 ────────────────────────────────────────────────────────────────────
73
+
74
+ export interface GoalContinueDeps {
75
+ /** H2 문 — classic `internalTurnGate.startTurnIfIdle` · next `wakeup.gate.startTurnIfIdle`. */
76
+ startTurnIfIdle: (input: string, opts: StartTurnIfIdleOptions) => StartTurnIfIdleResult;
77
+ isEnabled?: () => boolean;
78
+ consecutiveCap?: number;
79
+ notify?: (line: string) => void;
80
+ /** 사람 입력 직후 거부(HumanTyping)면 다시 잴 시각까지 미룬다(기본 setTimeout · unref). */
81
+ defer?: (fn: () => void, ms: number) => void;
82
+ /** HumanTyping 재시도 간격(기본 문 조용창 10초 + 여유). */
83
+ retryMs?: number;
84
+ log?: (category: string, event: string, data: Record<string, unknown>) => void;
85
+ }
86
+
87
+ export interface GoalContinueTurnEnd {
88
+ /** 화면에 그린 답 줄(classic `chatLines` 꼬리) — 또는 답 원문 한 줄(next). */
89
+ lines: readonly string[];
90
+ /** 턴이 실패(✘)·취소로 끝났으면 true — 이어가지 않는다. */
91
+ failed?: boolean;
92
+ }
93
+
94
+ export interface GoalContinueController {
95
+ /** 모델 턴이 끝났다 — 답 끝 구절을 판정해 둔다(여는 것은 check). */
96
+ noteTurnEnded(end: GoalContinueTurnEnd): void;
97
+ /** 판정된 턴 끝이 무장돼 있으면 H2 로 연다. 사람 입력이 먼저면 미뤘다가 다시 잰다. */
98
+ check(): { opened: boolean; reason: string };
99
+ /** 사람이 턴을 열었다 — 연속 카운터·지문을 비운다. */
100
+ noteHumanTurn(): void;
101
+ /** classic: H2 yield port 를 감싸 «입력칸 마운트 = 판정 시점»으로 잇는다(입력칸 무접촉). */
102
+ wrapPort(port: TextInputInternalTurnYieldPort): TextInputInternalTurnYieldPort;
103
+ }
104
+
105
+ function defaultDefer(fn: () => void, ms: number): void {
106
+ const t = setTimeout(fn, ms);
107
+ (t as { unref?: () => void }).unref?.();
108
+ }
109
+
110
+ export function createGoalContinue(deps: GoalContinueDeps): GoalContinueController {
111
+ const isEnabled = deps.isEnabled ?? (() => isGoalContinueEnabledByEnv());
112
+ const cap = deps.consecutiveCap ?? DEFAULT_GOAL_CONTINUE_CAP;
113
+ const defer = deps.defer ?? defaultDefer;
114
+ const retryMs = deps.retryMs ?? 10_500;
115
+ const log = deps.log ?? ((c, e, d) => debug.log(c, e, d));
116
+
117
+ let armed: { tail: string; phrase: string; fingerprint: string; mode: 'pledge' | 'remaining' } | null = null;
118
+ let consecutive = 0;
119
+ /** 사람 턴 이후 이미 이어간 답들의 지문 — A→B→A 에서도 같은 답으로 두 번 열지 않는다(r2 must-fix). */
120
+ const openedFingerprints = new Set<string>();
121
+ let capNotified = false;
122
+ let retryArmed = false;
123
+
124
+ const check: GoalContinueController['check'] = () => {
125
+ if (!armed) return { opened: false, reason: 'not-armed' };
126
+ const { tail, phrase, fingerprint, mode } = armed;
127
+ // 초기화는 실제 사람 턴(noteHumanTurn)에서만 — 키만 치고 안 보낸 것으로 상한을 우회하지 못한다(r2 must-fix).
128
+ if (openedFingerprints.has(fingerprint)) {
129
+ armed = null;
130
+ log('tui.goal-continue', 'decided', { rejected: true, reason: 'same-reply', tail, consecutive });
131
+ if (mode === 'remaining') {
132
+ log('tui.proactive', 'stop-no-progress', { reason: 'same-remaining', remainingDigest: fingerprint, autoTurn: consecutive });
133
+ return { opened: false, reason: 'no-progress' };
134
+ }
135
+ return { opened: false, reason: 'same-reply' };
136
+ }
137
+ if (consecutive >= cap) {
138
+ armed = null;
139
+ if (!capNotified) {
140
+ capNotified = true;
141
+ log('tui.goal-continue', 'cap', { cap, tail });
142
+ deps.notify?.(`⏸ 골 이어가기 상한(${cap}회 연속) — 사람 확인 필요 · 키 하나면 다시 이어간다`);
143
+ }
144
+ log('tui.goal-continue', 'decided', { rejected: true, reason: 'cap', tail, consecutive });
145
+ log('tui.proactive', 'stop-cap', { reason: mode === 'remaining' ? 'work-remaining' : 'pledge', remainingDigest: fingerprint, autoTurn: consecutive, cap });
146
+ return { opened: false, reason: 'cap' };
147
+ }
148
+ const result = deps.startTurnIfIdle(formatGoalContinuePrompt(phrase), { origin: 'goal-continue', reason: `«${phrase}» 뒤 이어서 실행` });
149
+ if (result.opened) {
150
+ armed = null;
151
+ consecutive += 1;
152
+ openedFingerprints.add(fingerprint);
153
+ log('tui.goal-continue', 'decided', { opened: true, reason: 'pledge-without-result', phrase, tail, consecutive, turnId: result.turnId });
154
+ log('tui.proactive', 'continue', { reason: mode === 'remaining' ? 'work-remaining' : 'pledge-without-result', remainingDigest: fingerprint, autoTurn: consecutive, turnId: result.turnId });
155
+ return { opened: true, reason: 'pledge-without-result' };
156
+ }
157
+ log('tui.goal-continue', 'decided', { rejected: true, reason: result.reason, ...(result.detail ? { detail: result.detail } : {}), tail, consecutive });
158
+ // 사람이 막 쳤거나(조용창) 아직 안 비켰다 — 무장은 남기고 조금 뒤 다시 잰다(그 사이 사람 턴이면 noteHumanTurn 이 푼다).
159
+ if ((result.reason === 'HumanTyping' || result.reason === 'NotIdle') && !retryArmed) {
160
+ retryArmed = true;
161
+ defer(() => { retryArmed = false; try { check(); } catch { /* fail-soft */ } }, retryMs);
162
+ } else if (result.reason !== 'HumanTyping' && result.reason !== 'NotIdle') {
163
+ armed = null;
164
+ }
165
+ return { opened: false, reason: result.reason };
166
+ };
167
+
168
+ return {
169
+ noteTurnEnded(end) {
170
+ armed = null;
171
+ if (!isEnabled()) return;
172
+ if (end.failed) {
173
+ log('tui.goal-continue', 'decided', { rejected: true, reason: 'turn-failed' });
174
+ return;
175
+ }
176
+ const tail = replyTailFromLines(end.lines);
177
+ const verdict = classifyReplyTail(tail);
178
+ const remaining = remainingWorkTail(tail);
179
+ if (tail && HUMAN_ACTION.test(tail)) {
180
+ log('tui.goal-continue', 'skipped', { reason: 'asks-human', tail: tail.slice(-80) });
181
+ log('tui.proactive', 'stop-human', { reason: 'human-action', remainingDigest: goalContinueFingerprint(tail), autoTurn: consecutive });
182
+ return;
183
+ }
184
+ if (!verdict.pledge && !remaining) {
185
+ // 평범한 끝(질문·결과 보고)은 관측만 — 대부분의 턴이 여기다.
186
+ log('tui.goal-continue', 'skipped', { reason: verdict.reason, ...(tail ? { tail: tail.slice(-80) } : {}) });
187
+ return;
188
+ }
189
+ const phrase = remaining ?? (verdict.pledge ? verdict.phrase : '');
190
+ armed = { tail: tail!, phrase, fingerprint: goalContinueFingerprint(remaining ?? tail!), mode: remaining ? 'remaining' : 'pledge' };
191
+ },
192
+ check,
193
+ noteHumanTurn() {
194
+ armed = null;
195
+ consecutive = 0;
196
+ openedFingerprints.clear();
197
+ capNotified = false;
198
+ },
199
+ wrapPort(port) {
200
+ return {
201
+ attach(requestYield) {
202
+ port.attach(requestYield);
203
+ if (armed) defer(() => { try { check(); } catch { /* fail-soft */ } }, 0);
204
+ },
205
+ detach(opts) { port.detach(opts); },
206
+ declined(detail) { port.declined?.(detail); },
207
+ };
208
+ },
209
+ };
210
+ }
@@ -0,0 +1,2 @@
1
+ // Dashboard compatibility entry; the pure display planner is shared with next TUI.
2
+ export * from '../../tui/chat/goal-interim.js';
@@ -18,17 +18,11 @@
18
18
  import type { InputResult, TextInputInternalTurnYieldPort } from '../../chat/index.js';
19
19
  import { debug } from '../../debug/log.js';
20
20
  import type { SubmitTurnIntent } from '../../input/input-intent.js';
21
+ import type { InternalTurnOrigin } from '../../chat/internal-turn-origin.js';
22
+ export type { InternalTurnOrigin } from '../../chat/internal-turn-origin.js';
21
23
  import { lastHumanKeyAt as tuiLastHumanKeyAt, pendingKeyCount as tuiPendingKeyCount } from '../../tui.js';
22
24
 
23
25
  /** 내부 턴의 출처 — 화면 한 줄·관측·정책이 이 값으로 갈린다. 새 출처는 여기에 더한다. */
24
- export type InternalTurnOrigin =
25
- | 'autowake'
26
- | 'msg-wake'
27
- | 'scheduled'
28
- | 'child-complete'
29
- | 'goal-continue'
30
- | 'test';
31
-
32
26
  /** 거부 사유 — 에러가 아니라 값이다. 호출자는 이 값을 보고 다음 idle 에 다시 부를지 정한다. */
33
27
  export type InternalTurnRejectReason =
34
28
  /** 턴이 도는 중이거나, 입력칸이 안 떠 있거나(다른 창·모달), 앞 내부 턴이 아직 안 시작됐다. */
@@ -331,21 +331,23 @@ export function createSeatAutowake(deps: SeatAutowakeDeps): SeatAutowakeControll
331
331
  lastFingerprint = null;
332
332
  consecutive = 0;
333
333
  }
334
- // The production failed-turn path renders this exact 400 notice and
335
- // stages its raw detail. Ordinary assistant text can quote the same API
336
- // error, so it must never be parsed as a failed turn by itself.
337
- const is400Notice = result.lastLine.includes('모델 API 가 요청을 400 으로 거절')
338
- && result.lastLine.includes('원문 /detail open');
339
- const match = is400Notice
340
- ? /\bCodex API 400\b[^\n]*?No tool call found for function call output with call_id\s+([\w-]+)/iu.exec(result.errorDetail ?? '')
334
+ // Only the production failed-turn path stages `errorDetail` (pushFailureNotice), so its presence is what
335
+ // marks a failed turn — ordinary assistant text that quotes the same API error never carries it.
336
+ // TUI-ORPHAN-AUTO-RESUME-STOP E4 (10-23): the visible line is not a usable gate — this 400 goes through
337
+ // autoheal, whose notice reads «⚠ 자동 회복 N회 실패…», and the turn footer «✘ 실패 …» is the last line.
338
+ // The old gate («모델 API 가 요청을 400 으로 거절» in lastLine) therefore never matched in the live TUI.
339
+ const match = result.errorDetail !== undefined
340
+ ? /\bCodex API 400\b[^\n]*?No tool call found for function call output with call_id\s+([\w-]+)/iu.exec(result.errorDetail)
341
341
  : null;
342
342
  if (!match || !activeSessionId) {
343
+ if (result.errorDetail !== undefined) log('tui.autowake', 'turn-failure', { sessionId: activeSessionId, orphan400: false, count: 0, detailHead: result.errorDetail.slice(0, 160) });
343
344
  lastOrphanFailure = null;
344
345
  return;
345
346
  }
346
347
  const callId = match[1]!;
347
348
  lastOrphanFailure = lastOrphanFailure?.callId === callId
348
349
  ? { callId, count: lastOrphanFailure.count + 1 } : { callId, count: 1 };
350
+ log('tui.autowake', 'turn-failure', { sessionId: activeSessionId, orphan400: true, callId, count: lastOrphanFailure.count });
349
351
  if (lastOrphanFailure.count < 2 || terminalCallId) return;
350
352
  terminalCallId = callId;
351
353
  log('tui.autowake', 'terminal', {
@@ -0,0 +1,52 @@
1
+ // TUI-400-AUTOHEAL-FALLBACK — classic TUI(대시보드)의 자동 회복 배선 한 곳.
2
+ //
3
+ // plain-turn 런타임(`chat-main-plain-turn-runtime`)이 «언제·몇 번» 을 정하고, 여기는 «무엇으로» 만 준다:
4
+ // ① 새 백엔드 세션 = `DashboardSession.renew`(= `/session new` 의 ACP 갱신과 같은 호출)
5
+ // ① 직전 요약 = 이미 있는 압축 요약 `compactConversation` ⊕ 실패 시 `buildCompactTranscript` 꼬리
6
+ // ② 다음 공급자 = 턴 안 폴백과 같은 `llm.fallbackChain` 해석(`nextTurnFallbackProvider`)
7
+ // ⛔ 원격 데몬 세션은 ② 를 못 한다(공급자 결정이 데몬 쪽 · 서버 다리는 in-process 만 표지를 읽는다) — ① 만.
8
+ // ⭐ 대시보드와 결함 주입 장치(`ux-sim/fault-tui-400-autoheal`)가 «같은» 이 함수를 쓴다(재구현 0).
9
+
10
+ import { nextTurnFallbackProvider, resolveDefaultProvider, type LLMMessage } from '../../llm.js';
11
+ import type { DashboardTurnAutoheal } from './chat-main-plain-turn-runtime.js';
12
+ import { summarizeForAutoheal } from '../../self-health/autoheal.js';
13
+
14
+ export interface DashboardTurnAutohealDeps {
15
+ /** ACP 세션 — `renew(cwd)` 가 새 백엔드 세션 id 를 돌려준다. */
16
+ session: { renew(cwd: string): Promise<string> };
17
+ getCwd(): string;
18
+ /** 새 세션 id 를 대시보드 상태(acpSessionIdRef 등)에 반영. */
19
+ onRenewed?(sessionId: string): void;
20
+ /** 원격 데몬에 붙은 세션이면 true — ② 를 건너뛴다. */
21
+ remote: boolean;
22
+ /** 이 턴 모델(공급자 해석의 힌트) — 다리의 `resolveModel` 과 같은 값. */
23
+ activeModel(): string | undefined;
24
+ /** 시험 seam — 요약 시간 상한(ms). */
25
+ summaryTimeoutMs?: number;
26
+ }
27
+
28
+ export function createDashboardTurnAutoheal(deps: DashboardTurnAutohealDeps): DashboardTurnAutoheal {
29
+ return {
30
+ async renewBackendSession() {
31
+ const renewed = await deps.session.renew(deps.getCwd());
32
+ deps.onRenewed?.(renewed);
33
+ return renewed;
34
+ },
35
+ async summarizeHistory(prior) {
36
+ const { compactConversation, buildCompactTranscript } = await import('../../compact/index.js');
37
+ const history = prior as readonly LLMMessage[];
38
+ const { summary } = await summarizeForAutoheal(history, {
39
+ compact: (h) => compactConversation(h),
40
+ transcript: (h) => buildCompactTranscript(h),
41
+ ...(deps.summaryTimeoutMs !== undefined ? { timeoutMs: deps.summaryTimeoutMs } : {}),
42
+ });
43
+ return summary;
44
+ },
45
+ peekFallbackProvider() {
46
+ if (deps.remote) return null;
47
+ // 다리(core-turn-bridge)가 ② 에서 고를 것과 «같은» 해석 — 화면 한 줄의 이름과 실제 공급자가 어긋나지 않게.
48
+ const failed = resolveDefaultProvider(deps.activeModel()).name;
49
+ return nextTurnFallbackProvider([failed])?.name ?? null;
50
+ },
51
+ };
52
+ }
@@ -33,6 +33,12 @@ import { getTheme } from '../../themes/index.js';
33
33
  // same shape `pluginHost.loadThemeTokens` produces — not a full ThemeTokens.
34
34
  export type PluginThemeLoader = (id: string) => ThemeTokenInput | null | undefined;
35
35
 
36
+ export interface PluginThemeAppliedEvent {
37
+ id: string;
38
+ tokensCount: number;
39
+ source: 'plugin';
40
+ }
41
+
36
42
  export interface ResolveActiveThemeOptions {
37
43
  /** Raw `dashboard.theme` value from user-config. Shape is flexible:
38
44
  * `null` | `string` | `{ active: string, ... }` | `{ tokens: {...} }`. */
@@ -44,17 +50,19 @@ export interface ResolveActiveThemeOptions {
44
50
  * (so a broken plugin doesn't crash the dashboard) but reported
45
51
  * here for visibility. */
46
52
  onPluginError?: (message: string) => void;
53
+ /** Called after plugin tokens have been merged into the resolved theme. */
54
+ onPluginApplied?: (event: PluginThemeAppliedEvent) => void;
47
55
  }
48
56
 
49
57
  /** Resolve the active dashboard theme from user-config, with preset
50
58
  * + plugin + default fallback layers. Pure function — no I/O. */
51
59
  export function resolveActiveTheme(opts: ResolveActiveThemeOptions): ThemeTokens {
52
- const { raw, loadPlugin, onPluginError } = opts;
60
+ const { raw, loadPlugin, onPluginError, onPluginApplied } = opts;
53
61
 
54
62
  // Extract active name + user overrides from the raw user-config
55
63
  // value. The config shape evolved over time — handle all known
56
64
  // forms defensively.
57
- const activeName = extractActiveName(raw);
65
+ const activeName = getActiveThemeName(raw);
58
66
  const rawOverrides: ThemeTokenInput | undefined = extractOverrides(raw);
59
67
 
60
68
  // Branch 1: preset registry hit.
@@ -70,10 +78,20 @@ export function resolveActiveTheme(opts: ResolveActiveThemeOptions): ThemeTokens
70
78
  try {
71
79
  const contributed = loadPlugin(activeName);
72
80
  if (contributed) {
73
- return mergeThemeTokens(
81
+ const resolved = mergeThemeTokens(
74
82
  mergeThemeTokens(DEFAULT_THEME_TOKENS, contributed),
75
83
  rawOverrides ?? {},
76
84
  );
85
+ try {
86
+ onPluginApplied?.({
87
+ id: activeName,
88
+ tokensCount: countTokenLeaves(contributed),
89
+ source: 'plugin',
90
+ });
91
+ } catch {
92
+ // Observation failures must not discard an already-resolved theme.
93
+ }
94
+ return resolved;
77
95
  }
78
96
  } catch (err: unknown) {
79
97
  const message =
@@ -86,7 +104,18 @@ export function resolveActiveTheme(opts: ResolveActiveThemeOptions): ThemeTokens
86
104
  return resolveThemeTokens(raw);
87
105
  }
88
106
 
89
- function extractActiveName(raw: unknown): string | null {
107
+ function countTokenLeaves(value: unknown, isRoot = true): number {
108
+ if (value === null || value === undefined) return 0;
109
+ if (typeof value !== 'object') return 1;
110
+ if (Array.isArray(value)) {
111
+ return value.reduce((count, item) => count + countTokenLeaves(item, false), 0);
112
+ }
113
+ return Object.entries(value as Record<string, unknown>)
114
+ .filter(([key]) => !isRoot || key !== 'name')
115
+ .reduce((count, [, item]) => count + countTokenLeaves(item, false), 0);
116
+ }
117
+
118
+ export function getActiveThemeName(raw: unknown): string | null {
90
119
  if (typeof raw === 'string') return raw.trim() || null;
91
120
  if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
92
121
  const active = (raw as Record<string, unknown>).active;