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
@@ -40,6 +40,7 @@ import { writeGoalDocumentAtomic } from './goal-document-write.js';
40
40
  import { hostname, loadavg } from 'node:os';
41
41
  import { resolveHostId } from '../platform/host-id.js';
42
42
  import { resolveInstanceName } from '../instance-identity.js';
43
+ import { ghAutomationEnv } from '../autopilot/pr-manager.js';
43
44
  import { citedReviewSymbols, MAX_CITED_REVIEW_SYMBOL_CHARS, measureReviewFindingKeyOverlap, normalizeReviewFindingKey, REVIEW_FINDING_KEY_VERSION, reviewFindingKey, shortNormalizedReviewFindingHash, type CitedReviewSymbol } from '../agent-substrate/review-finding-key.js';
44
45
  export { citedReviewSymbols, MAX_CITED_REVIEW_SYMBOL_CHARS, normalizeReviewFindingKey, REVIEW_FINDING_KEY_VERSION, reviewFindingKey, shortNormalizedReviewFindingHash, type CitedReviewSymbol } from '../agent-substrate/review-finding-key.js';
45
46
 
@@ -47,6 +48,46 @@ function displayBranchName(ref: string): string {
47
48
  return ref.trim().replace(/^refs\/heads\//, '').replace(/^origin\//, '');
48
49
  }
49
50
 
51
+ export const HARVEST_DEFERRED_MARKER = '수확보류: harvest-deferred';
52
+ const execFileAsync = promisify(execFileCallback);
53
+
54
+ export function markHarvestDeferredBody(input: {
55
+ runStatus: string | undefined;
56
+ prNumber: number | undefined;
57
+ body: string | undefined;
58
+ }): string | undefined {
59
+ if (input.runStatus !== 'failed' || input.prNumber === undefined || !Number.isSafeInteger(input.prNumber) || input.prNumber < 1 || input.body === undefined) return undefined;
60
+ if (harvestDeferredMarker(input.body)) return input.body;
61
+ const separator = input.body.endsWith('\n') ? '\n' : '\n\n';
62
+ return `${input.body}${separator}${HARVEST_DEFERRED_MARKER}`;
63
+ }
64
+
65
+ export async function readHarvestPrBody(opts: { number: number; cwd: string }): Promise<{ body: string; state: string; isDraft: boolean } | undefined> {
66
+ const { stdout } = await execFileAsync('gh', ['pr', 'view', String(opts.number), '--json', 'body,state,isDraft'], {
67
+ cwd: opts.cwd,
68
+ env: ghAutomationEnv(process.env),
69
+ encoding: 'utf8',
70
+ timeout: 120_000,
71
+ maxBuffer: 2 * 1024 * 1024,
72
+ });
73
+ const parsed: unknown = JSON.parse(stdout);
74
+ if (!parsed || typeof parsed !== 'object') return undefined;
75
+ const record = parsed as { body?: unknown; state?: unknown; isDraft?: unknown };
76
+ return typeof record.body === 'string' && typeof record.state === 'string' && typeof record.isDraft === 'boolean'
77
+ ? { body: record.body, state: record.state, isDraft: record.isDraft }
78
+ : undefined;
79
+ }
80
+
81
+ export async function updateHarvestPrBody(opts: { number: number; body: string; cwd: string }): Promise<void> {
82
+ await execFileAsync('gh', ['pr', 'edit', String(opts.number), '--body', opts.body], {
83
+ cwd: opts.cwd,
84
+ env: ghAutomationEnv(process.env),
85
+ encoding: 'utf8',
86
+ timeout: 120_000,
87
+ maxBuffer: 2 * 1024 * 1024,
88
+ });
89
+ }
90
+
50
91
  export function formatAutoMergeSuccessMessage(input: {
51
92
  prNumber: number;
52
93
  mergedBase?: string | undefined;
@@ -79,6 +120,7 @@ import { classifyGateEnvDeficit, DEFAULT_GATE_ENV_RETRY, GATE_ENV_DEFICIT_HARVES
79
120
  import { recordFailureEvent } from './heal-intake.js';
80
121
  import { classifyReworkCapExhaustion, type ReworkCapHealDecision } from './heal-triage.js';
81
122
  import { releasePathHold, releasePathHoldComment, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
123
+ import { harvestDeferredMarker } from '../self-dev/draft-triage-rules.js';
82
124
  import { emitDecision } from '../live/detail-switch.js';
83
125
  import { reworkDecision } from './decision-events.js';
84
126
  import type { LogSink } from '../mss/logging/sink.js';
@@ -91,7 +133,7 @@ import { classifyError } from '../session-runtime/retry-policy.js';
91
133
  import { decomposeSelfDevGoal, inferHotPaths, type SelfDevDecomposeOptions } from '../self-dev/decompose.js';
92
134
  import { boundaryGlobs, boundaryViolations } from './goal-boundary.js';
93
135
  import { askAtExecution, type ExecutionClarificationResult } from './execution-clarification.js';
94
- import { classifyOutOfScope } from './scope-adjacency.js';
136
+ import { decideScopeExpansion, renderScopeExpansionSection, SCOPE_EXPANSION_CAP, type ScopeExpansion, type ScopeStopReason } from './scope-adjacency.js';
95
137
  import { targetScopedGoalText } from './goal-text-path-scope.js';
96
138
  import { selectKnowhowPack } from './knowhow-pack.js';
97
139
  import { declaredNewFilePaths } from './goal-new-paths.js';
@@ -108,6 +150,7 @@ import { originObservationFields } from '../agent/origin-observation.js';
108
150
  import { resolveLaunchStamp, type LaunchStamp } from '../harness/launch-stamp.js';
109
151
  import { getHarnessSpace, normalizeSpaceId, resolveRunIdentity } from '../harness/harness-space.js';
110
152
  import { getElanousConfigDir } from '../elanous-config-dir.js';
153
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
111
154
  import { elanousStateRoot } from '../autopilot/state-paths.js';
112
155
  import { addNextMdReleaseNote, harnessReleaseNote, parseReleaseNoteSection, releaseNotesDir, renderReleaseNoteSection, writeReleaseNote, type ReleaseNoteFragment, type ReleaseNoteSection } from '../release-loop/release-note.js';
113
156
  import { landingFreezeMessage } from '../release-loop/landing-freeze.js';
@@ -182,7 +225,8 @@ import { formatGateFailedId, type PremiseReviewCard, type PremiseReviewInput } f
182
225
  import { runWorkflowToCompletion } from '../workflow-runtime/executor.js';
183
226
  import { mapReworkVerdict, supervisionObservationFields } from './supervision-vocabulary.js';
184
227
  import { resolveRunOutcome } from './run-outcome.js';
185
- import { authorLimitationCountFromGoal, harvestEvidenceLines, harvestedEvidenceObservation, MAX_HARVESTED_EVIDENCE_CHARS, parseOffDiffEvidence, requiredEvidenceFromGoal, runRequiredEvidenceChecks, coverRequiredEvidence, settleUncoveredEvidence, formatUncoveredEvidenceFeedback, type OffDiffEvidenceParse } from './off-diff-evidence.js';
228
+ import { authorLimitationCountFromGoal, harvestEvidenceLines, harvestedEvidenceObservation, MAX_HARVESTED_EVIDENCE_CHARS, parseOffDiffEvidence, requiredEvidenceFromGoal, createRequiredEvidenceBudget, coverRequiredEvidence, settleUncoveredEvidence, formatUncoveredEvidenceFeedback, type OffDiffEvidenceParse } from './off-diff-evidence.js';
229
+ import { resolveEvidenceHeadCommit } from './evidence-command-budget.js';
186
230
  import { pressDecisionSignals, type DecisionSignalPressResult } from './decision-signal-press.js';
187
231
  import { inspectDecisionObservations, inspectDecisionSignalKinds, inspectDecisionSignalObservations } from '../../scripts/ask-marker-check.js';
188
232
 
@@ -256,8 +300,9 @@ import type { ClassifyShadowCallLLM } from './classify-shadow.js';
256
300
  import { hasModuleLoadFailure, type GateTestFailure } from './gate-baseline.js';
257
301
  import { commitWorktree, defaultBranchRef, preservationHasChanges } from './seams.js';
258
302
  import { detectUncommittedWork } from './uncommitted-work.js';
259
- import { spawnSync } from 'node:child_process';
260
- import { blockedDraftDisposition, decideDraftOnStop, nextMoveFor, parseDraftOnStopMode, salvageBranchForRun, type DraftOnStopMode } from './blocked-draft-policy.js';
303
+ import { execFile as execFileCallback, spawnSync } from 'node:child_process';
304
+ import { promisify } from 'node:util';
305
+ import { blockedDraftDisposition, blockedDraftTargetFor, decideDraftOnStop, nextMoveFor, parseDraftOnStopMode, repairSalvageLinkComment, salvageBranchForRun, syntheticRepairBasePr, type DraftOnStopMode } from './blocked-draft-policy.js';
261
306
  import { formatLlmMergeOutcome } from '../autopilot/build/llm-conflict-merge.js';
262
307
  import { FOUND_CITED_PATH_REFUTATION_QUOTE, MISSING_CITED_PATH_REFUTATION_QUOTE, MUST_FIX_REFUTATION_ACKNOWLEDGEMENT_WITH_REASON, REFUTATION_QUOTE_GRAMMAR, observeMustFixCitedPaths, parseMustFixRefutationAcknowledgement, parseMustFixRefutations, renderMustFixCitedPathFacts, snapshotMustFixFindings, stableMustFixId, type ReflectEvidenceFacts, type ReflectGateFacts, type MustFixCitedPathFact, type MustFixFinding, type MustFixRecurrenceHistory, type MustFixRefutation, type MustFixRefutationKind } from './reflect-mustfix.js';
263
308
  import type { IngestionEntry } from '../agent-substrate/execution/ingestion-policy.js';
@@ -279,7 +324,8 @@ import { AMBIGUOUS_STAGES, checkPipelineTraversal, nodesForStage, pipelineGraphI
279
324
  import { appendGateWorktreeFreshnessEvidence, gateEvidenceNote } from '../harness/review-adapter.js';
280
325
  import { diffHeaderPaths } from '../agent-substrate/self-review-cli.js';
281
326
  import { format as formatPrComment, type PrCommentRole } from '../agent-substrate/pr-comment-meta.js';
282
- import { changedFiles, commitTitles, type SelfImplementCompletionDisposition } from './seams.js';
327
+ import { changedFiles, commitTitles, type OpenPrOutcome, type SelfImplementCompletionDisposition } from './seams.js';
328
+ import { findUnwiredExports, gitBaseFileReader } from './wiring-check.js';
283
329
  import {
284
330
  classifyAbandonedRun,
285
331
  isAbandonedClassificationOutcome,
@@ -1087,6 +1133,8 @@ export interface SelfImplementSeams {
1087
1133
  commitFinishedChildWork?: (cwd: string, paths: readonly string[], message: string) => { ok: boolean; out: string };
1088
1134
  /** --ground 코드베이스 prepass seam. cwd는 구현 대상 worktree이며 실패는 goal-loop를 막지 않는다. */
1089
1135
  groundGoal?: (goalText: string, deps: { cwd: string }) => Promise<string>;
1136
+ /** E1 GOAL-ELABORATE-ON-ARRIVAL — 착수 구체화 카드 작성·판정 LLM. 미주입이면 카드 없이 진행(`goal-elaboration-skipped`). */
1137
+ elaborateCallLLM?: (args: { prompt: string; systemPrompt?: string }) => Promise<string>;
1090
1138
  /** ③ 구현 — cwd(worktree)에서 코딩 에이전트 구동(P1: 헤드리스 elanous spawn·goal-loop 아밍).
1091
1139
  * escalateTier(#2) — sol 단일 승급으로 재시도하고 seam 이 그 대상을 honor한다. */
1092
1140
  /** ⚠️ `runId` 는 **필수**(리뷰 should-fix) — 오케스트레이터가 항상 보장하므로 옵셔널로 두면 새 seam
@@ -1156,6 +1204,8 @@ export interface SelfImplementSeams {
1156
1204
  /** Test seam for blocked environment branch persistence; return whether the branch was pushed. */
1157
1205
  /** Test seam — the worktree commit to pin before main sync (default `git rev-parse HEAD`). */
1158
1206
  headCommit?: (cwd: string) => string | undefined;
1207
+ /** Test seam for required evidence command execution; production uses its bounded shell runner. */
1208
+ evidenceCommandRunner?: (command: string, cwd: string) => Pick<ReturnType<typeof spawnSync>, 'status' | 'stdout' | 'stderr' | 'error'>;
1159
1209
  /** `commit` pins the pushed state; without it the worktree HEAD is pushed. */
1160
1210
  preserveBlockedBranch?: (ctx: { cwd: string; branch: string; title: string; commit?: string }) => boolean | Promise<boolean>;
1161
1211
  /** DRAFT-NOT-ARCHIVE — `tools.selfImplement.draftOnStop` 읽기 seam. 생략하면 user-config(실패·부재 = 'always' · 종전). */
@@ -1167,9 +1217,13 @@ export interface SelfImplementSeams {
1167
1217
  /** Persist a full oversized PR body so its bounded PR counterpart can link to it. */
1168
1218
  persistPrBodyArtifact?: (input: { origin: string; body: string; originalChars: number }) => { path: string };
1169
1219
  /** ⑥ PR 생성. labels=생성 시 부착할 GitHub 라벨(G8 auto-review 자기판단 통과 시). */
1170
- openPr: (opts: { title: string; body: string; head: string; base?: string; draft?: boolean; labels?: string[]; cwd: string }) => Promise<{ url: string; number: number }>;
1220
+ openPr: (opts: { title: string; body: string; head: string; base?: string; draft?: boolean; labels?: string[]; cwd: string; runId?: string }) => Promise<OpenPrOutcome>;
1171
1221
  /** PR 생성 뒤 런의 라운드 대화를 게시한다. 실패는 PR 개설을 되돌리지 않는다. */
1172
1222
  postPrComment?: (opts: { number: number; body: string; cwd: string }) => Promise<void>;
1223
+ /** Read-only body/state confirmation for the failed-run draft preservation marker. */
1224
+ readPrBodyForHarvest?: (opts: { number: number; cwd: string }) => Promise<{ body: string; state: string; isDraft: boolean } | undefined>;
1225
+ /** Update only the confirmed existing PR body; never creates a PR. */
1226
+ updatePrBodyForHarvest?: (opts: { number: number; body: string; cwd: string }) => Promise<void>;
1173
1227
  /** Read and edit the single marked status comment; missing seams fall back to individual comments. */
1174
1228
  findPrComment?: (opts: { number: number; marker: string; cwd: string; comments?: unknown }) => Promise<{ id: number; body: string } | undefined>;
1175
1229
  editPrComment?: (opts: { id: number; body: string; cwd: string }) => Promise<void>;
@@ -2326,6 +2380,14 @@ export interface SelfImplementResult {
2326
2380
  sessionId?: string;
2327
2381
  worktreePath?: string;
2328
2382
  branch?: string;
2383
+ /** SCOPE-AS-DIRECTION: outside-target files the scope guard accepted, each with its kind; rendered as the PR body's «범위 확장». */
2384
+ scopeExpansion?: ScopeExpansion;
2385
+ /** Bounded names measured by the execution-scope guard on a held edit. */
2386
+ outOfScopeEdits?: string[];
2387
+ /** SCOPE-ESCAPE-AS-REFINE: why the held edit stops (deletion · protected path · cap) — the parent stops only on these. */
2388
+ scopeStopReasons?: ScopeStopReason[];
2389
+ nameCapReached?: boolean;
2390
+ outsideCount?: number;
2329
2391
  gate?: SelfImplementGateResult;
2330
2392
  review?: SelfImplementReview;
2331
2393
  rework?: ReviewRework;
@@ -2366,6 +2428,9 @@ export interface SelfImplementResult {
2366
2428
  mergeReason?: string;
2367
2429
  prUrl?: string;
2368
2430
  prNumber?: number;
2431
+ /** REPAIR-BLOCKED-DRAFT-LINK-ORIGINAL: commit-only 수리가 멈춰 새 PR 대신 원 PR 에 이은 수확 가지. */
2432
+ originalPr?: number;
2433
+ salvageRef?: string;
2369
2434
  checkedHeadCommit?: string;
2370
2435
  detail?: string;
2371
2436
  }
@@ -3490,6 +3555,7 @@ async function autohealRecordedStop(stopEntry: RunLedgerEntry, s: SelfImplementS
3490
3555
  const loadLedger = s?.stopAutohealLoadLedger ?? (s?.writeRunLedger ? () => null : undefined);
3491
3556
  const result = await autohealFromStop({ runId: stopEntry.runId, ...(stopEntry.goalId ? { goalId: stopEntry.goalId } : {}), record }, {
3492
3557
  mode,
3558
+ knowhowCandidateDir: join(effectiveInstanceRoot(), 'self-implement', 'knowhow-candidates'),
3493
3559
  ...(s?.stopAutohealActions ? { actions: s.stopAutohealActions } : {}),
3494
3560
  ...(loadLedger ? { loadLedger } : {}),
3495
3561
  ...(s?.writeRunLedger ? { writeLedger: s.writeRunLedger } : {}),
@@ -3764,6 +3830,7 @@ export async function runSelfImplement(opts: SelfImplementOptions): Promise<Self
3764
3830
  openPr: async (args) => {
3765
3831
  openPrInvoked = true;
3766
3832
  const pr = await opts.seams.openPr(args);
3833
+ if (pr.rebind) debug.log('self-implement.same-cell', 'rebind-result', pr.rebind);
3767
3834
  const number = recordedPrNumber(pr.number);
3768
3835
  if (number !== undefined) capturedPrNumber = number;
3769
3836
  return pr;
@@ -4380,6 +4447,50 @@ export async function runSelfImplement(opts: SelfImplementOptions): Promise<Self
4380
4447
  } finally {
4381
4448
  if (loopRegistered) registerRunLoop('ended');
4382
4449
  const terminalStage = terminalResult?.stage ?? 'crashed';
4450
+ // A blocked draft may be opened on the first failed attempt, before the
4451
+ // normal outcome observer has written its terminal status. Persist the
4452
+ // actual terminal result before exposing harvest-deferred on that PR.
4453
+ const terminalOutcome = terminalResult ? mapStageToRunStatus(terminalStage) : undefined;
4454
+ if (terminalOutcome?.runStatus === 'failed'
4455
+ && loadRunLedger(runId)?.filter((entry) => entry.event === 'run-status').at(-1)?.data.runStatus !== 'failed') {
4456
+ observeOuter('run-status', {
4457
+ stage: terminalStage, node: terminalResult?.node ?? null, ...terminalOutcome,
4458
+ ...(terminalResult?.reviewReflectRejectedCount !== undefined
4459
+ ? { reviewReflectRejectedCount: terminalResult.reviewReflectRejectedCount }
4460
+ : {}),
4461
+ }, { level: 'warn' });
4462
+ }
4463
+ try {
4464
+ const runStatus = terminalOutcome?.runStatus;
4465
+ const prNumber = recordedPrNumber(terminalResult?.prNumber) ?? capturedPrNumber;
4466
+ // openPr is required on every seam (including production); it cannot
4467
+ // distinguish test PRs from real ones. The production adapter explicitly
4468
+ // supplies both body operations. A test replacing openPr without both
4469
+ // body operations must fail closed instead of touching a real PR.
4470
+ const readPrBody = opts.seams.readPrBodyForHarvest;
4471
+ const updatePrBody = opts.seams.updatePrBodyForHarvest;
4472
+ // The terminal observer must have persisted this run's failure before a
4473
+ // draft can advertise harvest deferral. Even an injected writer must
4474
+ // leave a matching record in the canonical ledger before mutation.
4475
+ const lastPersistedStatus = loadRunLedger(runId)?.filter((entry) => entry.event === 'run-status').at(-1)?.data.runStatus;
4476
+ const persistedFailure = runStatus === 'failed' && lastPersistedStatus === 'failed';
4477
+ if (persistedFailure && prNumber !== undefined && readPrBody && updatePrBody) {
4478
+ const existing = await readPrBody({ number: prNumber, cwd: worktreePath ?? process.cwd() });
4479
+ if (existing?.state === 'OPEN' && existing.isDraft === true) {
4480
+ const markedBody = markHarvestDeferredBody({ runStatus, prNumber, body: existing.body });
4481
+ if (markedBody !== undefined && markedBody !== existing.body) {
4482
+ await updatePrBody({ number: prNumber, body: markedBody, cwd: worktreePath ?? process.cwd() });
4483
+ observeOuter('harvest-deferred', { runStatus, prNumber, marker: HARVEST_DEFERRED_MARKER });
4484
+ }
4485
+ } else {
4486
+ observeOuter('harvest-deferred-skipped', { runStatus, prNumber, reason: 'existing-draft-not-confirmed' }, { level: 'warn' });
4487
+ }
4488
+ } else {
4489
+ observeOuter('harvest-deferred-skipped', { runStatus: runStatus ?? null, prNumber: prNumber ?? null, reason: 'status-pr-body-seam-unavailable' }, { level: 'warn' });
4490
+ }
4491
+ } catch (error) {
4492
+ logRunAwareFailSoft(runId, 'harvest-deferred-failed', { error: safeErrorDescription(error) });
4493
+ }
4383
4494
  try {
4384
4495
  const mappedStatus = mapStageToRunStatus(terminalStage)?.runStatus;
4385
4496
  const reworkCapStop = terminalResult?.stage === 'pr-opened' && (
@@ -4727,7 +4838,7 @@ export function observeRunOutcome(
4727
4838
  type RollupPrNumber = number | 'none' | 'unknown';
4728
4839
 
4729
4840
  function recordedPrNumber(value: unknown): number | undefined {
4730
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
4841
+ return typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined;
4731
4842
  }
4732
4843
 
4733
4844
  function rollupPrNumber(
@@ -4855,7 +4966,7 @@ async function runSelfImplementInner(
4855
4966
  const { graphVersionHash } = await import('./graph-yaml.js');
4856
4967
  const { applyGraphOverlays } = await import('./graph-overlay-yaml.js');
4857
4968
  const { createGraphVariant } = await import('./graph-variant.js');
4858
- const { runLedgerPath } = await import('./run-ledger.js');
4969
+ const { saveRunGraphVariant, loadRunGraphVariant } = await import('./run-ledger.js');
4859
4970
  const { stringify } = await import('yaml');
4860
4971
  const baseSpec = GRAPH_SPECS[graphTemplate.graphId];
4861
4972
  const variantRunId = identity?.runId ?? opts.runId;
@@ -4867,16 +4978,16 @@ async function runSelfImplementInner(
4867
4978
  : undefined;
4868
4979
  if (launch && !launch.ok) throw new Error(`graph variant rejected: ${JSON.stringify(launch.rejections)}`);
4869
4980
  const sourceSpec = launch?.ok ? launch.template : baseSpec;
4870
- const variant = createGraphVariant({ template: sourceSpec, goal: `g_${variantRunId.replace(/[^a-z0-9_-]/gi, '_')}`, plan: opts.graphVariantPlan });
4981
+ // ⭐ 최초 변형 선택 — 골 종류(graphGoalType)·대상 경로 수(declaredPremiseScopePaths) 두 입력만으로
4982
+ // 결정론적으로 id·선택 이유를 유도해 검증 결과에 싣는다(종류를 못 읽었으면 지어내지 않는다).
4983
+ const variant = createGraphVariant({ template: sourceSpec, goal: `g_${variantRunId.replace(/[^a-z0-9_-]/gi, '_')}`, plan: opts.graphVariantPlan,
4984
+ ...(graphGoalType === undefined ? {} : { goalAnalysis: { goalType: graphGoalType, targetPathCount: declaredPremiseScopePaths(opts.feature).length } }) });
4871
4985
  if (!variant.ok) throw new Error(`graph variant rejected: ${JSON.stringify(variant.rejections)}`);
4872
4986
  variantSpec = variant.template;
4873
4987
  graphTemplate = { ...specToTemplate(variantSpec), version: graphVersionHash(variantSpec) };
4874
- const { runLedgerDir } = await import('./run-ledger.js');
4875
- const graphFile = `${runLedgerPath(variantRunId)}.graph.yaml`;
4876
- mkdirSync(runLedgerDir(), { recursive: true });
4877
- const { writeFileSync } = await import('node:fs');
4878
- writeFileSync(graphFile, stringify({
4988
+ const graphFile = saveRunGraphVariant(variantRunId, stringify({
4879
4989
  graph_id: variantSpec.graphId, version: variantSpec.version,
4990
+ ...(variant.selection === undefined ? {} : { variant_id: variant.selection.variantId, reason: variant.selection.reason }),
4880
4991
  entry_node: variantSpec.entryNode, terminal_nodes: variantSpec.terminalNodes,
4881
4992
  ...(variantSpec.journeyStages ? { journey_stages: variantSpec.journeyStages } : {}),
4882
4993
  ...(variantSpec.runContract ? { run_contract: variantSpec.runContract } : {}),
@@ -4886,6 +4997,9 @@ async function runSelfImplementInner(
4886
4997
  ...(n.progress ? { progress: n.progress } : {}), ...(n.phases ? { phases: n.phases } : {}),
4887
4998
  ...(n.terminalStages ? { terminal_stages: n.terminalStages } : {}),
4888
4999
  ...(n.fanOut ? { fan_out: n.fanOut } : {}), ...(n.contract ? { contract: n.contract } : {}),
5000
+ ...(n.call ? { call: n.call } : {}),
5001
+ ...(n.callEntry ? { call_entry: n.callEntry } : {}),
5002
+ ...(n.budget ? { budget: { inner_steps: n.budget.innerSteps } } : {}),
4889
5003
  ...(n.skipWhen ? { skip_when: n.skipWhen } : {}),
4890
5004
  })),
4891
5005
  edges: variantSpec.edges.map(e => ({
@@ -4894,9 +5008,17 @@ async function runSelfImplementInner(
4894
5008
  ...(e.observed === undefined ? {} : { observed: e.observed }),
4895
5009
  ...(e.when ? { when: e.when } : {}),
4896
5010
  })),
4897
- }), { flag: 'wx' });
5011
+ }));
5012
+ // ⭐ 저장·diff — 방금 원장 옆에 쓴 선택(id·이유)을 다시 읽어 «같은지» 확인한다(다르면 이 런의 그래프 신원이 거짓).
5013
+ if (variant.selection !== undefined) {
5014
+ const persisted = loadRunGraphVariant(variantRunId);
5015
+ if (persisted === null || persisted.variantId !== variant.selection.variantId || persisted.reason !== variant.selection.reason) {
5016
+ throw new Error(`graph variant rejected: persisted selection mismatch: ${JSON.stringify(persisted)}`);
5017
+ }
5018
+ }
4898
5019
  observe('graph-variant-applied', { graphId: variant.template.graphId, overlayId: variant.overlay.overlayId,
4899
- graphFile, patches: variant.patches });
5020
+ graphFile, patches: variant.patches,
5021
+ ...(variant.selection === undefined ? {} : { variantId: variant.selection.variantId, variantReason: variant.selection.reason }) });
4900
5022
  }
4901
5023
  /** 단계 이름 → 그 템플릿의 노드 이름. */
4902
5024
  const node = (stage: PipelineNodeId): PipelineNodeId => nodeNameForStage(stage, graphTemplate) as PipelineNodeId;
@@ -5018,6 +5140,8 @@ async function runSelfImplementInner(
5018
5140
  observe('start', {
5019
5141
  feature: boundedFeature.text, featureTruncated: boundedFeature.truncated, featureOriginalChars: boundedFeature.originalChars,
5020
5142
  branch, base: opts.base ?? null, draft: opts.draft ?? true,
5143
+ // OPT #25551: 런 모드가 원장에 없었다 — PR 개설 의도 ⊕ commit-only 수리의 원 PR 번호(합성 base pr-<N>).
5144
+ openPr: opts.completion === undefined ? null : opts.completion !== 'worktree-only', repairCommitOnly: syntheticRepairBasePr(opts.base) ?? null,
5021
5145
  willFork: !!(opts.parentSessionId && s.forkSession), parentSessionId: opts.parentSessionId ?? null,
5022
5146
  nestDepth: nestInfo().depth, goalSource, goalFile: opts.goalFile === undefined ? null : resolve(launchCwd, opts.goalFile),
5023
5147
  targetRoot: gitRootOf(launchCwd) ?? launchCwd, ...originObservationFields(),
@@ -5075,6 +5199,14 @@ async function runSelfImplementInner(
5075
5199
  ...goalContext,
5076
5200
  }), T.worktree, 'worktree');
5077
5201
  onWorktreeCreated(wt.path);
5202
+ // Capture the child worktree's HEAD at creation. `wt.invokedHead` names the
5203
+ // caller checkout and may differ after base selection or PR-source checkout.
5204
+ const terminalLaunchHeadRead = runGitCommand(wt.path, ['rev-parse', '--verify', 'HEAD'], { encoding: 'utf8', timeout: 10_000 });
5205
+ const terminalLaunchHeadCandidate = terminalLaunchHeadRead.status === 0 ? terminalLaunchHeadRead.stdout.trim() : '';
5206
+ const terminalLaunchHead = /^[0-9a-f]{40,64}$/i.test(terminalLaunchHeadCandidate) ? terminalLaunchHeadCandidate : undefined;
5207
+ const terminalLaunchWork = detectUncommittedWork(wt.path);
5208
+ const terminalLaunchDirtyPaths = terminalLaunchWork.status === 'unavailable' ? undefined
5209
+ : new Set([...terminalLaunchWork.trackedChanges, ...terminalLaunchWork.untrackedFiles]);
5078
5210
  // ⭐ 제1원칙 — **어디서 갈랐나**를 관측에 남긴다. 이것이 없어서 2026-07-29 에 하니스 런 둘이
5079
5211
  // `main` 위에서 돌았고(호출자가 브랜치 워크트리에서 발사했는데도) 산출 diff 를 눈으로 봐야 알았다.
5080
5212
  // ⚠️ `branch` 는 **새로 만든 브랜치 이름**이라 그 질문에 답하지 않는다.
@@ -5088,6 +5220,8 @@ async function runSelfImplementInner(
5088
5220
  observe('worktree', {
5089
5221
  path: wt.path,
5090
5222
  branch: wt.branch,
5223
+ terminalLaunchHead: terminalLaunchHead ?? null,
5224
+ terminalLaunchDirtyPaths: terminalLaunchDirtyPaths ? [...terminalLaunchDirtyPaths] : null,
5091
5225
  // ⭐ 우리가 **무엇을 요청했는지는 이미 안다** — 시임 반환에서 되읽지 않는다.
5092
5226
  // 커스텀 시임이 관측 필드를 생략하면 명시/생략이 둘 다 null 이 되어 구분이 사라진다(리뷰 must-fix).
5093
5227
  requestedBase,
@@ -5259,6 +5393,14 @@ async function runSelfImplementInner(
5259
5393
  if (knowhow.text) round0Feature = `${knowhow.text}\n\n${round0Feature}`;
5260
5394
  observe('knowhow-pack', { ids: knowhow.ids, bytes: knowhow.bytes, injected: knowhow.bytes > 0 });
5261
5395
 
5396
+ // E1 착수 구체화(RFC-progressive-goal-elaboration §2 E1 · §7 간선 ①) — 고정 층(KPI·판정 신호)은 그대로, 카드만 덧붙인다.
5397
+ const elaboration = await (await import('./goal-elaborate.js')).runArrivalElaboration({ goal: opts.feature, prompt: round0Feature, cwd: wt.path, callLLM: s.elaborateCallLLM, observe });
5398
+ round0Feature = elaboration.prompt;
5399
+ if (elaboration.parked) {
5400
+ progress('parked', '착수 구체화 카드가 골 고정 층과 어긋남(다시 쓰기 뒤에도) — 사람 판단 대기');
5401
+ return { ok: false, stage: 'parked', node: 'implement', ...resolveRunOutcome({ termination: 'abandoned' }), sessionId, worktreePath: wt.path, branch: wt.branch, detail: elaboration.detail };
5402
+ }
5403
+
5262
5404
  const maxRework = Math.max(0, opts.maxReworkRounds ?? 2);
5263
5405
  const selfImplementConfig = (await import('../user-config.js')).getUserConfig().tools.selfImplement;
5264
5406
  const shadowStop = opts.reworkBudgetShadowStop ?? selfImplementConfig.reworkBudget.shadowStop;
@@ -5290,6 +5432,8 @@ async function runSelfImplementInner(
5290
5432
  let gate!: SelfImplementGateResult;
5291
5433
  /** GATE-ENV-RETRY: 재시도 뒤에도 남은 환경 결손의 종류. 정의되면 이 라운드의 gate 실패는 «수확 대기»로 끝난다. */
5292
5434
  let gateEnvDeficitKind: GateEnvDeficitKind | undefined;
5435
+ /** SCOPE-AS-DIRECTION: outside-target files accepted by the scope guard (latest round); rendered in the PR body. */
5436
+ let scopeExpansion: ScopeExpansion | undefined;
5293
5437
  let review: SelfImplementReview | undefined;
5294
5438
  let reviewedHeadCommit: string | undefined;
5295
5439
  /** Review-budget leftovers and the body that carried them, so a later merge drafts from the same text. */
@@ -5609,9 +5753,17 @@ async function runSelfImplementInner(
5609
5753
  };
5610
5754
  }
5611
5755
  let round = 0;
5756
+ // A timeout is evidence about this command, not an invitation to spend the
5757
+ // next rework round on the identical oversized check.
5758
+ const runBudgetedEvidenceChecks = createRequiredEvidenceBudget({ run: s.evidenceCommandRunner });
5612
5759
  // A goal-only retry spends its one allowance for this run even if a later
5613
5760
  // gate/review round removes the target diff and reaches the same disposition.
5614
5761
  let goalOnlyReworkUsed = false;
5762
+ // E3 GOAL-REFINE-FROM-FIRST-IMPL — 첫 라운드 뒤 골 v2(재그라운딩). 둘째 라운드부터 프롬프트의 골은 roundGoal 이다.
5763
+ // 방향·KPI 줄은 불변(goal-refine.ts 가 강제) · 되돌이는 런당 GOAL_REFINE_MAX_VISITS 번.
5764
+ let roundGoal = opts.feature;
5765
+ let goalRefineVisits = 0;
5766
+ let goalRefinement: import('./goal-refine.js').GoalRefinement | undefined;
5615
5767
  // PR이 열리기 전에 프로세스가 죽으면 PR 자체가 없으므로 잃을 대화도 없다. 따라서 파일로 영속화하지 않는다.
5616
5768
  const prCommentBuffer: string[] = [];
5617
5769
  // GitHub PR comment bodies are bounded; retain the RFC header and disclose omitted source rather than losing the whole record.
@@ -5730,10 +5882,12 @@ async function runSelfImplementInner(
5730
5882
  };
5731
5883
  let blockedDraftNoChanges = false;
5732
5884
  let blockedDraftPrFailure: string | undefined;
5885
+ let repairLink: { originalPr: number; salvageRef: string } | undefined;
5733
5886
  const reviewBlockedResult = (pr: { url: string; number: number } | undefined) => ({
5734
5887
  stage: blockedDraftNoChanges && podReviewBlockedDraft ? 'no-changes' as const : podReviewBlockedDraft && !pr ? 'aborted' as const : 'review-blocked' as const,
5735
5888
  mustFix: [...(review?.mustFix ?? [])],
5736
5889
  ...(pr ? { prUrl: pr.url, prNumber: pr.number } : {}),
5890
+ ...(repairLink ?? {}),
5737
5891
  });
5738
5892
  const preserveBlockedArtifacts = async ({ stage, reason, verdict, gate: preservedGate, typecheck, decomposition, childSummary, reasonTruncated, failureKind, terminalStatus, salvageStatusExpected }: { stage: 'review-blocked' | 'gate-failed' | 'aborted'; reason: string; verdict?: ReworkBudgetVerdict; gate?: SelfImplementGateResult; typecheck?: { passed: boolean; log?: string }; decomposition?: TerminalDecomposition; childSummary?: string; reasonTruncated?: boolean; failureKind?: ReturnType<typeof classifyReviewProviderFailure> | null; terminalStatus?: ImplementTerminalStatus; salvageStatusExpected: boolean }): Promise<{ url: string; number: number } | undefined> => {
5739
5893
  let childSummaryArtifact: ChildSummaryArtifactRef | undefined;
@@ -5940,6 +6094,47 @@ async function runSelfImplementInner(
5940
6094
  progress(stage, '보존할 변경이 없어 draft PR을 열지 않음');
5941
6095
  return undefined;
5942
6096
  }
6097
+ // REPAIR-BLOCKED-DRAFT-LINK-ORIGINAL: 합성 base pr-<N>(commit-only 수리)은 origin 에 없다 — 새 draft 대신 수확 가지를 원 PR #N 에 잇는다.
6098
+ const blockedTarget = blockedDraftTargetFor(opts.base);
6099
+ if (blockedTarget.action === 'link-original') {
6100
+ const salvageRef = salvageBranchForRun(runId, wt.branch);
6101
+ let salvageSha: string | undefined;
6102
+ let pushError: string | undefined;
6103
+ try {
6104
+ if (s.preserveBlockedBranch) {
6105
+ if (!await s.preserveBlockedBranch({ cwd: wt.path, branch: salvageRef, title: prTitle(opts.feature, opts.goalFile) })) throw new Error('수확 가지 push가 성공하지 않았음');
6106
+ } else {
6107
+ const commit = commitWorktree(wt.path, prTitle(opts.feature, opts.goalFile));
6108
+ if (!commit.ok && !/nothing to commit/.test(commit.out)) throw new Error(`로컬 커밋 실패: ${commit.out}`);
6109
+ const push = runGitCommand(wt.path, ['push', 'origin', `HEAD:refs/heads/${salvageRef}`]);
6110
+ if (push.status !== 0) throw new Error(push.stderr || push.stdout || 'git push failed');
6111
+ }
6112
+ const head = existsSync(wt.path) ? runGitCommand(wt.path, ['rev-parse', 'HEAD']) : undefined;
6113
+ if (head?.status === 0) salvageSha = head.stdout.trim();
6114
+ } catch (error) {
6115
+ pushError = safeErrorDescription(error);
6116
+ }
6117
+ let commentError: string | undefined;
6118
+ if (pushError === undefined) {
6119
+ try {
6120
+ if (!s.postPrComment) throw new Error('postPrComment seam unavailable');
6121
+ await s.postPrComment({ number: blockedTarget.originalPr, body: repairSalvageLinkComment({ salvageRef, ...(salvageSha ? { sha: salvageSha } : {}), runId, stage }), cwd: wt.path });
6122
+ } catch (error) {
6123
+ commentError = safeErrorDescription(error);
6124
+ }
6125
+ }
6126
+ if (pushError === undefined) repairLink = { originalPr: blockedTarget.originalPr, salvageRef };
6127
+ observe('rework-blocked-draft-pr', {
6128
+ ...observation, skipped: 'repair-link-original', originalPr: blockedTarget.originalPr, salvageRef,
6129
+ ...(salvageSha ? { salvageSha } : {}), pushed: pushError === undefined, ...(pushError ? { pushError } : {}),
6130
+ commentPosted: pushError === undefined && commentError === undefined, ...(commentError ? { commentError } : {}),
6131
+ }, pushError || commentError ? { level: 'warn' } : undefined);
6132
+ blockedDraftPrFailure = pushError
6133
+ ? `수리 산출물 수확 가지 push 실패(원 PR #${blockedTarget.originalPr} · 새 PR 안 엶): ${pushError}; worktree: ${wt.path}`
6134
+ : `수리 산출물을 기존 PR #${blockedTarget.originalPr} 에 연결: salvage ${salvageRef}${commentError ? ` (코멘트 실패: ${commentError})` : ''}`;
6135
+ progress('aborted', blockedDraftPrFailure);
6136
+ return undefined;
6137
+ }
5943
6138
  // DRAFT-NOT-ARCHIVE (RFC R1): harvestable 멈춤은 draft PR 대신 수확 가지 ⊕ 런 원장(사유·다음 수).
5944
6139
  // ⛔ Pod review-blocked 는 결과 stage 가 PR 유무로 갈리므로 이 조각에서는 건드리지 않는다.
5945
6140
  const draftOnStopMode = readDraftOnStopMode();
@@ -6051,6 +6246,7 @@ async function runSelfImplementInner(
6051
6246
  try {
6052
6247
  pr = await withStepTimeout(s.openPr({
6053
6248
  title: prTitle(opts.feature, opts.goalFile),
6249
+ runId,
6054
6250
  body: assembled.body,
6055
6251
  head: wt.branch,
6056
6252
  ...(opts.base ? { base: opts.base } : {}),
@@ -6097,6 +6293,9 @@ async function runSelfImplementInner(
6097
6293
  : `중단 산출물의 draft PR 생성 실패(worktree·branch 보존 · 판정 본문 보존 실패: ${artifactError ?? 'unknown error'})`);
6098
6294
  return undefined;
6099
6295
  }
6296
+ // The production draft sweep resolves run ownership from pr-opened, not
6297
+ // from the blocked-draft diagnostic event. Bind this PR to the same run.
6298
+ observe('pr-opened', { url: pr.url, number: pr.number, branch: wt.branch, draft: true });
6100
6299
  observe('rework-blocked-draft-pr', {
6101
6300
  ...observation,
6102
6301
  url: pr.url,
@@ -6199,7 +6398,7 @@ async function runSelfImplementInner(
6199
6398
  // and pushes this worktree after the note is written and before creating the PR.
6200
6399
  addNextMdReleaseNote(wt.path, releaseNote);
6201
6400
  const preparedPrBody = preparePrBody(
6202
- `${prBody(opts.feature, impl.summary, gate.log, review, reviewIntent, undefined, harvestedForPr(), opts.goalFile, lastPlanRevision, releaseNote)}${followUpMustFix}`,
6401
+ `${prBody(roundGoal, impl.summary, gate.log, review, reviewIntent, undefined, harvestedForPr(), opts.goalFile, lastPlanRevision, releaseNote)}${renderScopeExpansionSection(scopeExpansion)}${goalRefinement ? `\n\n${(await import('./goal-refine.js')).renderGoalChangeSection(goalRefinement)}` : ''}${followUpMustFix}`,
6203
6402
  s.persistPrBodyArtifact,
6204
6403
  'self-implement-review-budget-pr',
6205
6404
  followUpMustFix,
@@ -6207,6 +6406,7 @@ async function runSelfImplementInner(
6207
6406
  preparedReviewBudgetPrBody = preparedPrBody.body;
6208
6407
  const pr = await withStepTimeout(s.openPr({
6209
6408
  title: prTitle(opts.feature, opts.goalFile),
6409
+ runId,
6210
6410
  body: preparedPrBody.body,
6211
6411
  head: wt.branch,
6212
6412
  ...(opts.base ? { base: opts.base } : {}),
@@ -6365,7 +6565,7 @@ async function runSelfImplementInner(
6365
6565
  const predictionAccuracyBefore = supervisorDecisionHistory.length
6366
6566
  ? judgePredictionAccuracy(supervisorDecisionHistory)
6367
6567
  : undefined;
6368
- diagnosis = await withStepTimeout(s.diagnose({ runId, note: reworkJudgeNote, kind: reworkKind, round, cwd: wt.path, goal: opts.feature, history: priorHistory, supervisorDecisionHistory, ...(predictionAccuracyBefore ? { judgePredictionAccuracy: predictionAccuracyBefore } : {}), effectiveMax, priorRuns, reviewFindingTelemetry: reviewFindingTelemetrySnapshot, ...(diagnosisRefutations ? { refutations: diagnosisRefutations.refutations, refutationRound: diagnosisRefutations.round } : {}), purpose: 'budget' }), T.review, 'review');
6568
+ diagnosis = await withStepTimeout(s.diagnose({ runId, note: reworkJudgeNote, kind: reworkKind, round, cwd: wt.path, goal: roundGoal, history: priorHistory, supervisorDecisionHistory, ...(predictionAccuracyBefore ? { judgePredictionAccuracy: predictionAccuracyBefore } : {}), effectiveMax, priorRuns, reviewFindingTelemetry: reviewFindingTelemetrySnapshot, ...(diagnosisRefutations ? { refutations: diagnosisRefutations.refutations, refutationRound: diagnosisRefutations.round } : {}), purpose: 'budget' }), T.review, 'review');
6369
6569
  const diagnosedDecision = parseReworkBudgetDecision(diagnosis);
6370
6570
  if (diagnosedDecision?.verdict === 'CONTRACT-CONFLICT') lastSupervisorVerdict = diagnosedDecision.verdict;
6371
6571
  let parsedDecision = diagnosedDecision;
@@ -6809,7 +7009,7 @@ async function runSelfImplementInner(
6809
7009
  if (escalationEligible && s.diagnose) {
6810
7010
  try {
6811
7011
  escalationJudgement = await withStepTimeout(s.diagnose({
6812
- runId, note: reworkNote, kind: reworkKind, round, cwd: wt.path, goal: opts.feature,
7012
+ runId, note: reworkNote, kind: reworkKind, round, cwd: wt.path, goal: roundGoal,
6813
7013
  history: reworkHistory.slice(0, -1), supervisorDecisionHistory, effectiveMax,
6814
7014
  purpose: 'escalation-triage',
6815
7015
  }), T.review, 'review');
@@ -6822,8 +7022,24 @@ async function runSelfImplementInner(
6822
7022
  }, { level: 'warn' });
6823
7023
  }
6824
7024
  }
7025
+ // 라운드 «번호»가 아니라 «첫 gate·리뷰 지적을 받은 뒤 첫 rework 진입»에서 한 번 — goal-only-rework·증거 되먹임이
7026
+ // 번호를 당겨도(round = retryRound/nextRound) 한 번 돈다(리뷰 r1 should-fix 6).
7027
+ if (round > 0 && goalRefineVisits === 0 && reworkNote.trim().length > 0) {
7028
+ goalRefineVisits++;
7029
+ // ta-journey author-dialogue 되돌이(judge findings → author → deliver v2) — 노트 LLM 은 E1 과 같은 저작 래퍼를 쓴다.
7030
+ const firstRound = roundSummaryEntries.at(-1);
7031
+ const refined = await (await import('./goal-refine.js')).runFirstRoundRefine({
7032
+ goal: opts.feature, round, visit: goalRefineVisits, callLLM: s.elaborateCallLLM, observe,
7033
+ // SCOPE-ESCAPE-AS-REFINE — accepted out-of-scope edits are the «new scope» the first implementation found.
7034
+ evidence: { implSummary: firstRound?.tried, findings: reworkNote, changedFiles: firstRound?.filesTouched,
7035
+ ...(scopeExpansion?.files.length ? { newScope: scopeExpansion.files.map((file) => file.path) } : {}) },
7036
+ });
7037
+ roundGoal = refined.goal;
7038
+ // PR «골 변경» 절 — 유지(kept · no-provider 포함)여도 «시도 · v1 유지 · 사유» 한 줄을 싣는다(리뷰 r2).
7039
+ goalRefinement = refined.refinement;
7040
+ }
6825
7041
  const reworkFeature = round === 0 ? ''
6826
- : buildReworkFeature(opts.feature, round, effectiveMax, reworkPromptNote, stripReworkBudgetHeaders(diagnosis), appliedLastRound, refutableFindings, pendingPlanRevision, reworkKind, buildRefutationGuidance(), escalationJudgement);
7042
+ : buildReworkFeature(roundGoal, round, effectiveMax, reworkPromptNote, stripReworkBudgetHeaders(diagnosis), appliedLastRound, refutableFindings, pendingPlanRevision, reworkKind, buildRefutationGuidance(), escalationJudgement);
6827
7043
  const card = round === 0 ? '' : renderRoundSummaryCard(roundSummaryEntries);
6828
7044
  const feature = round === 0 ? round0Feature : reworkFeature + (card ? `\n\n${card}` : '');
6829
7045
  if (card) {
@@ -7046,6 +7262,45 @@ async function runSelfImplementInner(
7046
7262
  }
7047
7263
  }
7048
7264
  }
7265
+ // The child can report changed=false after committing its edits. Compare
7266
+ // against the worktree HEAD captured at creation, not the caller's HEAD or
7267
+ // origin/main: a PR source already had a diff before the child ran.
7268
+ if (!impl.ok && impl.completionDisposition === 'completed-without-changes'
7269
+ && impl.terminalStatus?.reached === true && impl.terminalStatus.timedOut === false
7270
+ && !hasCurrentProviderError() && !hasCurrentCredentialFailure()) {
7271
+ const committed = terminalLaunchHead
7272
+ ? runGitCommand(wt.path, ['diff', '--name-only', '-z', terminalLaunchHead, 'HEAD'], { encoding: 'utf8', timeout: 10_000 })
7273
+ : undefined;
7274
+ const pending = detectUncommittedWork(wt.path);
7275
+ const observedFiles = committed?.status === 0 && pending.status !== 'unavailable'
7276
+ ? [...new Set([
7277
+ ...committed.stdout.split('\0').filter(Boolean),
7278
+ ...pending.trackedChanges, ...pending.untrackedFiles,
7279
+ ])]
7280
+ : [];
7281
+ if (!terminalLaunchHead || terminalLaunchDirtyPaths === undefined || committed?.status !== 0 || pending.status === 'unavailable') {
7282
+ observe('terminal-change-evidence', { round, status: 'unmeasured',
7283
+ reason: !terminalLaunchHead ? 'launch-head-unavailable' : terminalLaunchDirtyPaths === undefined
7284
+ ? 'launch-status-unavailable' : committed?.status !== 0 ? 'git-diff-unavailable' : 'git-status-unavailable' }, { level: 'warn' });
7285
+ }
7286
+ // A PR-source worktree may be dirty before this child starts. A path
7287
+ // already dirty at launch cannot prove this child's edits from names
7288
+ // alone, even if the child later commits it. Leave that path unmeasured.
7289
+ const implementationFiles = terminalLaunchDirtyPaths === undefined ? [] : observedFiles.filter(path =>
7290
+ !terminalLaunchDirtyPaths.has(path) && !harnessSeededPaths.includes(path) && !isHarnessTempArtifact(path));
7291
+ const preexistingDirtyPaths = terminalLaunchDirtyPaths === undefined ? [] : observedFiles.filter(path =>
7292
+ terminalLaunchDirtyPaths.has(path) && !harnessSeededPaths.includes(path) && !isHarnessTempArtifact(path));
7293
+ if (preexistingDirtyPaths.length > 0) observe('terminal-change-evidence', {
7294
+ round, status: 'unmeasured', reason: 'preexisting-dirty-path', paths: preexistingDirtyPaths,
7295
+ }, { level: 'warn' });
7296
+ if (implementationFiles.length > 0) {
7297
+ observe('terminal-change-reconciled', {
7298
+ round, source: 'post-launch-git-diff', launchHead: terminalLaunchHead, childDisposition: impl.completionDisposition,
7299
+ paths: implementationFiles, pathCount: implementationFiles.length,
7300
+ });
7301
+ impl = { ...impl, ok: true, completionDisposition: undefined };
7302
+ }
7303
+ }
7049
7304
  // A finished child can leave edits without a commit. Measure them before any
7050
7305
  // diff/no-changes classification, and commit only paths declared in the goal.
7051
7306
  finishedChildCommitMissing = false;
@@ -7075,12 +7330,12 @@ async function runSelfImplementInner(
7075
7330
  const declared = goalDocument === undefined ? undefined : declaredPathsFromGoalDocumentText(goalDocument);
7076
7331
  const targets = declared?.readable
7077
7332
  ? declared.paths
7078
- : inferHotPaths(targetScopedGoalText(opts.feature));
7333
+ : inferHotPaths(targetScopedGoalText(roundGoal));
7079
7334
  const eligible = [...new Set([...work.trackedChanges, ...work.untrackedFiles])]
7080
7335
  .filter((path) => !harnessSeededPaths.includes(path)
7081
7336
  && targets.some((target) => changedFileIsInsideDeclaredTarget(path, target)));
7082
7337
  if (eligible.length) {
7083
- inspectStaleReverts(revertGuardTargetPaths(opts.feature, goalDocument));
7338
+ inspectStaleReverts(revertGuardTargetPaths(roundGoal, goalDocument)); // E3 — refine 뒤 v2 «대상 경로»
7084
7339
  const message = `self-implement: ${prTitle(opts.feature, opts.goalFile)}`;
7085
7340
  let outcome: { ok: boolean; out: string };
7086
7341
  try {
@@ -7148,9 +7403,16 @@ async function runSelfImplementInner(
7148
7403
  const evidenceText = diffEvidence ? `${childEvidenceSource}\n${diffEvidence}` : childEvidenceSource;
7149
7404
  evidenceSource = diffEvidence ? 'diff-added-lines' : harvested ? 'harvested' : 'summary-tail';
7150
7405
  offDiffEvidence = parseOffDiffEvidence(evidenceText);
7151
- const requiredEvidence = requiredEvidenceFromGoal(opts.feature);
7152
- const limitationCount = authorLimitationCountFromGoal(opts.feature);
7153
- const evidenceChecks = runRequiredEvidenceChecks(opts.feature, wt.path, runId);
7406
+ // E3 — refine 뒤 라운드는 «현재 골»(v2)로 증거를 센다(REQUIRED EVIDENCE 절은 고정 칸이라 v1 과 같다).
7407
+ const requiredEvidence = requiredEvidenceFromGoal(roundGoal);
7408
+ const limitationCount = authorLimitationCountFromGoal(roundGoal);
7409
+ const evidenceHead = resolveEvidenceHeadCommit(s.headCommit?.(wt.path), () =>
7410
+ runGitCommand(wt.path, ['rev-parse', '--verify', 'HEAD'], { encoding: 'utf8', timeout: 10_000 }).stdout.trim());
7411
+ if (!evidenceHead) {
7412
+ try { debug.log('self-implement.evidence', 'command-budget-head-unresolved', { runId, round, cwd: wt.path }); }
7413
+ catch { /* observation is fail-soft */ }
7414
+ }
7415
+ const evidenceChecks = runBudgetedEvidenceChecks(roundGoal, wt.path, runId, evidenceHead);
7154
7416
  const tagCoverage = coverRequiredEvidence(requiredEvidence, offDiffEvidence.items);
7155
7417
  // EVIDENCE-WIRING-EXEMPT — a requirement whose own `|| bun test …` check passed is covered by what the harness measured.
7156
7418
  const settledByCheck = settleUncoveredEvidence(tagCoverage.uncovered, { checks: evidenceChecks, required: requiredEvidence });
@@ -7244,6 +7506,7 @@ async function runSelfImplementInner(
7244
7506
  // Unknown declaration or changed files cannot justify an invented choice.
7245
7507
  let gateRouteFiles: readonly string[] | undefined;
7246
7508
  try { gateRouteFiles = (s.changedFilesForGateRoute ?? changedFiles)(wt.path); } catch { gateRouteFiles = undefined; }
7509
+ scopeExpansion = undefined;
7247
7510
  if (opts.goalFile) {
7248
7511
  let goalDocument: string | undefined;
7249
7512
  try { goalDocument = readFileSync(opts.goalFile, 'utf8'); } catch { /* unknown scope */ }
@@ -7257,20 +7520,24 @@ async function runSelfImplementInner(
7257
7520
  observe('execution-scope-undeclared', { outsideCount: scope.outsideCount });
7258
7521
  progress('implementing', `⚠️ 대상 경로를 하나도 못 읽었다 — 범위 밖 ${scope.outsideCount}개를 묻지 않고 게이트로 간다`);
7259
7522
  } else if (scope.status === 'known' && scope.outsideCount !== null && scope.outsideCount > 0) {
7260
- const impact = scope.outsideNames.some(file => {
7523
+ // SCOPE-AS-DIRECTION — target paths are the starting point: outside edits are accepted by default and named for the
7524
+ // reviewer. Only a deletion, a protected path, or more than SCOPE_EXPANSION_CAP outside files stops for the owner.
7525
+ const deleted = scope.outsideNames.filter(file => {
7261
7526
  if (existsSync(join(wt.path, file))) return false;
7262
7527
  const tracked = runGitCommand(wt.path, ['ls-files', '--error-unmatch', '--', file], { encoding: 'utf8', timeout: 20_000 });
7263
7528
  return tracked.status === 0;
7264
- }) ? 'critical' : 'high';
7529
+ });
7530
+ const impact = deleted.length > 0 ? 'critical' : 'high';
7265
7531
  const declaredPaths = declaredPathsFromGoalDocumentText(goalDocument!).paths;
7266
- const { adjacent, other } = classifyOutOfScope(scope.outsideNames, declaredPaths);
7267
- // Only edits next to a declared file, none of them a deletion: the gate judges them — nobody has to answer first.
7268
- const adjacentOnly = impact !== 'critical' && !scope.nameCapReached && other.length === 0 && adjacent.length === scope.outsideCount;
7269
- if (adjacentOnly) {
7270
- observe('execution-scope-adjacent-accepted', { outsideCount: scope.outsideCount, adjacent });
7271
- progress('implementing', `범위 밖 인접 편집 ${adjacent.length}개(대상과 같은 폴더) — 묻지 않고 게이트로 간다: ${adjacent.join(' · ')}`);
7532
+ const decision = decideScopeExpansion({ outsideFiles: scope.outsideNames, declaredPaths, deleted, nameCapReached: scope.nameCapReached,
7533
+ readFile: file => { try { return readFileSync(join(wt.path, file), 'utf8'); } catch { return undefined; } } });
7534
+ if (decision.accept) {
7535
+ scopeExpansion = decision.expansion;
7536
+ observe('execution-scope-accepted', { outsideCount: scope.outsideCount, count: decision.expansion.count, cap: SCOPE_EXPANSION_CAP,
7537
+ files: decision.expansion.files, round });
7538
+ progress('implementing', `범위 확장 ${decision.expansion.count}개 수용 — 대상 경로는 출발점, PR 본문 «범위 확장»에서 리뷰가 판단한다: ${decision.expansion.files.map(file => `${file.path}(${file.kind})`).join(' · ')}`);
7272
7539
  }
7273
- const result: ExecutionClarificationResult = adjacentOnly ? { choice: 'Expand scope', by: 'assumed' } : await (s.askExecutionClarification ?? askAtExecution)({
7540
+ const result: ExecutionClarificationResult = decision.accept ? { choice: 'Expand scope', by: 'assumed' } : await (s.askExecutionClarification ?? askAtExecution)({
7274
7541
  id: 'execution_scope', decision: 'Changing files outside the authored target paths',
7275
7542
  prompt: 'Implementation changed files outside the authored target paths. Keep the original scope or expand it?',
7276
7543
  whyNow: 'Continuing to gate or publish these edits would expand the requested scope.',
@@ -7280,11 +7547,18 @@ async function runSelfImplementInner(
7280
7547
  { label: 'Expand scope', description: 'Accept the changed files outside the target paths.' },
7281
7548
  ],
7282
7549
  }, { runId, outsideFiles: scope.outsideNames, outsideCount: scope.outsideCount, declaredPaths }, { writeRunLedger: s.writeRunLedger });
7550
+ if (!decision.accept && !('parked' in result) && !('deferred' in result) && result.choice === 'Expand scope') scopeExpansion = decision.expansion;
7283
7551
  if ('parked' in result || 'deferred' in result || result.choice !== 'Expand scope') {
7284
7552
  finalizeSupervisorDeliveries('execution-scope-not-approved');
7285
- observe('execution-scope-held', { outsideCount: scope.outsideCount, disposition: 'parked' in result ? 'parked' : 'in-scope-only' });
7553
+ const outOfScopeEdits = [...scope.outsideNames];
7554
+ observe('execution-scope-held', { outOfScopeEdits, nameCapReached: scope.nameCapReached,
7555
+ outsideCount: scope.outsideCount, worktreePath: wt.path, branch: wt.branch,
7556
+ disposition: 'parked' in result ? 'parked' : 'in-scope-only',
7557
+ ...(!decision.accept ? { stopReasons: decision.reasons, deleted: decision.deleted, protectedPaths: decision.protectedPaths, cap: SCOPE_EXPANSION_CAP } : {}),
7558
+ files: decision.expansion.files });
7286
7559
  if ('parked' in result) progress('parked', `critical 질문 ${result.questionId} 미응답 — 이 런만 대기`);
7287
7560
  return { ok: false, stage: 'parked' in result ? 'parked' : 'soft-stopped', node: 'implement', ...resolveRunOutcome({ termination: 'abandoned' }), sessionId, worktreePath: wt.path, branch: wt.branch,
7561
+ outOfScopeEdits, ...(!decision.accept ? { scopeStopReasons: decision.reasons } : {}), nameCapReached: scope.nameCapReached, outsideCount: scope.outsideCount,
7288
7562
  detail: 'parked' in result ? `critical-unanswered: ${result.questionId}` : 'Out-of-scope edits held in the worktree; gate and publication skipped.' };
7289
7563
  }
7290
7564
  }
@@ -7581,6 +7855,33 @@ async function runSelfImplementInner(
7581
7855
  if (untracked.status === 0) untrackedFiles = untracked.stdout.split(/\r?\n/).filter(Boolean);
7582
7856
  } catch { /* change discovery must not stop review */ }
7583
7857
  }
7858
+ // Gate has passed. Measure newly exported runtime values before review, without
7859
+ // turning a static-analysis guess into a rework verdict during the first rollout.
7860
+ const wiringFiles = [...new Set([...(runFacts.changedFiles ?? []), ...(gateRouteFiles ?? []), ...untrackedFiles])];
7861
+ if (wiringFiles.some((file) => /^(?:src|scripts|apps\/pwa\/src)\/.*\.tsx?$/.test(file))) {
7862
+ const wiringBase = wt.resolvedBase;
7863
+ const wiring = wiringBase && /^[0-9a-f]{40}$/i.test(wiringBase)
7864
+ ? findUnwiredExports({
7865
+ cwd: wt.path,
7866
+ changedFiles: wiringFiles,
7867
+ // Timeouts and git errors throw → recorded as `failure`, never as "absent at base".
7868
+ readBaseFile: gitBaseFileReader(
7869
+ (args) => runGitCommand(wt.path, args, { encoding: 'utf8', timeout: 10_000 }),
7870
+ wiringBase,
7871
+ ),
7872
+ })
7873
+ : { checked: 0, unwired: [], failure: 'resolved-base-unavailable' };
7874
+ const wiringObservation = {
7875
+ round,
7876
+ checked: wiring.checked,
7877
+ unwired: wiring.unwired.length,
7878
+ examples: wiring.unwired.slice(0, 10),
7879
+ ...(wiring.failure ? { failure: wiring.failure } : {}),
7880
+ mode: 'warn',
7881
+ };
7882
+ debug.log('self-implement.wiring-check', wiring.failure ? 'unmeasured' : 'measured', wiringObservation);
7883
+ observe('wiring-check', wiringObservation, wiring.failure || wiring.unwired.length ? { level: 'warn' } : {});
7884
+ }
7584
7885
  if ([...(runFacts.changedFiles ?? []), ...(gateRouteFiles ?? []), ...untrackedFiles].some((file) => /\.(?:html|css)$/i.test(file))) {
7585
7886
  try {
7586
7887
  designGate = (s.runDesignGate ?? runDesignGate)({ projectDir: wt.path, base: wt.resolvedBase });
@@ -7600,7 +7901,8 @@ async function runSelfImplementInner(
7600
7901
  const reviewContext = {
7601
7902
  runId,
7602
7903
  ...runFacts,
7603
- goal: opts.feature,
7904
+ // E3 — refine 뒤 라운드의 리뷰는 «현재 골»(v2)로 판정한다. v1 은 PR «골 변경» 절에만 남는다(리뷰 r1 must-fix).
7905
+ goal: roundGoal,
7604
7906
  goalFile: opts.goalFile,
7605
7907
  ...(priorRunFindings.length ? { priorRunFindings } : {}),
7606
7908
  ...(goalDocumentPath ? { goalDocumentPath } : {}),
@@ -7721,7 +8023,7 @@ async function runSelfImplementInner(
7721
8023
  }, { category: 'self-dev.rework' });
7722
8024
  }
7723
8025
  const refutations = refutableFindings.length
7724
- ? parseMustFixRefutations(impl.summary, opts.feature, refutableFindings, ({ stage, findingId }) => {
8026
+ ? parseMustFixRefutations(impl.summary, roundGoal, refutableFindings, ({ stage, findingId }) => {
7725
8027
  observe('refute-rejected', { round, stage, ...(findingId ? { findingId } : {}) });
7726
8028
  }, { citedPathFacts, round })
7727
8029
  : [];
@@ -7753,7 +8055,7 @@ async function runSelfImplementInner(
7753
8055
  try {
7754
8056
  const originalMustFix = refutableFindings.map((finding) => finding.item);
7755
8057
  const recurrenceHistory = recurrenceHistoryFor(originalMustFix);
7756
- const adjudicated = await withStepTimeout(s.reflectMustFix({ mustFix: originalMustFix, goal: opts.feature, cwd: wt.path, evidenceFacts, gateFacts: gate.reflectGateFacts, refutations, citedPathFacts, ...(recurrenceHistory.length ? { recurrenceHistory } : {}), runId, round }), T.review, 'review');
8058
+ const adjudicated = await withStepTimeout(s.reflectMustFix({ mustFix: originalMustFix, goal: roundGoal, cwd: wt.path, evidenceFacts, gateFacts: gate.reflectGateFacts, refutations, citedPathFacts, ...(recurrenceHistory.length ? { recurrenceHistory } : {}), runId, round }), T.review, 'review');
7757
8059
  observe('review-refute-adjudicated', {
7758
8060
  round,
7759
8061
  submittedCount: refutations.length,
@@ -7771,7 +8073,7 @@ async function runSelfImplementInner(
7771
8073
  const oneLine = (text: string): string => text.replace(/\s+/g, ' ').trim().slice(0, 60);
7772
8074
  try {
7773
8075
  const recurrenceHistory = recurrenceHistoryFor(review.mustFix);
7774
- const reflected = await withStepTimeout(s.reflectMustFix({ mustFix: review.mustFix, goal: opts.feature, cwd: wt.path, evidenceFacts, gateFacts: gate.reflectGateFacts, citedPathFacts, ...(recurrenceHistory.length ? { recurrenceHistory } : {}), runId, round }), T.review, 'review');
8076
+ const reflected = await withStepTimeout(s.reflectMustFix({ mustFix: review.mustFix, goal: roundGoal, cwd: wt.path, evidenceFacts, gateFacts: gate.reflectGateFacts, citedPathFacts, ...(recurrenceHistory.length ? { recurrenceHistory } : {}), runId, round }), T.review, 'review');
7775
8077
  const rejectedItems = new Set(reflected.rejected.filter((r) => r.reason && r.reason.trim().length > 0).map((r) => r.item));
7776
8078
  const rejected = reflected.rejected.filter((r) => rejectedItems.has(r.item));
7777
8079
  effectiveMustFix = review.mustFix.filter((m) => !rejectedItems.has(m));
@@ -7872,7 +8174,7 @@ async function runSelfImplementInner(
7872
8174
  }
7873
8175
  // EVIDENCE-WIRING-EXEMPT — a commandless [preservation] is covered once the changed-file gate passed.
7874
8176
  if (gate.passed && evidenceCoverage?.uncoveredCount) {
7875
- const settledByGate = settleUncoveredEvidence(evidenceCoverage.uncovered, { gatePassed: true, required: requiredEvidenceFromGoal(opts.feature) });
8177
+ const settledByGate = settleUncoveredEvidence(evidenceCoverage.uncovered, { gatePassed: true, required: requiredEvidenceFromGoal(roundGoal) });
7876
8178
  if (settledByGate.coveredByGate.length) {
7877
8179
  debug.log('self-implement.evidence', 'covered-by-gate', { round, tags: settledByGate.coveredByGate });
7878
8180
  evidenceCoverage = { ...evidenceCoverage, uncovered: settledByGate.uncovered, uncoveredCount: settledByGate.uncovered.length };
@@ -7910,6 +8212,7 @@ async function runSelfImplementInner(
7910
8212
 
7911
8213
  const { decisionSignalPress, decisionSignalPressReason } = resolveDecisionSignalPress(opts.goalFile, wt.path, opts.decisionSignalPressSources);
7912
8214
  const decisionSignalResult = decisionSignalPress ? { decisionSignalPress } : {};
8215
+ const scopeExpansionResult = scopeExpansion ? { scopeExpansion } : {};
7913
8216
  const decisionSignalRed = (decisionSignalPress?.pressedRed.length ?? 0) > 0;
7914
8217
  const decisionSignalBaselineOnly = decisionSignalPress?.pressedBaselineOnly.length ?? 0;
7915
8218
  const preservedCompletionResult = !decisionSignalRed && completionDisposition
@@ -7939,10 +8242,13 @@ async function runSelfImplementInner(
7939
8242
  // (모집단 0인데 distinguishes=1) 틀린 값으로 막으면 새 병목이 된다.
7940
8243
  // ⛔ `ran === false`(skipped)는 «다른 것»이다 — 자식이 테스트를 안 건드린 경우이고
7941
8244
  // 그건 `skippedReason` 이 이미 가른다. 그래서 여기 조건에 넣지 않는다.
7942
- const verifyInconclusive = gate.verifyByBreaking?.ran === true && (gate.verifyByBreaking.distinguishes ?? 0) === 0;
7943
- const verifyNothingAtBase = verifyInconclusive && (gate.verifyByBreaking?.missingAtBase ?? 0) > 0;
8245
+ // A new test absent from the fixed base is a structural RED witness when the
8246
+ // head gate passed. Keep that distinct from an executed test that proved nothing.
8247
+ const verifyStructuralRed = gate.verifyByBreaking?.ran === true && (gate.verifyByBreaking.missingAtBase ?? 0) > 0;
8248
+ const verifyInconclusive = gate.verifyByBreaking?.ran === true
8249
+ && (gate.verifyByBreaking.distinguishes ?? 0) === 0 && !verifyStructuralRed;
7944
8250
  let mergeReason = canAuto && reviewDeferredToHost ? REVIEW_DEFERRED_TO_HOST_MERGE_REASON
7945
- : canAuto ? (verifyNothingAtBase ? 'review-clean-verify-nothing-at-base' : verifyInconclusive ? 'review-clean-verify-inconclusive' : 'review-clean-armed')
8251
+ : canAuto ? (verifyStructuralRed ? 'review-clean-verify-structural-red' : verifyInconclusive ? 'review-clean-verify-inconclusive' : 'review-clean-armed')
7946
8252
  : gateTimeoutUnmeasured ? GATE_TIMEOUT_UNMEASURED_MERGE_REASON
7947
8253
  : !autoMerge ? 'no-auto-flag'
7948
8254
  : requiredEvidenceMissing ? 'required-evidence-uncovered'
@@ -7990,7 +8296,7 @@ async function runSelfImplementInner(
7990
8296
  progress('worktree-completed', '✅ 작업 트리 완료 — PR 생성 없이 worktree 보존');
7991
8297
  observe('worktree-completed', { branch: wt.branch, hadApprover: !!s.approvePr });
7992
8298
  return {
7993
- ok: true, stage: 'worktree-completed', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}),
8299
+ ok: true, stage: 'worktree-completed', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}),
7994
8300
  detail: 'worktree-only completion: PR creation skipped',
7995
8301
  };
7996
8302
  }
@@ -8001,7 +8307,7 @@ async function runSelfImplementInner(
8001
8307
  recordMergeDecision();
8002
8308
  observe('pr-declined', { branch: wt.branch, hadApprover: !!s.approvePr });
8003
8309
  return {
8004
- ok: false, stage: 'pr-declined', node: 'open-pr', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}),
8310
+ ok: false, stage: 'pr-declined', node: 'open-pr', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}),
8005
8311
  detail: s.approvePr ? 'PR not approved' : 'no approvePr seam — fail-closed(자동승인 금지)',
8006
8312
  };
8007
8313
  }
@@ -8012,7 +8318,7 @@ async function runSelfImplementInner(
8012
8318
  if (opts.goalFile) {
8013
8319
  try { goalDocument = readFileSync(opts.goalFile, 'utf8'); } catch { /* no documented targets */ }
8014
8320
  }
8015
- inspectStaleReverts(revertGuardTargetPaths(opts.feature, goalDocument));
8321
+ inspectStaleReverts(revertGuardTargetPaths(roundGoal, goalDocument)); // E3 — refine 뒤 v2 «대상 경로»
8016
8322
  s.commitWork(wt.path, prTitle(opts.feature, opts.goalFile));
8017
8323
  // ⛔⭐ resume 경로와 «같은» 해석기를 쓴다 — 두 자리가 갈리면 같은 원인이 다른 얼굴로 나온다.
8018
8324
  const resolvedTarget = resolveDefaultBranchTarget(s.defaultBranchRef ?? defaultBranchRef, wt.path);
@@ -8027,7 +8333,7 @@ async function runSelfImplementInner(
8027
8333
  canAuto = false;
8028
8334
  mergeReason = 'default-branch-unresolved';
8029
8335
  recordMergeDecision();
8030
- return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), detail: 'pre-PR main sync default-branch-unresolved' };
8336
+ return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), detail: 'pre-PR main sync default-branch-unresolved' };
8031
8337
  }
8032
8338
  progress('gating', `최신 ${mergeTarget} 정합 (병렬 드리프트·LLM 충돌해결)…`);
8033
8339
  onMainSyncStarted((s.headCommit ?? ((cwd: string) => {
@@ -8045,7 +8351,7 @@ async function runSelfImplementInner(
8045
8351
  mergeReason = 'main-sync-interrupted';
8046
8352
  recordMergeDecision();
8047
8353
  progress('merge-conflict', `⚠️ ${mergeTarget} 정합 중단 — 사람 수확 (${wt.branch})`);
8048
- return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), harvestable: true, detail: `pre-PR main sync interrupted: ${safeErrorDescription(error)}` };
8354
+ return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), harvestable: true, detail: `pre-PR main sync interrupted: ${safeErrorDescription(error)}` };
8049
8355
  }
8050
8356
  // ⛔⭐ `OBS-T96` 🅐 — 「무엇을 봤는지」를 남긴다. 수만 남기면 정합 실패가 «재현 불가»가 된다.
8051
8357
  observe('pre-pr-sync', mainSyncObservation(sync, mergeTarget, opts.base, wt.branch));
@@ -8056,7 +8362,7 @@ async function runSelfImplementInner(
8056
8362
  recordMergeDecision();
8057
8363
  const harvestable = (sync.reason === 'conflict-input-too-large' || sync.reason === 'conflict-resolver-interrupted')
8058
8364
  && await preserveMergeHarvest(sync.reason, sync.inputChars);
8059
- return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(harvestable ? { harvestable: true } : {}), detail: harvestable ? sync.reason === 'conflict-input-too-large' ? `충돌 큼 — 사람 수확 (${wt.branch}, 입력 ${sync.inputChars}자)` : `충돌 해결 중단 — 사람 수확 (${wt.branch})` : `pre-PR main sync ${sync.status}` };
8365
+ return { ok: false, stage: 'merge-conflict', node: 'main-sync', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...(harvestable ? { harvestable: true } : {}), detail: harvestable ? sync.reason === 'conflict-input-too-large' ? `충돌 큼 — 사람 수확 (${wt.branch}, 입력 ${sync.inputChars}자)` : `충돌 해결 중단 — 사람 수확 (${wt.branch})` : `pre-PR main sync ${sync.status}` };
8060
8366
  }
8061
8367
  if (sync.status === 'llm-resolved' || sync.status === 'merged' || sync.status === 'deterministic-resolved') {
8062
8368
  preservationBase = opts.base ?? mergeTarget;
@@ -8115,7 +8421,7 @@ async function runSelfImplementInner(
8115
8421
  mergeReason = 'post-sync-gate-failed';
8116
8422
  recordMergeDecision();
8117
8423
  const pr = await preserveBlockedArtifacts({ stage: 'gate-failed', reason, gate: regate, salvageStatusExpected: false });
8118
- return { ok: false, stage: 'gate-failed', node: 'regate', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate: regate, quotaExhaustionAssessment: quotaExhaustionAssessmentForRun(), ...(review ? { review } : {}), ...(pr ? { prUrl: pr.url, prNumber: pr.number } : {}), detail: reason };
8424
+ return { ok: false, stage: 'gate-failed', node: 'regate', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate: regate, quotaExhaustionAssessment: quotaExhaustionAssessmentForRun(), ...(review ? { review } : {}), ...(pr ? { prUrl: pr.url, prNumber: pr.number } : {}), detail: reason };
8119
8425
  }
8120
8426
  if (!regate.passed) {
8121
8427
  progress('gating', timeoutOnlyPostSync
@@ -8129,7 +8435,7 @@ async function runSelfImplementInner(
8129
8435
  recordMergeDecision();
8130
8436
  if (!approved) {
8131
8437
  observe('pr-declined', { branch: wt.branch, hadApprover: !!s.approvePr });
8132
- return { ok: false, stage: 'pr-declined', node: 'open-pr', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), mergeReason, detail: s.approvePr ? 'PR not approved' : 'no approvePr seam — fail-closed(자동승인 금지)' };
8438
+ return { ok: false, stage: 'pr-declined', node: 'open-pr', ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), mergeReason, detail: s.approvePr ? 'PR not approved' : 'no approvePr seam — fail-closed(자동승인 금지)' };
8133
8439
  }
8134
8440
  if (canAuto) onMergeApprovalReceived();
8135
8441
  const extractedOriginalAsk = extractVerbatimOriginalAsk(opts.feature);
@@ -8164,7 +8470,7 @@ async function runSelfImplementInner(
8164
8470
  }
8165
8471
  const stoppedBeforePr = honorParentSoftStop('open-pr');
8166
8472
  if (stoppedBeforePr) {
8167
- return { ...stoppedBeforePr, ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, sessionId, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}) };
8473
+ return { ...stoppedBeforePr, ...resolveRunOutcome({ termination: 'abandoned' }), ...decisionSignalResult, ...scopeExpansionResult, sessionId, gate, ...(review ? { review } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}) };
8168
8474
  }
8169
8475
  progress('pr-opening', 'PR 생성…');
8170
8476
  onNodeEntry('open-pr', round);
@@ -8204,7 +8510,8 @@ async function runSelfImplementInner(
8204
8510
  addNextMdReleaseNote(wt.path, releaseNote);
8205
8511
  const preparedPrBody = preparePrBody(
8206
8512
  [
8207
- prBody(opts.feature, impl.summary, gate.log, review, reviewIntent, declineReasons, harvestedForPr(), opts.goalFile, lastPlanRevision, releaseNote, revertGuard),
8513
+ prBody(roundGoal, impl.summary, gate.log, review, reviewIntent, declineReasons, harvestedForPr(), opts.goalFile, lastPlanRevision, releaseNote, revertGuard) + renderScopeExpansionSection(scopeExpansion),
8514
+ ...(goalRefinement ? ['', (await import('./goal-refine.js')).renderGoalChangeSection(goalRefinement)] : []),
8208
8515
  ...(prEvidenceDecision.body ? ['', '---', '', prEvidenceDecision.body] : []),
8209
8516
  ].join('\n'),
8210
8517
  s.persistPrBodyArtifact,
@@ -8214,6 +8521,7 @@ async function runSelfImplementInner(
8214
8521
  try {
8215
8522
  pr = await withStepTimeout(s.openPr({
8216
8523
  title: prTitle(opts.feature, opts.goalFile),
8524
+ runId,
8217
8525
  body: preparedPrBody.body,
8218
8526
  head: wt.branch,
8219
8527
  ...(opts.base ? { base: opts.base } : {}),
@@ -8290,7 +8598,7 @@ async function runSelfImplementInner(
8290
8598
  }
8291
8599
  recordMergeDecision();
8292
8600
  progress('pr-opened', `OP 승인 대기 (#${pr.number}): ${releaseHoldPath}`);
8293
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason, prUrl: pr.url, prNumber: pr.number, detail: `OP approval required: ${releaseHoldPath}` };
8601
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason, prUrl: pr.url, prNumber: pr.number, detail: `OP approval required: ${releaseHoldPath}` };
8294
8602
  }
8295
8603
  if (!releasePathInspectionError && labels?.includes(AUTO_REVIEW_LABEL)) {
8296
8604
  try {
@@ -8308,7 +8616,7 @@ async function runSelfImplementInner(
8308
8616
  : 'release-path-inspection-failed';
8309
8617
  recordMergeDecision();
8310
8618
  progress('pr-opened', `OP 승인 대기 (#${pr.number}): PR 경로 조회 실패`);
8311
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason, prUrl: pr.url, prNumber: pr.number };
8619
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason, prUrl: pr.url, prNumber: pr.number };
8312
8620
  }
8313
8621
 
8314
8622
  if (canAuto && (s.mergePr || opts.mergeByHost)) {
@@ -8358,12 +8666,12 @@ async function runSelfImplementInner(
8358
8666
  // 판정(mergeReason)이 아니라 «집행 직전 가드»가 막았으므로 그 사실을 값으로 말한다.
8359
8667
  // ⛔ 안 그러면 마지막 줄이 침묵하고, 그건 이 착지가 없애려던 상태다(리뷰 must-fix 2R).
8360
8668
  const guardSkipReason = mergeSkipReason ?? (guardFailure ? 'merge-guard-unevaluated' : 'docs-deletion-threshold');
8361
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: guardSkipReason, prUrl: pr.url, prNumber: pr.number, detail };
8669
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: guardSkipReason, prUrl: pr.url, prNumber: pr.number, detail };
8362
8670
  }
8363
8671
  if (opts.mergeByHost) {
8364
8672
  observe('merge-ready', { number: pr.number, checkedHeadCommit });
8365
8673
  progress('pr-opened', `호스트 재게이트 대기 (#${pr.number})`);
8366
- return { ok: true, stage: 'merge-ready', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, ...(reviewDeferredToHost ? { mergeReason } : {}), checkedHeadCommit: checkedHeadCommit!, prUrl: pr.url, prNumber: pr.number };
8674
+ return { ok: true, stage: 'merge-ready', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, ...(reviewDeferredToHost ? { mergeReason } : {}), checkedHeadCommit: checkedHeadCommit!, prUrl: pr.url, prNumber: pr.number };
8367
8675
  }
8368
8676
  // Landing freeze: the in-flight marker is written before the freeze is read, so a `freeze on` racing this merge waits.
8369
8677
  // The resume sweep merges from the repository that owns the run worktree (the worktree itself may be cleaned up).
@@ -8375,13 +8683,13 @@ async function runSelfImplementInner(
8375
8683
  };
8376
8684
  const landing = admitLandingMerge(heldEntry, undefined, {}, { prNumber: pr.number, repoRoot: owningRepoRoot(wt.path) ?? wt.path, ...(checkedHeadCommit ? { headCommit: checkedHeadCommit } : {}) });
8377
8685
  if (landing.kind === 'held' && !(checkedHeadCommit && /^[0-9a-f]{40}$/i.test(checkedHeadCommit))) {
8378
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: 'merge-guard-unevaluated', prUrl: pr.url, prNumber: pr.number, detail: 'freeze: checked head SHA unavailable; PR left ready for review' };
8686
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: 'merge-guard-unevaluated', prUrl: pr.url, prNumber: pr.number, detail: 'freeze: checked head SHA unavailable; PR left ready for review' };
8379
8687
  }
8380
8688
  if (landing.kind !== 'merge') {
8381
8689
  const detail = landing.kind === 'held' ? landingFreezeMessage(landing.freeze) : 'freeze lifted; a resume sweep is merging this PR';
8382
8690
  debug.log('harness.merge', 'frozen', { pr: pr.number, ...(landing.kind === 'held' ? { reason: landing.freeze.reason, until: landing.freeze.until } : { resumedElsewhere: true }) });
8383
8691
  progress('pr-opened', `#${pr.number} ready · ${detail}`);
8384
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: landing.kind === 'held' ? 'frozen' : 'resumed-elsewhere', prUrl: pr.url, prNumber: pr.number, detail };
8692
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: landing.kind === 'held' ? 'frozen' : 'resumed-elsewhere', prUrl: pr.url, prNumber: pr.number, detail };
8385
8693
  }
8386
8694
  // The marker and claim live until the merge call itself settles — a step timeout does not stop a merge already
8387
8695
  // sent — and anything that throws before the merge call is made releases them.
@@ -8464,17 +8772,17 @@ async function runSelfImplementInner(
8464
8772
  ...(opts.goalId ? { cellId: opts.goalId } : {}),
8465
8773
  ...(opts.goalFile ? { goalFile: opts.goalFile } : {}),
8466
8774
  }, s.followUp);
8467
- return { ok: true, stage: 'merged', node: 'merge', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), merged: true, ...(mergedBase ? { mergedBase } : {}), prUrl: pr.url, prNumber: pr.number };
8775
+ return { ok: true, stage: 'merged', node: 'merge', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), merged: true, ...(mergedBase ? { mergedBase } : {}), prUrl: pr.url, prNumber: pr.number };
8468
8776
  }
8469
8777
  progress('pr-opened', `병합 실패 — PR 개설됨(#${pr.number}·수동 병합). ${m.detail ?? ''}`);
8470
8778
  // ⛔⭐ 이 경로는 `canAuto` 가 «참»이었는데 병합이 안 된 자리다 ⇒ mergeSkipReason 은 undefined 다.
8471
8779
  // 그대로 두면 마지막 산출 줄이 «침묵»한다 — 이 착지가 없애려던 바로 그 상태다(리뷰 must-fix).
8472
8780
  // ⇒ 판정이 아니라 «집행»에서 막힌 것이므로 그 사실을 별도 값으로 말한다.
8473
8781
  const mergeAttemptSkipReason = mergeSkipReason ?? 'merge-attempt-failed';
8474
- return { ok: true, stage: 'pr-opened', node: 'merge', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: mergeAttemptSkipReason, merged: false, prUrl: pr.url, prNumber: pr.number, ...(m.detail ? { detail: m.detail } : {}) };
8782
+ return { ok: true, stage: 'pr-opened', node: 'merge', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, mergeReason: mergeAttemptSkipReason, merged: false, prUrl: pr.url, prNumber: pr.number, ...(m.detail ? { detail: m.detail } : {}) };
8475
8783
  }
8476
8784
  progress('pr-opened', `✅ PR 개설 (#${pr.number})`);
8477
- return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, ...(lastSupervisorReason ? { supervisorReason: lastSupervisorReason } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}), prUrl: pr.url, prNumber: pr.number };
8785
+ return { ok: true, stage: 'pr-opened', node: 'open-pr', ...resolveRunOutcome({ termination: 'completed' }), ...decisionSignalResult, ...scopeExpansionResult, ...preservedCompletionResult, ...(completionStatus ? { completionStatus } : {}), sessionId, worktreePath: wt.path, branch: wt.branch, gate, ...(review ? { review } : {}), ...reviewedHeadResult, ...(lastSupervisorReason ? { supervisorReason: lastSupervisorReason } : {}), ...(mergeSkipReason ? { mergeReason: mergeSkipReason } : {}), prUrl: pr.url, prNumber: pr.number };
8478
8786
  }
8479
8787
 
8480
8788
  /** 결정적 요청 거부 — 같은 요청을 다시 보내면 «같은» 답이 온다(BACKLOG B6).