elanous 0.2.32 → 0.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (633) 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/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
  5. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
  8. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
  9. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
  13. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
  15. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
  16. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
  19. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
  30. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
  31. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
  37. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
  39. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
  41. package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
  44. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
  45. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
  46. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
  47. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
  48. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
  51. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
  63. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
  76. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
  80. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
  87. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
  91. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
  94. package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
  97. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
  114. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
  116. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
  117. package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
  123. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-8c66a3b24a745630.js → page-398c0faa173203f7.js} +1 -1
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-df3445b207ceceab.js} +1 -1
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +1 -0
  184. package/apps/pwa/out/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 +9 -2
  278. package/docs/goal-context/README.md +1 -0
  279. package/graphs/default-loop.yaml +20 -3
  280. package/graphs/document-loop.yaml +21 -2
  281. package/graphs/implement-loop.yaml +6 -0
  282. package/graphs/journey/SCENARIOS.md +33 -0
  283. package/graphs/journey/recipes.yaml +1 -0
  284. package/graphs/journey/ta-journey.yaml +84 -0
  285. package/graphs/journey/units/author/author.yaml +20 -0
  286. package/graphs/journey/units/author/recipes.yaml +2 -0
  287. package/graphs/journey/units/green/green.yaml +20 -0
  288. package/graphs/journey/units/green/recipes.yaml +2 -0
  289. package/graphs/journey/units/pr/pr.yaml +20 -0
  290. package/graphs/journey/units/pr/recipes.yaml +2 -0
  291. package/graphs/journey/units/remember/recipes.yaml +2 -0
  292. package/graphs/journey/units/remember/remember.yaml +20 -0
  293. package/graphs/operate-loop.yaml +21 -2
  294. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  295. package/graphs/release-rehearsal/recipes.yaml +1 -1
  296. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  297. package/graphs/research-loop.yaml +23 -2
  298. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  299. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  300. package/graphs/units/entry/entry.yaml +50 -0
  301. package/graphs/units/entry/recipes.yaml +14 -0
  302. package/graphs/units/harvest/harvest.yaml +25 -0
  303. package/graphs/units/harvest/recipes.yaml +4 -0
  304. package/graphs/units/land/land.yaml +45 -0
  305. package/graphs/units/land/recipes.yaml +3 -0
  306. package/graphs/units/recipes.yaml +7 -0
  307. package/graphs/units/recover.yaml +39 -0
  308. package/graphs/units/reflect/recipes.yaml +3 -0
  309. package/graphs/units/reflect/reflect.yaml +15 -0
  310. package/graphs/units/task-agent-recover-review.yaml +17 -0
  311. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  312. package/graphs/units/verbs/make-doc.yaml +34 -0
  313. package/graphs/units/verbs/recipes.yaml +33 -0
  314. package/graphs/units/verbs/verify.yaml +55 -0
  315. package/graphs/work/recipes.yaml +2 -0
  316. package/graphs/work/research-report.yaml +28 -0
  317. package/package.json +1 -1
  318. package/scripts/ci-typecheck-changed.ts +69 -16
  319. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  320. package/scripts/graph-harvest-unit.ts +22 -0
  321. package/scripts/graph-units/journey-stub.ts +6 -0
  322. package/scripts/graph-units/land-enqueue.ts +78 -0
  323. package/scripts/graph-units/recover-plan.ts +15 -0
  324. package/scripts/graph-units/reflect-node.ts +88 -0
  325. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  326. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  327. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  328. package/scripts/graph-units/verbs-envelope.ts +139 -0
  329. package/scripts/hq/standby-snapshot.ts +25 -0
  330. package/scripts/public-export.ts +43 -1
  331. package/scripts/ratchets/train-side-invariants.sh +45 -0
  332. package/scripts/release-loop/auto-approve-node.ts +30 -16
  333. package/scripts/release-loop/gate-closure.ts +5 -1
  334. package/scripts/release-loop/gate-diff.ts +1 -1
  335. package/scripts/release-loop/gate-node.ts +498 -31
  336. package/scripts/release-loop/gate-partial.ts +3 -3
  337. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  338. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  339. package/scripts/release-loop/gate-triage-node.ts +5 -2
  340. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  341. package/scripts/release-loop/known-issues-node.ts +77 -8
  342. package/scripts/release-loop/preflight.ts +93 -7
  343. package/scripts/release-loop/publish-node.ts +60 -9
  344. package/scripts/release-loop/resume-cap.ts +56 -0
  345. package/scripts/release-loop/resume-release.ts +114 -15
  346. package/scripts/release-loop/resume.ts +24 -1
  347. package/scripts/release-loop/tui-sim-node.ts +8 -2
  348. package/scripts/release-loop/unattended-release.ts +8 -2
  349. package/src/acp/core-turn-bridge.ts +20 -5
  350. package/src/acp/reasoning-thought-buffer.ts +45 -0
  351. package/src/agent-substrate/acp-reviewer.ts +52 -12
  352. package/src/agent-substrate/review-finding-key.ts +53 -0
  353. package/src/agent-substrate/self-review-cli.ts +126 -5
  354. package/src/ask-user-question/pending-questions.ts +1 -1
  355. package/src/autopilot/pr-manager.ts +192 -43
  356. package/src/chat/tool-render/dispatch.ts +62 -10
  357. package/src/cli/control-cli.ts +24 -7
  358. package/src/cli/guardian-cli.ts +10 -0
  359. package/src/cli/light-entry-route.ts +35 -0
  360. package/src/cli/llm-detect-cli.ts +23 -1
  361. package/src/cli/pr-cli.ts +76 -12
  362. package/src/cli/pr-land-base-read.ts +2 -0
  363. package/src/cli/pr-land-overlap-evidence.ts +154 -16
  364. package/src/cli/pr-land-recovery.ts +64 -0
  365. package/src/cli/pty-takeover-cli.ts +6 -5
  366. package/src/cli/release-cli.ts +120 -33
  367. package/src/cli/release-run-if-ready.ts +29 -28
  368. package/src/cli/release-single-flight.ts +178 -0
  369. package/src/cli/seat-cli.ts +37 -0
  370. package/src/cli/setup-cli.ts +40 -1
  371. package/src/cli/tasks-cli.ts +149 -5
  372. package/src/control/control-status.ts +8 -3
  373. package/src/control-plane/ledger.ts +5 -3
  374. package/src/control-plane/server.ts +5 -3
  375. package/src/core-turn/short-question.ts +5 -1
  376. package/src/dashboard/index.ts +36 -67
  377. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  378. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  379. package/src/dashboard/input/seat-autowake.ts +56 -3
  380. package/src/dashboard/seat-boot-preamble.ts +1 -1
  381. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  382. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  383. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  384. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  385. package/src/dashboard/turn-preamble.ts +47 -1
  386. package/src/dashboard/turn-stream-formatter.ts +34 -1
  387. package/src/dashboard/turn-stream-runtime.ts +2 -0
  388. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  389. package/src/domains/guardian-tick.ts +54 -2
  390. package/src/domains/outbound-alert.ts +3 -2
  391. package/src/extractors.ts +3 -1
  392. package/src/git-fs/retry.ts +4 -0
  393. package/src/git-fs/runner.ts +2 -0
  394. package/src/graph-runner/runner.ts +114 -44
  395. package/src/grok/credential.ts +5 -0
  396. package/src/harness/harness-cli-command.ts +39 -10
  397. package/src/harness/harness-incidents.ts +4 -0
  398. package/src/harness/harness-pod-dispatch.ts +38 -1
  399. package/src/harness/harness-salvage-cli.ts +14 -2
  400. package/src/index.ts +192 -8
  401. package/src/intake-plane/already-built-hint.ts +89 -0
  402. package/src/knowhow/pack.ts +199 -0
  403. package/src/light-cli.ts +95 -0
  404. package/src/llm.ts +55 -9
  405. package/src/loops/budget.ts +95 -0
  406. package/src/loops/msg-wake.ts +8 -2
  407. package/src/loops/orchestrator/traffic.ts +132 -1
  408. package/src/mss/logging/log-store.ts +4 -5
  409. package/src/nexus/api/graphs-api.ts +22 -3
  410. package/src/nexus/api/http-server.ts +1 -1
  411. package/src/nexus/api/ops-api.ts +12 -0
  412. package/src/oauth/claude-pty-maturity.ts +66 -0
  413. package/src/oauth/codex-access-mirror.ts +55 -0
  414. package/src/oauth/fallback-chain.ts +1 -1
  415. package/src/onboarding/first-run.ts +5 -3
  416. package/src/onboarding/non-interactive.ts +64 -13
  417. package/src/onboarding.ts +10 -2
  418. package/src/ops/overview-collect.ts +36 -1
  419. package/src/ops/overview.ts +11 -0
  420. package/src/pr-tool/census.ts +23 -5
  421. package/src/pr-tool/inflight-registry.ts +160 -7
  422. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  423. package/src/pty-shell/herdr-agent-report.ts +442 -0
  424. package/src/pty-shell/pty-control-ipc.ts +5 -5
  425. package/src/pty-shell/pty-write-outcome.ts +24 -6
  426. package/src/pty-shell/tui-run-state.ts +117 -3
  427. package/src/release-loop/checklist.ts +79 -5
  428. package/src/release-loop/feature-store.ts +19 -2
  429. package/src/release-loop/placement.ts +10 -3
  430. package/src/release-loop/rehearsal.ts +205 -25
  431. package/src/release-loop/rubric.ts +16 -2
  432. package/src/self-dev/draft-sweep.ts +52 -3
  433. package/src/self-dev/graph-journey-nodes.ts +10 -6
  434. package/src/self-dev/graph-journey-route.ts +60 -6
  435. package/src/self-dev/orchestrate.ts +79 -3
  436. package/src/self-dev/run-supervisor.ts +107 -12
  437. package/src/self-dev/run-types.ts +5 -1
  438. package/src/self-implement/gate-baseline.ts +49 -5
  439. package/src/self-implement/gate-remote.ts +9 -5
  440. package/src/self-implement/goal-author-identity.ts +66 -0
  441. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  442. package/src/self-implement/goal-author.ts +4 -120
  443. package/src/self-implement/graph-overlay-yaml.ts +17 -2
  444. package/src/self-implement/graph-unit-flatten.ts +103 -0
  445. package/src/self-implement/graph-unit-resolver.ts +107 -0
  446. package/src/self-implement/graph-yaml.ts +151 -1
  447. package/src/self-implement/headless-elanous-driver.ts +1 -0
  448. package/src/self-implement/knowhow-pack.ts +103 -0
  449. package/src/self-implement/orchestrator.ts +8 -0
  450. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  451. package/src/self-implement/review-mustfix-class.ts +203 -0
  452. package/src/self-implement/run-stop.ts +8 -2
  453. package/src/self-implement/seams.ts +32 -1
  454. package/src/self-implement/stop-autoheal.ts +25 -1
  455. package/src/session/chat.ts +27 -0
  456. package/src/session-runtime/retry-policy.ts +2 -1
  457. package/src/skills/tools/schedule-wakeup.ts +66 -17
  458. package/src/steward/release-day.ts +7 -3
  459. package/src/steward/triage.ts +37 -4
  460. package/src/task-agent/harvest-unit.ts +141 -0
  461. package/src/task-agent/live-moves.ts +98 -12
  462. package/src/task-agent/parent-host.ts +93 -3
  463. package/src/task-agent/postland-card.ts +80 -1
  464. package/src/task-agent/rejudge-on-head.ts +112 -26
  465. package/src/task-agent/repair-branch-cas.ts +4 -1
  466. package/src/task-agent/repair-cycle.ts +16 -3
  467. package/src/task-agent/run-identity.ts +4 -3
  468. package/src/task-agent/shadow.ts +12 -2
  469. package/src/task-agent/task-hand.ts +54 -7
  470. package/src/task-agent/work-order-build.ts +22 -0
  471. package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
  472. package/src/task-orchestrator/surfaces/pod-command-job.ts +2 -1
  473. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  474. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
  475. package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
  476. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +26 -3
  477. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
  478. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
  479. package/src/task-orchestrator/surfaces/self-implement-pod.ts +223 -38
  480. package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
  481. package/src/tool-runtime/truncation-store.ts +4 -0
  482. package/src/tui-client/dashboard-session.ts +10 -1
  483. package/src/user-config/coercion.ts +36 -0
  484. package/src/user-config.ts +18 -41
  485. package/src/ux-sim/scenario.ts +72 -13
  486. package/src/version/packed-revision.json +1 -1
  487. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  490. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  491. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  492. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  496. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  498. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  499. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  506. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  507. package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
  510. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  514. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  518. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  519. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  521. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  524. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  529. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  531. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  538. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  539. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  541. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  546. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  547. package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  555. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  625. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  632. package/src/cli/g6a-registration-probe.ts +0 -16
  633. /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
@@ -22,7 +22,9 @@ import { debug } from '../debug/log.js';
22
22
  import { findGitDir } from '../git-fs/locate.js';
23
23
  import { getUserConfig, userConfigPath } from '../user-config.js';
24
24
  import type { DetachedSpawn } from '../cli/tasks-cli.js';
25
- import { LIVE_MOVE_HISTORY_EVENT, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
25
+ import { LIVE_MOVE_HISTORY_EVENT, shellQuote, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
26
+ import { reconcileHandMergedCard } from './postland-card.js';
27
+ import { resolveParentHosts, type ParentHostConfig } from './parent-host.js';
26
28
  import { LIVE_RETRY_MOVES } from './judge.js';
27
29
  import { decisionCardGrounds, decisionRaiseArgs, type DecisionCardEvidence, type NextAction } from './actions.js';
28
30
  import { pendingReviewResults, reviewResultPath, TA_REVIEW_COMPLETION_CARD_ENV, TA_REVIEW_COMPLETION_RESULT_ENV, TA_REVIEW_COMPLETION_STATE_ENV } from './review-result-capture.js';
@@ -83,6 +85,8 @@ export interface LiveMoveDeps {
83
85
  priorDiff?: PriorDiffReader;
84
86
  /** Fresh PR head and draft flag for landing; separate from the unchanged review lookup. */
85
87
  landPrHead?: (pr: number, cwd: string) => Promise<(PrHeadView & { isDraft: boolean }) | null>;
88
+ /** TA-CARD-MERGE-RECONCILE — MERGED PR 의 merge SHA·base·mergedAt 관측(시험 주입 · 기본 = `gh pr view`). */
89
+ handMergePr?: (pr: number, cwd: string) => Promise<HandMergePrView | null>;
86
90
  /** One existing pr land operation; inject in tests instead of invoking the CLI. */
87
91
  /** TA-REJUDGE-ON-HEAD — `opts.overlapEvidence` 가 있으면 `pr land --overlap-evidence <file>` 로 넘긴다(없으면 종전 인자). */
88
92
  land?: (pr: number, head: string, cwd: string, opts?: { overlapEvidence?: string }) => Promise<{ status: number; stdout: string; stderr?: string }>;
@@ -208,25 +212,44 @@ export function liveReviewArgs(entry: string, configDir: string, pr: number, int
208
212
  return [resolve(entry), '--config-dir', configDir, 'self', 'review', String(pr), '--json', '--intent', intent];
209
213
  }
210
214
 
215
+ /** Use the configured node-b checkout for heavy TA workers; absence of parentHost preserves the legacy local path. */
216
+ export function configuredMsb1Worker(): ParentHostConfig | null {
217
+ const setting = getUserConfig().taskAgent?.parentHost;
218
+ if (setting === undefined) return null;
219
+ const target = resolveParentHosts(setting, {} as NodeJS.ProcessEnv).find((entry) => entry.host === 'node-b');
220
+ if (!target) throw new Error('taskAgent.parentHost configured without a valid node-b worker');
221
+ return target;
222
+ }
223
+
224
+ export function remoteTaWorkerCommand(target: ParentHostConfig, args: readonly string[]): string {
225
+ const entry = target.elanous ? shellQuote(target.elanous) : '$HOME/.local/share/elanous/bin/elanous';
226
+ const configDir = target.configDir ? shellQuote(target.configDir) : '$HOME/.elanous';
227
+ return `cd ${shellQuote(target.cwd)} && ${entry} --config-dir ${configDir} ${args.map(shellQuote).join(' ')}`;
228
+ }
229
+
211
230
  /**
212
231
  * 지금 도는 진입점으로 같은 우주의 리뷰를 떼어 띄운다 — 기다리지 않는다(결과는 self review 자기 관측에 남는다).
213
232
  * TA-REVIEW-RESULT-CAPTURE — `resultPath` 가 있으면 자식 stdout(`--json` 결과)만 그 파일로 받는다(stdin·stderr 는 종전대로 버린다 ·
214
233
  * 파이프가 아니라 파일 — 부모가 먼저 끝나도 자식이 EPIPE 로 죽지 않는다). 없으면 종전과 같다(stdio ignore).
215
234
  * `opts` 는 시험 몫(spawn·진입점·우주) — 기본은 실물.
216
235
  */
217
- export async function defaultRequestReview(pr: number, intent: string, cwd?: string, opts: { spawn?: DetachedSpawn; entry?: string; configDir?: string; resultPath?: string; cardId?: string; statePath?: string } = {}): Promise<void> {
236
+ export async function defaultRequestReview(pr: number, intent: string, cwd?: string, opts: { spawn?: DetachedSpawn; entry?: string; configDir?: string; resultPath?: string; cardId?: string; statePath?: string; remote?: ParentHostConfig | null } = {}): Promise<void> {
218
237
  const { spawnDetachedConfirmed, ELANOUS_CLI_ENTRY } = await import('../cli/tasks-cli.js');
219
238
  const { getElanousConfigDirOverride } = await import('../elanous-config-dir.js');
220
239
  const { effectiveInstanceRoot } = await import('../instance/resolve.js');
221
240
  const configDir = opts.configDir ?? getElanousConfigDirOverride() ?? effectiveInstanceRoot();
222
241
  const base = opts.spawn ?? (spawn as unknown as DetachedSpawn);
242
+ const remote = opts.remote === undefined ? (opts.spawn ? null : configuredMsb1Worker()) : opts.remote;
223
243
  const args = liveReviewArgs(opts.entry ?? ELANOUS_CLI_ENTRY, configDir, pr, intent);
224
244
  const completionEnv = opts.resultPath && opts.cardId && opts.statePath ? {
225
245
  [TA_REVIEW_COMPLETION_CARD_ENV]: opts.cardId,
226
246
  [TA_REVIEW_COMPLETION_STATE_ENV]: opts.statePath,
227
247
  [TA_REVIEW_COMPLETION_RESULT_ENV]: opts.resultPath,
228
248
  } : undefined;
229
- if (!opts.resultPath) { await spawnDetachedConfirmed(base, process.execPath, args, undefined, cwd); return; }
249
+ const workerCommand = remote ? remoteTaWorkerCommand(remote, ['self', 'review', String(pr), '--json', '--model', 'gpt-6-sol', '--intent', intent]) : null;
250
+ const command = remote ? 'ssh' : process.execPath;
251
+ const workerArgs = remote ? ['-T', '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=5', remote.host, workerCommand!] : args;
252
+ if (!opts.resultPath) { await spawnDetachedConfirmed(base, command, workerArgs, undefined, cwd); return; }
230
253
  let fd: number;
231
254
  try {
232
255
  mkdirSync(dirname(opts.resultPath), { recursive: true });
@@ -234,13 +257,13 @@ export async function defaultRequestReview(pr: number, intent: string, cwd?: str
234
257
  } catch (error) {
235
258
  // 결과 파일을 못 열어도 리뷰는 막지 않는다(종전처럼 stdio ignore) — 회수는 상한 뒤 «no result» 줄로 드러난다.
236
259
  try { debug.log('task-agent', 'review-result-file-open-failed', { pr, resultPath: opts.resultPath, reason: (error instanceof Error ? error.message : String(error)).slice(-300) }, { level: 'warn' }); } catch { /* fail-soft */ }
237
- await spawnDetachedConfirmed(base, process.execPath, args, undefined, cwd);
260
+ await spawnDetachedConfirmed(base, command, workerArgs, undefined, cwd);
238
261
  return;
239
262
  }
240
263
  const toFile: DetachedSpawn = (command, spawnArgs, options) =>
241
264
  (base as unknown as (c: string, a: string[], o: unknown) => ReturnType<DetachedSpawn>)(command, spawnArgs, { ...options, stdio: ['ignore', fd, 'ignore'] });
242
265
  try {
243
- await spawnDetachedConfirmed(toFile, process.execPath, args, undefined, cwd, completionEnv);
266
+ await spawnDetachedConfirmed(toFile, command, workerArgs, undefined, cwd, remote ? undefined : completionEnv);
244
267
  } finally {
245
268
  try { closeSync(fd); } catch { /* the child keeps its own copy */ }
246
269
  }
@@ -296,6 +319,35 @@ export async function defaultLandPrHead(pr: number, cwd: string): Promise<(PrHea
296
319
  } catch { return null; }
297
320
  }
298
321
 
322
+ /** TA-CARD-MERGE-RECONCILE — 손수 병합된 PR 의 정산 관측값(merge SHA 가 main 조상 검증의 재료). */
323
+ export interface HandMergePrView {
324
+ state: string;
325
+ url?: string;
326
+ baseRefName?: string;
327
+ mergedAt?: string;
328
+ mergeCommit?: string;
329
+ }
330
+
331
+ export async function defaultHandMergePr(pr: number, cwd: string): Promise<HandMergePrView | null> {
332
+ const view = (env: NodeJS.ProcessEnv) => runGh(['pr', 'view', String(pr), '--json', 'state,url,baseRefName,mergedAt,mergeCommit'], { env, cwd });
333
+ let out = view(process.env);
334
+ if (out.status !== 0) {
335
+ const noProxy = { ...process.env };
336
+ for (const key of ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy']) delete noProxy[key];
337
+ out = view(noProxy);
338
+ }
339
+ if (out.status !== 0) return null;
340
+ try {
341
+ const value = JSON.parse(out.stdout) as { state?: unknown; url?: unknown; baseRefName?: unknown; mergedAt?: unknown; mergeCommit?: { oid?: unknown } | null };
342
+ if (typeof value.state !== 'string') return null;
343
+ return { state: value.state,
344
+ ...(typeof value.url === 'string' && value.url ? { url: value.url } : {}),
345
+ ...(typeof value.baseRefName === 'string' && value.baseRefName ? { baseRefName: value.baseRefName } : {}),
346
+ ...(typeof value.mergedAt === 'string' && value.mergedAt ? { mergedAt: value.mergedAt } : {}),
347
+ ...(typeof value.mergeCommit?.oid === 'string' && /^[a-f0-9]{40}$/i.test(value.mergeCommit.oid) ? { mergeCommit: value.mergeCommit.oid } : {}) };
348
+ } catch { return null; }
349
+ }
350
+
299
351
  /**
300
352
  * REVIEW-CONVERGE-PRIOR-FIX — `prior` 는 같은 PR 의 두 번째 이후 리뷰에만 온다: «직전 반영분»에 직전 머리 범위·diff·must-fix 를,
301
353
  * 범위 경계에 «바뀌지 않은 줄의 새 must-fix 는 근거 줄» 한 줄을 붙인다. 없으면(첫 리뷰) 종전 문면 바이트 그대로.
@@ -402,7 +454,7 @@ export async function executeLiveReview(
402
454
  * (`executeLiveLand` ctx `gateAt` = 그 재게이트 요청 시각)에만 이 시도는 «소비됨»으로 빠진다. judgement·infra 와 섞이지 않는다.
403
455
  */
404
456
  export const LAND_ATTEMPTS_PER_HEAD_ON_INFRA = 2;
405
- export type LandFailureClass = 'infra' | 'judgement' | 'base-stale';
457
+ export type LandFailureClass = 'infra' | 'judgement' | 'base-stale' | 'recovery';
406
458
 
407
459
  /** `pr land` 출력 줄 → 인프라 사유. ⛔ 줄 «전체»가 맞아야 한다 — 비슷한 문면을 넓게 받지 않는다. */
408
460
  export const LAND_INFRA_OUTPUT_REASONS: ReadonlyArray<{ reason: string; line: RegExp }> = [
@@ -422,6 +474,8 @@ const LAND_INFRA_CONSEQUENCE_LINES: ReadonlyArray<{ of: string; line: RegExp }>
422
474
  ];
423
475
  /** REJUDGE base-stale — 겹침 증거의 게이트 base 가 낡았고 그 사이 착지가 PR 파일을 건드렸다(`pr land` · #26060 문면). */
424
476
  const LAND_BASE_STALE_LINE = /^✗ overlap-evidence: (base-stale-overlap: .*)$/;
477
+ const LAND_RECOVER_REVIEW = /^✗ (?:ancestor-auto|overlap-evidence): (?:review-missing|review-not-reviewed|review-error|review-no-result|review-unreadable|review-pr-mismatch|review-head-mismatch|review-path-not-for-this-pr-head|review-verdict-null|review-must-fix-unknown)(?:\b|$)/;
478
+ const LAND_RECOVER_BUSY = /^✗ heavy-remote: (?:원격|병합 직전 원격|node-b) 게이트 gate-host-busy(?:\b|\s|$)/;
425
479
  /** base-stale 에 «딸려 나오는» 줄 — 증거가 거절되면 `pr land` 가 이어서 낸다(그 줄만 있으면 판정 거절로 세지 않는다). */
426
480
  const LAND_BASE_STALE_CONSEQUENCE_LINES: readonly RegExp[] = [/^✗ expected-head: overlap merge approval unavailable for the reviewed head$/];
427
481
  /** 실패가 아닌 ✗ 줄 — `pr land` 가 «계속합니다»로 넘어간다(판정에 쓰지 않는다). */
@@ -464,6 +518,10 @@ export function classifyLandFailure(outcome: { status: number; stdout?: string;
464
518
  if (hit) infra.add(hit.reason); else unlisted.push(line);
465
519
  }
466
520
  const judged = unlisted.filter((line) => !LAND_INFRA_CONSEQUENCE_LINES.some((entry) => infra.has(entry.of) && entry.line.test(line)));
521
+ if (judged.length === 1 && !infra.size) {
522
+ if (LAND_RECOVER_REVIEW.test(judged[0]!)) return { class: 'recovery', reason: 'review-missing' };
523
+ if (LAND_RECOVER_BUSY.test(judged[0]!)) return { class: 'recovery', reason: 'gate-host-busy' };
524
+ }
467
525
  // REJUDGE base-stale — 거절 줄이 base-stale-overlap(⊕ 딸린 줄) «뿐»이고 인프라 사유가 없을 때만. 하나라도 다른 ✗ 줄이 섞이면 judgement(fail-closed).
468
526
  const stale = judged.map((line) => LAND_BASE_STALE_LINE.exec(line)?.[1]).find((reason): reason is string => !!reason);
469
527
  if (stale && !infra.size && judged.every((line) => LAND_BASE_STALE_LINE.test(line) || LAND_BASE_STALE_CONSEQUENCE_LINES.some((re) => re.test(line)))) {
@@ -520,7 +578,20 @@ function observeLandWorktreeCreateCapped(deps: LiveMoveDeps, data: { card: strin
520
578
  /** 같은 머리에 한 번 더 시도해도 되나 — 앞 시도가 «전부» 끝났고(ok:false) «전부» infra 이고 상한 밑일 때만. */
521
579
  function landRetryAllowed(prior: readonly LandAttempt[]): boolean {
522
580
  return prior.length > 0 && prior.length < LAND_ATTEMPTS_PER_HEAD_ON_INFRA
523
- && prior.every((entry) => entry.ok === false && (entry.class === 'infra' || legacyMissingTscRuntime(entry)));
581
+ && prior.every((entry) => entry.ok === false && (entry.class === 'infra' || entry.class === 'recovery' || legacyMissingTscRuntime(entry)));
582
+ }
583
+
584
+ function recoveryAdmissionReady(card: TaskCard, prior: readonly LandAttempt[], pr: number, head: string, nowMs = Date.now()): boolean {
585
+ const last = prior.at(-1);
586
+ if (last?.class !== 'recovery') return true;
587
+ if (last.reason === 'gate-host-busy') return nowMs >= Date.parse(last.at) + 30_000
588
+ && (card.history ?? []).some((event) => event.event === 'rejudge-on-head' && event.kind === 'land'
589
+ && event.effect === 'recover-wait-retry' && event.pr === pr && event.head?.toLowerCase() === head.toLowerCase()
590
+ && Date.parse(event.at) >= Date.parse(last.at));
591
+ if (last.reason === 'review-missing') return (card.reviewRequests ?? []).some((request) => request.pr === pr
592
+ && request.head.toLowerCase() === head.toLowerCase() && Date.parse(request.at) >= Date.parse(last.at) && !request.error)
593
+ && !pendingReviewResults(card).some((request) => request.pr === pr && request.head.toLowerCase() === head.toLowerCase());
594
+ return false;
524
595
  }
525
596
 
526
597
  /** A previous release classified a missing node interpreter as judgement; only that exact recorded shape may be reopened. */
@@ -541,8 +612,9 @@ export function openLandAttempts<T extends Pick<LandAttempt, 'at' | 'class'>>(pr
541
612
  }
542
613
 
543
614
  /** 카드의 이 PR·머리에 인프라 재시도가 남았나(재판정 틱이 «머리 그대로»여도 land 단계까지 가게). */
544
- export function landRetryPending(card: Pick<TaskCard, 'landAttempts'>, pr: number, head: string): boolean {
545
- return landRetryAllowed((card.landAttempts ?? []).filter(sameHeadOf(pr, head)));
615
+ export function landRetryPending(card: TaskCard, pr: number, head: string): boolean {
616
+ const attempts = (card.landAttempts ?? []).filter(sameHeadOf(pr, head));
617
+ return landRetryAllowed(attempts) && recoveryAdmissionReady(card, attempts, pr, head);
546
618
  }
547
619
 
548
620
  export const LAND_RETRY_ON_INFRA_EVENT = 'land-retry-on-infra';
@@ -575,7 +647,21 @@ export async function executeLiveLand(
575
647
  let view: (PrHeadView & { isDraft: boolean }) | null;
576
648
  try { view = await (deps.landPrHead ?? defaultLandPrHead)(pr, cwd); } catch { view = null; }
577
649
  if (!view || !/^[0-9a-f]{40}$/i.test(view.head)) return reject(card.id, `PR #${pr} head unknown`, reviewRepo);
578
- if (view.state !== 'OPEN') return reject(card.id, `PR #${pr} is ${view.state}`, reviewRepo);
650
+ if (view.state !== 'OPEN') {
651
+ // TA-CARD-MERGE-RECONCILE — 실패 카드에 묶인 PR을 사람이 손수 병합한 경우만 이 자리에서 정산한다; 정산이 아니면 종전 거절 그대로.
652
+ if (view.state === 'MERGED') {
653
+ let hand: HandMergePrView | null = null;
654
+ try { hand = await (deps.handMergePr ?? defaultHandMergePr)(pr, cwd); } catch { hand = null; }
655
+ if (hand?.mergeCommit) {
656
+ const settled = reconcileHandMergedCard({ number: pr, url: hand.url ?? view.url ?? '', headRefOid: view.head, state: 'MERGED',
657
+ baseRefName: hand.baseRefName ?? 'main', mergedAt: hand.mergedAt ?? '', mergeCommit: hand.mergeCommit },
658
+ cwd, deps.statePath ? { statePath: deps.statePath } : {});
659
+ if (settled.outcome === 'reconciled')
660
+ return withRepo(observe(deps, { kind, card: card.id, ok: true, executed: true, detail: `PR #${pr} 손 병합 정산 — card ${settled.status} (merge ${settled.mergeSha.slice(0, 12)})` }));
661
+ }
662
+ }
663
+ return reject(card.id, `PR #${pr} is ${view.state}`, reviewRepo);
664
+ }
579
665
  if (view.isDraft !== false) return reject(card.id, `PR #${pr} is draft or draft status unknown`, reviewRepo);
580
666
  if (ctx.produced?.prUrl && (!view.url || view.url.trim().replace(/\/+$/, '').toLowerCase() !== ctx.produced.prUrl.trim().replace(/\/+$/, '').toLowerCase())) {
581
667
  return reject(card.id, `PR #${pr} URL mismatches run evidence`, reviewRepo);
@@ -622,7 +708,7 @@ export async function executeLiveLand(
622
708
  }
623
709
  }
624
710
  prior = openLandAttempts((current.landAttempts ?? []).filter(sameHeadOf(pr, view!.head)), ctx.gateAt);
625
- if (prior.length && !landRetryAllowed(prior)) return undefined;
711
+ if (prior.length && (!landRetryAllowed(prior) || !recoveryAdmissionReady(current, prior, pr, view!.head, (deps.now ?? (() => new Date()))().getTime()))) return undefined;
626
712
  claimed = true;
627
713
  return { ...current, landAttempts: [...(current.landAttempts ?? []), { pr, head: view!.head, at }] };
628
714
  });
@@ -721,7 +807,7 @@ export async function executeLiveLand(
721
807
  detail = (error instanceof Error ? error.message : String(error)).slice(-300);
722
808
  failure = classifyLandFailure({ thrown: detail });
723
809
  }
724
- const retryAllowed = failure?.class === 'infra' && attempt < LAND_ATTEMPTS_PER_HEAD_ON_INFRA;
810
+ const retryAllowed = (failure?.class === 'infra' || failure?.class === 'recovery') && attempt < LAND_ATTEMPTS_PER_HEAD_ON_INFRA;
725
811
  // 인프라 실패로 재시도가 남으면 주기 표시도 푼다 — 같은 주기 id(재판정 틱의 `rejudge:<card>:<head>`)가 그 한 번을 막지 않게.
726
812
  if (retryAllowed && cycle) landedCycles.delete(cycle);
727
813
  if (worktree && queueConfig && ok) {
@@ -16,6 +16,8 @@ import { createHash } from 'node:crypto';
16
16
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
17
17
  import { join, resolve } from 'node:path';
18
18
  import { debug } from '../debug/log.js';
19
+ import { memoryQuantityBytes } from '../task-orchestrator/surfaces/pod-lease.js';
20
+ import { parsePodPool } from '../task-orchestrator/surfaces/pod-pool.js';
19
21
  import { shellQuote } from './task-hand.js';
20
22
 
21
23
  /** `taskAgent.parentHost` 설정 칸. */
@@ -42,6 +44,11 @@ const DEFAULT_REMOTE_ELANOUS = '$HOME/.local/share/elanous/bin/elanous';
42
44
  const DEFAULT_REMOTE_CONFIG_DIR = '$HOME/.elanous';
43
45
  const HOST_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]{0,127}$/;
44
46
 
47
+ /** Missing child-provider metadata keeps the established Pod default: the HQ Codex mirror is needed. */
48
+ export function shouldInstallRemoteCodexAccess(effectiveChildProvider: string | undefined): boolean {
49
+ return effectiveChildProvider === undefined || effectiveChildProvider === 'openai-codex';
50
+ }
51
+
45
52
  /**
46
53
  * 켜졌나 — env 가 이긴다(`off`·`0`·빈 값이면 끔). env 가 호스트를 주면 나머지 칸(cwd 등)은 설정에서 받는다.
47
54
  * cwd 가 없으면 켜지지 않는다(어디서 띄울지 모르는 원격 발사는 하지 않는다).
@@ -74,6 +81,50 @@ export function resolveParentHosts(config: ParentHostSetting | undefined, env: N
74
81
 
75
82
  /** Capacity sample is read on the host before launch. Unknown or saturated capacity is not a positive weight. */
76
83
  export interface ParentHostCapacity { approvalHeadroom: number; load: number }
84
+
85
+ export interface ParentHostPodFit {
86
+ state: 'fits' | 'never-fits' | 'unmeasured';
87
+ memoryLimit: string;
88
+ requiredBytes: number | null;
89
+ allocatableBytes: number | null;
90
+ reason: string;
91
+ }
92
+
93
+ /** Read node allocatable memory only. This preflight never creates a probe Pod. */
94
+ export function readParentHostPodFit(target: ParentHostConfig, memoryLimit: string, ssh: SshRunner = defaultSshRunner): ParentHostPodFit {
95
+ const requiredBytes = memoryQuantityBytes(memoryLimit);
96
+ const unknown = (reason: string, allocatableBytes: number | null = null): ParentHostPodFit =>
97
+ ({ state: 'unmeasured', memoryLimit, requiredBytes, allocatableBytes, reason });
98
+ if (requiredBytes === null || requiredBytes <= 0) return unknown('memory-limit-unreadable');
99
+ // Without an explicit pool, the remote current kubectl context may be unrelated to the launched Job.
100
+ if (!target.podPool) return unknown('pod-pool-unset');
101
+ let members: ReturnType<typeof parsePodPool>;
102
+ try { members = parsePodPool(target.podPool); }
103
+ catch { return unknown('pod-pool-unreadable'); }
104
+ if (!members.length) return unknown('pod-pool-empty');
105
+ let maximum = 0;
106
+ let unreadable = false;
107
+ for (const member of members) {
108
+ let result: ReturnType<SshRunner>;
109
+ try { result = ssh(target.host, `kubectl --context ${shellQuote(member.context)} get nodes -o json`, 15_000); }
110
+ catch { unreadable = true; continue; }
111
+ if (result.status !== 0) { unreadable = true; continue; }
112
+ try {
113
+ const parsed = JSON.parse(result.stdout) as { items?: Array<{ status?: { allocatable?: { memory?: unknown } } }> };
114
+ if (!Array.isArray(parsed.items) || parsed.items.length === 0) { unreadable = true; continue; }
115
+ for (const node of parsed.items) {
116
+ const raw = node?.status?.allocatable?.memory;
117
+ const bytes = typeof raw === 'string' ? memoryQuantityBytes(raw) : null;
118
+ if (bytes === null || bytes <= 0) { unreadable = true; continue; }
119
+ maximum = Math.max(maximum, bytes);
120
+ }
121
+ } catch { unreadable = true; }
122
+ }
123
+ if (maximum >= requiredBytes) return { state: 'fits', memoryLimit, requiredBytes, allocatableBytes: maximum, reason: 'node-allocatable-fits' };
124
+ if (unreadable || maximum === 0) return unknown('node-allocatable-unmeasured', maximum || null);
125
+ return { state: 'never-fits', memoryLimit, requiredBytes, allocatableBytes: maximum, reason: 'memory-never-fits' };
126
+ }
127
+
77
128
  const CAPACITY_MARKER = '__ELANOUS_PARENT_CAPACITY__';
78
129
  const APPROVAL_MARKER = '__ELANOUS_PARENT_APPROVALS__';
79
130
  const LOAD_MARKER = '__ELANOUS_PARENT_LOAD__';
@@ -170,10 +221,12 @@ export function remoteLaunchScript(target: ParentHostConfig, args: readonly stri
170
221
  }
171
222
 
172
223
  /** ssh 실행기(시험 주입). */
173
- export type SshRunner = (host: string, script: string, timeoutMs: number) => { status: number | null; stdout: string; stderr: string };
224
+ export type SshRunner = (host: string, script: string, timeoutMs: number, stdin?: string) => { status: number | null; stdout: string; stderr: string };
174
225
 
175
- export const defaultSshRunner: SshRunner = (host, script, timeoutMs) => {
176
- const result = spawnSync('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=8', '-o', 'ControlPath=none', host, script], { encoding: 'utf8', timeout: timeoutMs, maxBuffer: 32 * 1024 * 1024 });
226
+ export const defaultSshRunner: SshRunner = (host, script, timeoutMs, stdin) => {
227
+ const result = spawnSync('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=8', '-o', 'ControlPath=none', host, script], {
228
+ encoding: 'utf8', timeout: timeoutMs, maxBuffer: 32 * 1024 * 1024, ...(stdin !== undefined ? { input: stdin } : {}),
229
+ });
177
230
  return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? (result.error ? String(result.error) : '') };
178
231
  };
179
232
 
@@ -302,6 +355,43 @@ export function launchRemoteParent(target: ParentHostConfig, args: readonly stri
302
355
  throw new Error(`원격 부모 발사 결과 불확실(${target.host} · rc=${result.status}) — 중복을 피해 로컬로 다시 띄우지 않는다 · 원격에서 ELANOUS_RUN_ID=${env.ELANOUS_RUN_ID ?? '?'} 를 확인: ${(result.stderr.trim().split('\n').pop() || '').slice(0, 160)}`);
303
356
  }
304
357
 
358
+ /** Install access-only Codex copies over SSH stdin; credentials never enter argv, shell text, or logs. */
359
+ export function installRemoteCodexAccess(target: ParentHostConfig, mirror: { elanousAuth: string; codexAuth: string; account?: string }, ssh: SshRunner = defaultSshRunner): void {
360
+ let elanous: { version?: number; providers?: Record<string, Record<string, unknown>> };
361
+ let codex: { auth_mode?: string; tokens?: Record<string, unknown> };
362
+ try {
363
+ elanous = JSON.parse(mirror.elanousAuth) as typeof elanous;
364
+ codex = JSON.parse(mirror.codexAuth) as typeof codex;
365
+ } catch { throw new Error('invalid local Codex access mirror'); }
366
+ const provider = elanous.providers?.['openai-codex'];
367
+ const elanousTokens = provider?.tokens as Record<string, unknown> | undefined;
368
+ const codexTokens = codex.tokens;
369
+ if (!Number.isSafeInteger(elanous.version) || Number(elanous.version) < 1
370
+ || typeof elanousTokens?.accessToken !== 'string' || !elanousTokens.accessToken || elanousTokens.refreshToken !== '' || elanousTokens.refresh_token !== ''
371
+ || codex.auth_mode !== 'chatgpt'
372
+ || typeof codexTokens?.access_token !== 'string' || !codexTokens.access_token || codexTokens.refresh_token !== '' || codexTokens.refreshToken !== '')
373
+ throw new Error('Codex access mirror must contain a versioned store, auth mode, access tokens, and empty refresh tokens');
374
+
375
+ const account = mirror.account ?? 'default';
376
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(account)) throw new Error('invalid Codex mirror account name');
377
+
378
+ const payload = JSON.stringify({ elanousVersion: elanous.version, provider, codexAuth: codex, account, storeKey: account === 'default' ? 'openai-codex' : `openai-codex:${account}` });
379
+ const configDir = remotePath(target.configDir ?? DEFAULT_REMOTE_CONFIG_DIR);
380
+ // HQ owns token metadata; the remote keeps only the selected named Codex credential in managed account homes.
381
+ const code = [
382
+ 'const fs=require("node:fs"),path=require("node:path"),os=require("node:os");',
383
+ 'const payload=JSON.parse(fs.readFileSync(0,"utf8"));',
384
+ 'const read=(file)=>{try{return JSON.parse(fs.readFileSync(file,"utf8"))}catch{return {}}};',
385
+ 'const write=(file,value)=>{const temp=file+"."+process.pid+".tmp";try{fs.writeFileSync(temp,JSON.stringify(value),{mode:0o600});fs.chmodSync(temp,0o600);fs.renameSync(temp,file)}catch(error){try{fs.unlinkSync(temp)}catch{};throw error}};',
386
+ 'const elanousFile=path.join(process.argv[1],"auth.json"),configDir=path.dirname(elanousFile);fs.mkdirSync(configDir,{recursive:true,mode:0o700});',
387
+ 'const elanous=read(elanousFile);if(typeof elanous.version!=="number")elanous.version=payload.elanousVersion;elanous.providers={...(elanous.providers||{})};const defaultHome=path.join(os.homedir(),".codex"),managedAccounts=path.join(configDir,"codex-accounts");for(const key of Object.keys(elanous.providers)){if(key.startsWith("openai-codex:"))delete elanous.providers[key]}fs.rmSync(managedAccounts,{recursive:true,force:true});fs.rmSync(path.join(configDir,"remote-codex-mirror.json"),{force:true});',
388
+ 'const accountHome=payload.account==="default"?defaultHome:path.join(configDir,"codex-accounts",payload.account),tokens={...(payload.provider.tokens||{}),refreshToken:"",refresh_token:""};const upsert=(key,codexHome)=>{const current=elanous.providers[key]||{};elanous.providers[key]={...current,...payload.provider,codexHome,chatGPT:{...(current.chatGPT||{}),...(payload.provider.chatGPT||{})},tokens}};upsert("openai-codex",defaultHome);if(payload.storeKey!=="openai-codex")upsert(payload.storeKey,accountHome);write(elanousFile,elanous);',
389
+ 'const incoming=payload.codexAuth;const installCodex=(home)=>{const file=path.join(home,"auth.json");fs.mkdirSync(home,{recursive:true,mode:0o700});const current=read(file),merged={...current,...incoming};merged.auth_mode=incoming.auth_mode;if(Object.prototype.hasOwnProperty.call(incoming,"last_refresh"))merged.last_refresh=incoming.last_refresh;else delete merged.last_refresh;merged.tokens={...(incoming.tokens||{}),refresh_token:"",refreshToken:""};write(file,merged)};installCodex(defaultHome);if(accountHome!==defaultHome)installCodex(accountHome);',
390
+ ].join('');
391
+ const result = ssh(target.host, `umask 077; mkdir -p ${configDir} "$HOME/.codex" && bun -e ${shellQuote(code)} ${configDir}`, 20_000, payload);
392
+ if (result.status !== 0) throw new Error(`remote Codex access mirror failed (ssh rc=${result.status ?? 'unknown'})`);
393
+ }
394
+
305
395
  // ── 관측: 원격 런 원장 거울 ─────────────────────────────────────────────────────────────
306
396
 
307
397
  const RUN_ID_RE = /^run-[A-Za-z0-9_-]{4,64}$/;
@@ -1,7 +1,8 @@
1
+ import { spawnSync } from 'node:child_process';
1
2
  import { debug } from '../debug/log.js';
2
3
  import { listChecklist, setItemIfSnapshot, type Checklist } from '../release-loop/checklist.js';
3
4
  import { judgeLandedCell, parseJudgeSignals, type GreenVerdict } from '../release-loop/landed-to-green.js';
4
- import { cardPrNumber, readTaskAgentState, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
5
+ import { HAND_MOVE_HISTORY_EVENT, LIVE_MOVE_HISTORY_EVENT, LIVE_MOVE_RESULT_EVENT, cardPrNumber, readTaskAgentState, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
5
6
  import { isGoalOnlyPr } from './judge.js';
6
7
 
7
8
  export interface LandedTaskPr { number: number; url: string; headRefOid: string; state: string; baseRefName: string; mergedAt: string; files?: Array<{ path: string }> }
@@ -142,3 +143,81 @@ export function closeMergedTaskCard(pr: LandedTaskPr, cwd: string, deps: Postlan
142
143
  log('task-agent', 'postland-card-closed', { pr: pr.number, card: card.id, version, id: item.id, outcome: complete ? 'complete' : 'partial', verdict });
143
144
  return item.id;
144
145
  }
146
+
147
+ const defaultGit = (cwd: string, args: string[]): { status: number; stdout: string; stderr: string } => {
148
+ const run = spawnSync('git', args, { cwd, encoding: 'utf8' });
149
+ return { status: run.status ?? 1, stdout: run.stdout ?? '', stderr: run.stderr ?? '' };
150
+ };
151
+
152
+ export type HandMergeReconcileOutcome =
153
+ | { outcome: 'reconciled'; card: string; status: 'landed-by-hand' | 'landed'; pr: number; head: string; mergeSha: string; mergedAt: string }
154
+ | { outcome: 'not-reconciled'; reason: 'pr-not-merged' | 'no-merge-sha' | 'no-bound-card' | 'ambiguous-card' | 'card-not-failed' | 'not-ancestor-of-main' | 'card-binding-changed-before-write' };
155
+
156
+ export interface HandMergeReconcileDeps {
157
+ statePath?: string;
158
+ mainRef?: string;
159
+ updateCard?: typeof updateTaskCard;
160
+ git?: (cwd: string, args: string[]) => { status: number; stdout: string; stderr: string };
161
+ log?: typeof debug.log;
162
+ }
163
+
164
+ /**
165
+ * TA-CARD-MERGE-RECONCILE — 실패 카드에 묶인 PR을 사람이 손수 병합했을 때만 카드를 정산한다.
166
+ * MERGED + merge SHA가 `${mainRef}`(기본 `origin/main`) 조상일 때 status=landed-by-hand(또는 merge 커밋이
167
+ * land attempt head와 일치하면 landed)로 `updateTaskCard` 파일-락 트랜잭션 하나로 갱신하고,
168
+ * 이전 status·사유는 history `hand-move` 줄에 보존한다. OPEN·비조상·묶임 없음은 카드를 그대로 둔다.
169
+ */
170
+ export function reconcileHandMergedCard(pr: LandedTaskPr & { mergeCommit?: string }, cwd: string, deps: HandMergeReconcileDeps = {}): HandMergeReconcileOutcome {
171
+ const log = deps.log ?? debug.log.bind(debug);
172
+ if (pr.state !== 'MERGED' || !pr.url) return { outcome: 'not-reconciled', reason: 'pr-not-merged' };
173
+ const mergeSha = pr.mergeCommit ?? '';
174
+ if (!/^[a-f0-9]{40}$/i.test(mergeSha)) return { outcome: 'not-reconciled', reason: 'no-merge-sha' };
175
+ const path = deps.statePath ?? taskAgentStatePath();
176
+ const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(path).tasks ?? {};
177
+ const cards = Object.values(tasks).filter((card) => card.taLand && cardPrNumber(card) === pr.number
178
+ && typeof card.pr === 'object' && card.pr.url?.replace(/\/+$/, '') === pr.url.replace(/\/+$/, ''));
179
+ if (cards.length !== 1) {
180
+ log('task-agent', 'postland-card-hand-skipped', { pr: pr.number, reason: cards.length ? 'ambiguous-card' : 'no-bound-card' });
181
+ return { outcome: 'not-reconciled', reason: cards.length ? 'ambiguous-card' : 'no-bound-card' };
182
+ }
183
+ const card = cards[0]!;
184
+ if (card.status !== 'failed') {
185
+ log('task-agent', 'postland-card-hand-skipped', { pr: pr.number, card: card.id, reason: 'card-not-failed', status: card.status });
186
+ return { outcome: 'not-reconciled', reason: 'card-not-failed' };
187
+ }
188
+ const mainRef = deps.mainRef ?? 'origin/main';
189
+ if ((deps.git ?? defaultGit)(cwd, ['merge-base', '--is-ancestor', mergeSha, mainRef]).status !== 0) {
190
+ log('task-agent', 'postland-card-hand-skipped', { pr: pr.number, card: card.id, reason: 'not-ancestor-of-main', mainRef });
191
+ return { outcome: 'not-reconciled', reason: 'not-ancestor-of-main' };
192
+ }
193
+ const at = new Date().toISOString();
194
+ let reconciled: { status: 'landed-by-hand' | 'landed' } | undefined;
195
+ // The card lock keeps the settlement atomic with its binding checks: a card that flipped off
196
+ // `failed` mid-flight is left untouched for its owning path to finish.
197
+ (deps.updateCard ?? updateTaskCard)(path, card.id, (current, currentTasks) => {
198
+ const matching = Object.values(currentTasks).filter((candidate) => candidate.taLand && cardPrNumber(candidate) === pr.number
199
+ && typeof candidate.pr === 'object' && candidate.pr.url?.replace(/\/+$/, '') === pr.url.replace(/\/+$/, ''));
200
+ if (matching.length !== 1 || matching[0]?.id !== card.id) return undefined;
201
+ if (!current || current.status !== 'failed' || cardPrNumber(current) !== pr.number || typeof current.pr !== 'object'
202
+ || current.pr.url?.replace(/\/+$/, '') !== pr.url.replace(/\/+$/, '')) return undefined;
203
+ const status = (current.landAttempts ?? []).some((attempt) => attempt.pr === pr.number
204
+ && attempt.head.toLowerCase() === mergeSha.toLowerCase()) ? 'landed' : 'landed-by-hand';
205
+ const priorReason = [...current.history].reverse().find((event) => event.event !== LIVE_MOVE_HISTORY_EVENT
206
+ && event.event !== LIVE_MOVE_RESULT_EVENT && event.event !== HAND_MOVE_HISTORY_EVENT)?.detail ?? '사유 기록 없음';
207
+ const detail = status === 'landed'
208
+ ? `PR #${pr.number} 병합 정산: merge ${mergeSha}가 land attempt head와 일치 — status landed; 이전 status: failed; 이전 사유: ${priorReason}`
209
+ : `PR #${pr.number} 손 병합 정산: merge ${mergeSha}가 ${mainRef} 조상 — status landed-by-hand; 이전 status: failed; 이전 사유: ${priorReason}`;
210
+ reconciled = { status };
211
+ return { ...current,
212
+ status,
213
+ prTerminal: { pr: pr.number, url: pr.url, head: mergeSha, state: 'MERGED' as const, at },
214
+ history: [...current.history, { at, event: HAND_MOVE_HISTORY_EVENT, pr: pr.number, head: mergeSha, detail }],
215
+ };
216
+ });
217
+ if (!reconciled) {
218
+ log('task-agent', 'postland-card-hand-pending', { pr: pr.number, card: card.id, reason: 'card-binding-changed-before-write' });
219
+ return { outcome: 'not-reconciled', reason: 'card-binding-changed-before-write' };
220
+ }
221
+ log('task-agent', 'postland-card-hand-reconciled', { pr: pr.number, card: card.id, status: reconciled.status, mergeSha, mainRef });
222
+ return { outcome: 'reconciled', card: card.id, status: reconciled.status, pr: pr.number, head: pr.headRefOid, mergeSha, mergedAt: pr.mergedAt };
223
+ }