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
@@ -11,11 +11,12 @@
11
11
  */
12
12
  import { debug } from '../debug/log.js';
13
13
  import { appendRunLedgerEntry, type RunLedgerEntry, type RunLedgerWriter, type RunShardIdentity } from './run-ledger.js';
14
+ import type { PodChildEvidence } from '../task-orchestrator/surfaces/self-implement.js';
14
15
 
15
16
  /** 닫힌 목록 — 못 고르면 `unclassified`. */
16
17
  export const RUN_STOP_CLASSES = [
17
18
  'env-unrelated', 'main-sync', 'pod-died', 'review-repeat',
18
- 'review-out-of-scope', 'evidence-uncovered', 'fabric', 'launch-failed', 'gate-failed', 'unclassified',
19
+ 'review-out-of-scope', 'scope-escape', 'evidence-uncovered', 'fabric', 'launch-failed', 'gate-failed', 'unclassified',
19
20
  ] as const;
20
21
  export type RunStopClass = typeof RUN_STOP_CLASSES[number];
21
22
 
@@ -28,6 +29,8 @@ export interface RunStopRecord {
28
29
  evidenceRef: string;
29
30
  /** 다음 한 수(사람·힐러가 읽는다). */
30
31
  nextMove: string;
32
+ /** Facts from the complete child JSON, lifted before the Pod stdout tail is shortened. */
33
+ childEvidence?: PodChildEvidence;
31
34
  }
32
35
 
33
36
  export const RUN_STOP_EVENT = 'stop';
@@ -44,6 +47,7 @@ export interface RunStopInput {
44
47
  nextMove: string;
45
48
  /** 관측용 — 어느 자리가 불렀나(merge-hold · implement-aborted · draft-pr-open-failed · pod-exit · launch-failed). */
46
49
  site?: string;
50
+ childEvidence?: PodChildEvidence;
47
51
  }
48
52
 
49
53
  export function isRunStopClass(value: unknown): value is RunStopClass {
@@ -99,6 +103,7 @@ export function recordRunStop(input: RunStopInput, write: RunLedgerWriter = appe
99
103
  cause: boundRunStopCause(input.cause),
100
104
  evidenceRef: input.evidenceRef,
101
105
  nextMove: input.nextMove,
106
+ ...(input.childEvidence ? { childEvidence: input.childEvidence } : {}),
102
107
  };
103
108
  const entry: RunLedgerEntry = {
104
109
  timestamp: new Date().toISOString(), runId: input.runId, event: RUN_STOP_EVENT,
@@ -120,5 +125,6 @@ export function readRunStopRecord(entry: RunLedgerEntry): RunStopRecord | undefi
120
125
  if (entry.event !== RUN_STOP_EVENT) return undefined;
121
126
  const data = entry.data as Partial<RunStopRecord>;
122
127
  if (typeof data.cause !== 'string' || typeof data.evidenceRef !== 'string' || typeof data.nextMove !== 'string') return undefined;
123
- return { class: isRunStopClass(data.class) ? data.class : 'unclassified', cause: data.cause, evidenceRef: data.evidenceRef, nextMove: data.nextMove };
128
+ return { class: isRunStopClass(data.class) ? data.class : 'unclassified', cause: data.cause, evidenceRef: data.evidenceRef, nextMove: data.nextMove,
129
+ ...(data.childEvidence ? { childEvidence: data.childEvidence } : {}) };
124
130
  }
@@ -69,6 +69,7 @@ import { stageNonGitDir, stageFile, applyShadowToTarget, applyFileToTarget } fro
69
69
  import type { TargetKind } from './target-kind.js';
70
70
  import { basename } from 'node:path';
71
71
  import { ghAutomationEnv, makePrManager, type PrManager } from '../autopilot/pr-manager.js';
72
+ import { cardPrNumber, taskAgentStatePath, updateTaskCard } from '../task-agent/task-hand.js';
72
73
  import { defaultSpawnGh, lookupOpenDraftPrs } from '../cli/logs-abandoned-draft-prs.js';
73
74
  import { loadRunLedger, runLedgerDir } from './run-ledger.js';
74
75
  import { readdirSync } from 'node:fs';
@@ -2494,11 +2495,14 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2494
2495
  openPr: async ({ title, body, head, base, draft, labels, cwd }) => {
2495
2496
  const resolvedBase = assertBaseBranchOnOrigin(cwd, base);
2496
2497
  const harnessSeat = process.env.ELANOUS_HARNESS_SEAT;
2498
+ const taskCardId = process.env.ELANOUS_TASK_CARD_ID;
2499
+ const bodyWithCard = taskCardId && /^[A-Za-z0-9][A-Za-z0-9._:-]{2,}$/.test(taskCardId)
2500
+ ? `${body}\n\n카드: ${taskCardId}` : body;
2497
2501
  const outcome = (o.prManager ?? makePrManager()).upsertPr({
2498
2502
  branch: head,
2499
2503
  worktreePath: cwd,
2500
2504
  title,
2501
- body: buildPrBody(cwd, body),
2505
+ body: buildPrBody(cwd, bodyWithCard),
2502
2506
  commitMessage: title,
2503
2507
  ...(resolvedBase ? { base: resolvedBase } : {}),
2504
2508
  ...(draft !== undefined ? { draft } : {}),
@@ -2511,6 +2515,33 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2511
2515
  });
2512
2516
  if (!outcome.ok) throw new Error(`self-implement PR ${outcome.reason} 실패: ${outcome.detail}`);
2513
2517
  const number = Number.parseInt(outcome.url.match(/\/pull\/(\d+)/)?.[1] ?? '', 10);
2518
+ if (outcome.supersededPr && Number.isSafeInteger(number) && number > 0) {
2519
+ const rebindFailed = (reason: string): never => {
2520
+ debug.log('self-implement.pr', 'same-cell-card-rebind-failed', {
2521
+ cardId: taskCardId ?? null, oldPr: outcome.supersededPr, newPr: number,
2522
+ url: outcome.url, reason,
2523
+ }, { level: 'warn' });
2524
+ throw new Error(`same-cell 새 draft ${outcome.url} 개설됨; 카드 재결속 실패(${reason}) — 새 PR 수확 필요`);
2525
+ };
2526
+ debug.log('self-implement.pr', 'same-cell-rebound', {
2527
+ cardId: taskCardId ?? null, oldPr: outcome.supersededPr, newPr: number, url: outcome.url,
2528
+ oldDraftCleanup: 'deferred',
2529
+ });
2530
+ const cardId = taskCardId ?? rebindFailed('카드 ID 없음');
2531
+ let rebound: ReturnType<typeof updateTaskCard>;
2532
+ try {
2533
+ rebound = updateTaskCard(taskAgentStatePath(), cardId, (card) => {
2534
+ if (!card || card.refSource === 'manual' || (cardPrNumber(card) !== undefined
2535
+ && cardPrNumber(card) !== outcome.supersededPr && cardPrNumber(card) !== number)) return undefined;
2536
+ if (cardPrNumber(card) === number && card.history.some((event) => event.event === 'same-cell-pr-rebound' && event.pr === number)) return undefined;
2537
+ return { ...card, pr: { number, url: outcome.url }, history: [...card.history, {
2538
+ at: new Date().toISOString(), event: 'same-cell-pr-rebound', pr: number,
2539
+ detail: `이전 draft #${outcome.supersededPr} 정리 후속 · 새 PR #${number} 결속`,
2540
+ }] };
2541
+ });
2542
+ } catch (error) { rebindFailed(error instanceof Error ? error.message : String(error)); }
2543
+ if (!rebound || cardPrNumber(rebound) !== number) rebindFailed('카드 없음 또는 기존 PR 결속 충돌');
2544
+ }
2514
2545
  return { url: outcome.url, number: Number.isFinite(number) ? number : 0 };
2515
2546
  },
2516
2547
 
@@ -13,7 +13,7 @@
13
13
  * main-sync → rebase-regate 리베이스(MERGE-INTENT-RESOLVE 의도 해석) 뒤 재게이트
14
14
  * pod-died → resume-from-salvage `salvage/run-<6hex>/<leaf>` 가지에서 resume(DRAFT-NOT-ARCHIVE)
15
15
  * evidence-uncovered → derive-evidence-rejudge 런 출력·시험·배선에서 증거를 끌어내 1회 재판정
16
- * review-repeat · review-out-of-scope · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
16
+ * review-repeat · review-out-of-scope · scope-escape · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
17
17
  *
18
18
  * 사다리의 «출처»: `graphs/overlays/stop-heal-ladder.yaml` 이 갈래마다 처방 노드(id = 처방 이름)를 선언한다.
19
19
  * 그 갈래에 얹힌 오버레이가 더한 노드 id 가 처방이다(source='graph'). 선언이 없거나 못 읽으면
@@ -50,6 +50,7 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
50
50
  'evidence-uncovered': 'derive-evidence-rejudge',
51
51
  'review-repeat': 'needs-owner',
52
52
  'review-out-of-scope': 'needs-owner',
53
+ 'scope-escape': 'needs-owner',
53
54
  fabric: 'needs-owner',
54
55
  'launch-failed': 'needs-owner',
55
56
  'gate-failed': 'needs-owner',
@@ -164,6 +165,12 @@ export interface AutohealDeps {
164
165
  writeLedger?: RunLedgerWriter;
165
166
  /** 사다리 선언 읽기 — 기본은 활성 템플릿 ⊕ `graphs/overlays`. 던지면 코드 표로 간다. */
166
167
  loadLadder?: () => AutohealLadder;
168
+ /**
169
+ * 같은 골·칸의 «앞 런» stop 레코드(원장 줄은 `readRunStopRecord` 로 읽는다).
170
+ * 같은 갈래(class)의 멈춤이 반복되면 자동 재시도를 하지 않고 사유를 골 되먹임 대상으로 넘긴다.
171
+ * 안 주면 지금과 똑같이 동작한다.
172
+ */
173
+ priorStops?: readonly RunStopRecord[];
167
174
  }
168
175
 
169
176
  /**
@@ -184,6 +191,15 @@ export function autohealAlreadyAttempted(ledger: readonly RunLedgerEntry[] | nul
184
191
  return ledger.some((e) => e.event === AUTOHEAL_EVENT && e.data?.class === cls && e.data?.mode === mode);
185
192
  }
186
193
 
194
+ /**
195
+ * 반복 멈춤 가드 — 앞 런의 stop 레코드 중 같은 갈래(class)가 `threshold` 이상이면 참.
196
+ * 같은 골에서 같은 갈래가 반복되면 자동 재시도를 끊고 사유를 골 되먹임 대상으로 넘긴다.
197
+ */
198
+ export function repeatedStop(prior: readonly RunStopRecord[] | undefined, record: RunStopRecord, threshold = 2): boolean {
199
+ if (!prior) return false;
200
+ return prior.filter((p) => p.class === record.class).length >= threshold;
201
+ }
202
+
187
203
  function observe(event: string, data: Record<string, unknown>): void {
188
204
  try { debug.log('self-implement.autoheal', event, data); } catch { /* observation is fail-soft */ }
189
205
  }
@@ -197,6 +213,14 @@ export async function autohealFromStop(ctx: AutohealContext, deps: AutohealDeps
197
213
  const { action, source, overlayId } = pickAutohealAction(cls, deps.loadLadder);
198
214
  const base = { runId: ctx.runId, class: cls, action, source, ...(overlayId ? { overlayId } : {}), mode };
199
215
 
216
+ if (repeatedStop(deps.priorStops, ctx.record)) {
217
+ // ⛔ 같은 골에서 같은 갈래의 멈춤이 반복되면 자동 재시도를 하지 않는다 — 사유를 골 되먹임 대상으로 넘긴다.
218
+ const n = deps.priorStops!.filter((p) => p.class === cls).length;
219
+ const reason = `repeat-stop: ${cls} ×${n} — feed back to goal: ${ctx.record.cause}`;
220
+ observe('repeat-stop', { ...base, reason });
221
+ return { ...base, outcome: 'needs-owner', reason };
222
+ }
223
+
200
224
  let ledger: readonly RunLedgerEntry[] | null = null;
201
225
  try {
202
226
  ledger = (deps.loadLedger ?? ((id) => loadRunLedger(id)))(ctx.runId);
@@ -42,6 +42,8 @@ import {
42
42
  // chat 툴루프를 canonical 엔진(runGoalLoop→runCoreTurn→streamLLMWithTools)으로 라우팅.
43
43
  // ACP bridge(core-turn-bridge.ts)·dashboard(runGoalLoopHook)와 동일 엔진 재사용(재발명 제거).
44
44
  import { runGoalLoop, type CoreTurnContext, type CoreTurnDispatchTool } from '../core-turn/index.js';
45
+ import { composeChildContext, type ChildContextProfile } from '../self-implement/child-context-composition.js';
46
+ import { getHarnessSpace } from '../harness/harness-space.js';
45
47
 
46
48
  export interface RunTurnOpts {
47
49
  userConfig: UserConfig;
@@ -272,6 +274,10 @@ export function buildRecentToolObservations(
272
274
  return `[직전 턴에 네가 실행한 도구와 결과 (참고용 컨텍스트) — 이어서 교정·판단할 때 근거로 삼되, 사용자가 이 원문을 봤다고 가정하지 말 것]\n${body}`;
273
275
  }
274
276
 
277
+ /** CHILD-CONTEXT-BUDGET — 세션별 첫 goal-loop 턴 계측 1회 플래그(모듈 인메모리 —
278
+ * 원장·세션 저장소 형식은 무변경). 키: runTurn sessionId. */
279
+ const childContextComposedSessions = new Set<string>();
280
+
275
281
  /** Run one conversational turn, persisting both sides to the session
276
282
  * JSONL. Never throws on LLM failure — reraises with context. */
277
283
  export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
@@ -435,6 +441,27 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
435
441
  const goalLoopCfg = opts.userConfig.llm.goalLoop;
436
442
  const armGoalLoop = opts.goalLoop === true || goalLoopCfg?.enabled === true;
437
443
  if (armGoalLoop) {
444
+ // ⭐ CHILD-CONTEXT-BUDGET(0.2.35 칸) — 구현 자식(self-implement 공간)의 첫 goal-loop
445
+ // 턴에서 실제 effectiveSystemPrompt·turnTools 스키마·userText(골)의 구성 바이트를
446
+ // composeChildContext 로 계측해 child.context-composition 사건 1회로 남긴다.
447
+ // 관측 전용 — 프롬프트·메시지는 무변경, 계측이 턴을 깨지 않는다(fail-open).
448
+ // 게이트: harness-space SSOT 로 구현 자식만 판별(getHarnessSpace().kind === 'self-implement')·
449
+ // 세션 첫 goal-loop 무장 턴 1회(모듈 인메모리 플래그 — 원장·세션 저장소는 무변경).
450
+ // profile 은 자식 프롬프트 예산 신호(ELANOUS_PROMPT_BUDGET=lean — local 자식 스폰 시 주입)에서
451
+ // 실측 파생한다: lean → small(32k 바이트 상한), 아니면 default(무상한).
452
+ const isSelfImplementChild = getHarnessSpace()?.kind === 'self-implement';
453
+ if (isSelfImplementChild && !childContextComposedSessions.has(opts.sessionId)) {
454
+ childContextComposedSessions.add(opts.sessionId);
455
+ const childContextProfile: ChildContextProfile
456
+ = process.env.ELANOUS_PROMPT_BUDGET?.trim() === 'lean' ? 'small' : 'default';
457
+ try {
458
+ composeChildContext({
459
+ systemPrompt: effectiveSystemPrompt,
460
+ toolSchemas: JSON.stringify(turnTools),
461
+ goal: opts.userText,
462
+ }, { profile: childContextProfile });
463
+ } catch { /* 계측은 턴을 깨지 않는다 */ }
464
+ }
438
465
  const coreCtx: CoreTurnContext = {
439
466
  sessionId: opts.sessionId,
440
467
  // ⭐ 이 턴의 «사람 문장» 운반자. 없으면 표면 판정이 늘 기본값으로 떨어진다
@@ -226,7 +226,8 @@ export function providerNamesFromFallbackChain(chain: readonly string[]): string
226
226
  const seen = new Set<string>();
227
227
  for (const step of chain) {
228
228
  // `codex-credits`(체인 마지막 칸 · 크레딧)도 provider 는 openai-codex 다 — 이미 앞에 있으면 중복이라 빠진다.
229
- const name = step === 'grok' ? 'grok' : step === 'codex-rotate' || step === 'codex-credits' ? 'openai-codex' : undefined;
229
+ const name = step === 'grok' ? 'grok' : step === 'zai' ? 'glm'
230
+ : step === 'codex-rotate' || step === 'codex-credits' ? 'openai-codex' : undefined;
230
231
  if (!name || seen.has(name)) continue;
231
232
  seen.add(name);
232
233
  out.push(name);
@@ -41,6 +41,17 @@ export const WAKEUP_MAX_CALLS_PER_TURN = 6;
41
41
  export const WAKEUP_REPEAT_INVALID_ERROR =
42
42
  'repeatMinutes 는 반복 간격(분 · 1 이상)이다 — 한 번만 깨우려면 repeatMinutes 를 빼거나 0 으로 두고 delaySeconds 또는 at 만 줘라';
43
43
 
44
+ function formatWakeupTimeConflictError(req: ScheduleWakeupRequest): string {
45
+ const corrected = { ...req };
46
+ delete corrected.at;
47
+ delete corrected.atProvided;
48
+ return `at 과 delaySeconds 는 둘 중 하나만 줄 수 있다 — 교정 인자 예시(at 을 빼고 delaySeconds 사용): ${JSON.stringify(corrected)}. 같은 인자를 다시 보내지 말고 이 교정 인자로 한 번만 재시도하라`;
49
+ }
50
+
51
+ function canonicalToolArgs(args: Record<string, unknown>): string {
52
+ return JSON.stringify(Object.fromEntries(Object.entries(args).sort(([a], [b]) => a.localeCompare(b))));
53
+ }
54
+
44
55
  export type WakeupTimerHandle = unknown;
45
56
 
46
57
  export interface WakeupEntry {
@@ -79,7 +90,9 @@ export interface WakeupSchedulerDeps {
79
90
 
80
91
  export type ScheduleWakeupRequest = {
81
92
  /** «HH:MM»(로컬 시각 · 지났으면 내일). delaySeconds 와 둘 중 하나. */
82
- at?: string;
93
+ at?: unknown;
94
+ /** Host tool must preserve property presence even when the provider sent a non-string value. */
95
+ atProvided?: boolean;
83
96
  delaySeconds?: number;
84
97
  reason: string;
85
98
  /** 반복 간격(분). 첫 발화는 at/delaySeconds — 둘 다 없으면 지금부터 repeatMinutes 뒤. 0 = 일회성(생략과 같다). */
@@ -93,7 +106,7 @@ export type ScheduleWakeupResult =
93
106
  export type CancelWakeupResult = { ok: true } | { ok: false; error: string; capped?: boolean };
94
107
 
95
108
  export interface WakeupScheduler {
96
- schedule(req: ScheduleWakeupRequest): ScheduleWakeupResult;
109
+ schedule(req: ScheduleWakeupRequest, requestKey?: string): ScheduleWakeupResult;
97
110
  list(): WakeupEntry[];
98
111
  cancel(id: string): boolean;
99
112
  /** cancel 과 같되 거부 사유(없는 id · 턴 상한)를 값으로 낸다 — LLM 도구가 쓴다. */
@@ -151,12 +164,24 @@ export function createWakeupScheduler(deps: WakeupSchedulerDeps): WakeupSchedule
151
164
  const maxCallsPerTurn = deps.maxCallsPerTurn ?? WAKEUP_MAX_CALLS_PER_TURN;
152
165
  let callTurnKey: string | null = null;
153
166
  let callCount = 0;
167
+ const conflictErrors = new Map<string, string>();
168
+
169
+ const readTurnId = (): string | null => deps.currentTurnId?.() ?? null;
154
170
 
155
- /** 한 턴 호출 상한 — 넘었으면 거부 문구, 아니면 null. 턴 경계를 모르면(currentTurnId 없음) 걸지 않는다. */
156
- const loopCapError = (action: 'schedule' | 'cancel'): string | null => {
157
- if (!deps.currentTurnId) return null;
158
- const turnId = deps.currentTurnId() ?? 'none';
159
- if (turnId !== callTurnKey) { callTurnKey = turnId; callCount = 0; }
171
+ /** 한 턴 호출 상한 — 넘었으면 거부 문구, 아니면 null. 턴 경계가 unknown 이면 cap·dedupe 상태를 버린다. */
172
+ const loopCapError = (action: 'schedule' | 'cancel', observedTurnId = readTurnId()): string | null => {
173
+ if (observedTurnId === null) {
174
+ callTurnKey = null;
175
+ callCount = 0;
176
+ conflictErrors.clear();
177
+ return null;
178
+ }
179
+ const turnId = observedTurnId;
180
+ if (turnId !== callTurnKey) {
181
+ callTurnKey = turnId;
182
+ callCount = 0;
183
+ conflictErrors.clear();
184
+ }
160
185
  callCount += 1;
161
186
  if (callCount <= maxCallsPerTurn) return null;
162
187
  log('tui.wakeup', 'loop-capped', { turnId, count: callCount, max: maxCallsPerTurn, action });
@@ -252,20 +277,35 @@ export function createWakeupScheduler(deps: WakeupSchedulerDeps): WakeupSchedule
252
277
  };
253
278
 
254
279
  return {
255
- schedule(req) {
280
+ schedule(req, requestKey) {
256
281
  const t = now();
257
282
  const reason = (req.reason ?? '').replace(/\s+/g, ' ').trim();
258
283
  const reject = (error: string): ScheduleWakeupResult => {
259
284
  log('tui.wakeup', 'rejected', { id: null, reason: 'invalid', error });
260
285
  return { ok: false, error };
261
286
  };
262
- const capped = loopCapError('schedule');
287
+ // Every schedule attempt consumes the per-turn budget before validation.
288
+ const turnId = readTurnId();
289
+ const capped = loopCapError('schedule', turnId);
263
290
  if (capped) return { ok: false, error: capped };
291
+ // Presence is the contract: invalidly typed `at` values from the host
292
+ // must still conflict with delaySeconds rather than silently disappear.
293
+ const hasAt = req.atProvided ?? req.at !== undefined;
294
+ const hasDelay = req.delaySeconds !== undefined;
295
+ if (hasAt && hasDelay) {
296
+ const key = requestKey ?? canonicalToolArgs(req as Record<string, unknown>);
297
+ if (turnId !== null) {
298
+ const previousError = conflictErrors.get(key);
299
+ if (previousError !== undefined) {
300
+ return { ok: false, error: `${previousError} — 같은 충돌 인자의 재시도는 억제했다` };
301
+ }
302
+ if (conflictErrors.size < maxCallsPerTurn) conflictErrors.set(key, formatWakeupTimeConflictError(req));
303
+ }
304
+ const error = formatWakeupTimeConflictError(req);
305
+ return reject(error);
306
+ }
264
307
  if (!reason) return reject('reason 이 비었다 — 깨어나서 무엇을 할지 한 줄로 적어라');
265
308
  if (entries.size >= maxEntries) return reject(`예약 상한 ${maxEntries}개 — list 로 보고 cancel 뒤 다시`);
266
- const hasAt = typeof req.at === 'string' && req.at.trim() !== '';
267
- const hasDelay = typeof req.delaySeconds === 'number';
268
- if (hasAt && hasDelay) return reject('at 과 delaySeconds 는 둘 중 하나만');
269
309
  let repeatMs: number | undefined;
270
310
  // ⭐ 0 = 일회성(생략과 같다) — 모델이 «한 번만»을 0 으로 부른다(라이브 실측). 음수·NaN·1 미만 소수는 거부.
271
311
  if (req.repeatMinutes !== undefined && req.repeatMinutes !== 0) {
@@ -276,7 +316,8 @@ export function createWakeupScheduler(deps: WakeupSchedulerDeps): WakeupSchedule
276
316
  }
277
317
  let dueAt: number;
278
318
  if (hasAt) {
279
- const resolved = resolveWakeupAt(req.at!, t);
319
+ if (typeof req.at !== 'string') return reject(`at 은 «HH:MM» 문자열이어야 한다 — 받은 값 ${JSON.stringify(req.at)}`);
320
+ const resolved = resolveWakeupAt(req.at, t);
280
321
  if (resolved === null) return reject(`at 은 «HH:MM»(24시간) 꼴 — 받은 값 ${JSON.stringify(req.at)}`);
281
322
  dueAt = resolved;
282
323
  } else if (hasDelay) {
@@ -342,7 +383,7 @@ export function buildScheduleWakeupHostTool(scheduler: WakeupScheduler): LLMTool
342
383
  name: SCHEDULE_WAKEUP_TOOL_NAME,
343
384
  description:
344
385
  'Wake THIS TUI later with an internal turn: when you would write «다음 점검 HH:MM» and end the turn, call this instead so the check actually happens. '
345
- + 'action=schedule (default) needs reason plus one of at ("HH:MM" local, past → tomorrow) / delaySeconds (≥60) / repeatMinutes (≥1; repeats expire after 7 days). '
386
+ + 'action=schedule (default) needs reason plus one of at ("HH:MM" local, past → tomorrow) / delaySeconds (≥60) / repeatMinutes (≥1; repeats expire after 7 days). Never provide both at and delaySeconds; the schema requires one timing variant. '
346
387
  + 'ONE-SHOT (wake once): give only delaySeconds or at and OMIT repeatMinutes (0 also means one-shot). Set repeatMinutes only when you really want it to repeat. '
347
388
  + `action=list shows pending wakeups; action=cancel needs id. Limits: ≥60s ahead, ≤7 days, at most 5 pending, at most ${WAKEUP_MAX_CALLS_PER_TURN} schedule/cancel calls per turn. `
348
389
  + 'If the TUI is busy or the human is typing at that time it retries once a minute later, then gives up (repeats move to the next tick). '
@@ -358,6 +399,11 @@ export function buildScheduleWakeupHostTool(scheduler: WakeupScheduler): LLMTool
358
399
  id: { type: 'string', description: 'Wakeup id for action=cancel (from schedule/list).' },
359
400
  },
360
401
  required: [],
402
+ oneOf: [
403
+ { not: { anyOf: [{ required: ['at'] }, { required: ['delaySeconds'] }] } },
404
+ { required: ['at'], not: { required: ['delaySeconds'] } },
405
+ { required: ['delaySeconds'], not: { required: ['at'] } },
406
+ ],
361
407
  },
362
408
  handler: async (args) => {
363
409
  const action = typeof args.action === 'string' ? args.action : 'schedule';
@@ -368,12 +414,15 @@ export function buildScheduleWakeupHostTool(scheduler: WakeupScheduler): LLMTool
368
414
  return r.ok ? { cancelled: id } : { error: r.error };
369
415
  }
370
416
  if (action !== 'schedule') return { error: `unknown action ${JSON.stringify(action)}` };
371
- const result = scheduler.schedule({
417
+ const atProvided = Object.prototype.hasOwnProperty.call(args, 'at');
418
+ const request: ScheduleWakeupRequest = {
372
419
  reason: typeof args.reason === 'string' ? args.reason : '',
373
- ...(typeof args.at === 'string' ? { at: args.at } : {}),
420
+ atProvided,
421
+ ...(atProvided ? { at: args.at } : {}),
374
422
  ...(typeof args.delaySeconds === 'number' ? { delaySeconds: args.delaySeconds } : {}),
375
423
  ...(typeof args.repeatMinutes === 'number' ? { repeatMinutes: args.repeatMinutes } : {}),
376
- });
424
+ };
425
+ const result = scheduler.schedule(request, canonicalToolArgs(args));
377
426
  return result.ok ? { scheduled: describeEntry(result.entry) } : { error: result.error };
378
427
  },
379
428
  };
@@ -15,16 +15,19 @@ export interface ReleaseDayDecision {
15
15
  reason?: string;
16
16
  }
17
17
 
18
- /** The release record, rather than publishAt (a planned time), opens green-back. */
18
+ /** Green-back waits for both the scheduled publish end and the actual publication record. */
19
19
  export function decideReleaseDayPhase(schedule: ReleaseSchedule, now: Date, publishedAt: string | null): ReleaseDayDecision {
20
20
  const cut = Date.parse(schedule.cutAt);
21
21
  const land = schedule.landBy ? Date.parse(schedule.landBy) : cut;
22
22
  const gate = cut - 30 * 60_000;
23
23
  const time = now.getTime();
24
+ const published = publishedAt ? Date.parse(publishedAt) : Number.NaN;
25
+ const publishEnd = schedule.publishAt ? Date.parse(schedule.publishAt) : published;
26
+ const greenAt = Number.isFinite(published) && Number.isFinite(publishEnd) ? Math.max(published, publishEnd) : Number.NaN;
24
27
  let phase: ReleaseDayPhase = 'none';
25
28
  let dueAt: string | null = null;
26
- if (publishedAt && time >= Date.parse(publishedAt)) {
27
- phase = 'green-back'; dueAt = publishedAt;
29
+ if (time >= greenAt) {
30
+ phase = 'green-back'; dueAt = publishEnd >= published ? schedule.publishAt ?? publishedAt : publishedAt;
28
31
  } else if (time >= cut) {
29
32
  phase = 'cut-run'; dueAt = schedule.cutAt;
30
33
  } else if (time >= land) {
@@ -133,6 +136,7 @@ export function runReleaseDayShadow(deps: ReleaseDayShadowDeps = {}): ReleaseDay
133
136
  continue;
134
137
  }
135
138
  const publishedAt = publication.kind === 'published' ? publication.at : null;
139
+ // The steward graph tick records this judgment only; release CLI actions remain outside this shadow boundary.
136
140
  const decision = decideReleaseDayPhase(schedule, now, publishedAt);
137
141
  let recorded = false;
138
142
  if (decision.phase !== 'none') {
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { closeSync, existsSync, openSync, readFileSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
2
+ import { closeSync, existsSync, openSync, readFileSync, writeFileSync, mkdirSync, renameSync, rmSync } from 'node:fs';
3
3
  import { launchModeOf, rescueAllows } from './rescue.js';
4
4
  import { join } from 'node:path';
5
5
  import { fetchLinearIssues } from '../connectors/linear.js';
@@ -328,13 +328,46 @@ function logStageFailure(root: string, stage: StewardStage, reason: string): voi
328
328
  }
329
329
  const SCHEDULE_CHECK_MS = 15 * 60_000;
330
330
 
331
+ /** Atomic marker write: stage the payload at `<marker>.tmp-<pid>`, then renameSync it into place so a
332
+ * crash mid-write never leaves a half-written marker for the next sync to trip over. */
333
+ export function writeScheduleCheckMarker(
334
+ marker: string,
335
+ at: Date,
336
+ write: (path: string, data: string) => void = writeFileSync,
337
+ ): void {
338
+ const tmp = `${marker}.tmp-${process.pid}`;
339
+ try {
340
+ write(tmp, JSON.stringify({ at: at.toISOString() }));
341
+ renameSync(tmp, marker);
342
+ } catch (error) {
343
+ try { rmSync(tmp, { force: true }); } catch { /* Preserve the write or rename error. */ }
344
+ throw error;
345
+ }
346
+ }
347
+
331
348
  /** Called by runStewardStage(sync) under its stage slot, never from the checker CLI. */
332
349
  async function checkStewardSchedules(root: string, settings: StewardSettings, deps: StewardDeps): Promise<void> {
333
350
  const now = (deps.now ?? (() => new Date()))();
334
351
  const marker = join(root, 'steward', 'schedule-check.json');
335
352
  let previous: { at?: string } = {};
336
- try { previous = JSON.parse(readFileSync(marker, 'utf8')) as typeof previous; }
337
- catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
353
+ try {
354
+ const parsed: unknown = JSON.parse(readFileSync(marker, 'utf8'));
355
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
356
+ && (!('at' in parsed) || typeof parsed.at === 'string')) {
357
+ previous = parsed as typeof previous;
358
+ } else {
359
+ debug.log('steward.schedule-check', 'marker-recovered', { reason: 'invalid-marker-shape' });
360
+ }
361
+ }
362
+ catch (error) {
363
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') { /* first run in this window — previous stays {} */ }
364
+ else if (error instanceof SyntaxError) {
365
+ // Corrupt marker bytes self-heal: previous stays {} so this check runs now and the fresh
366
+ // writeScheduleCheckMarker below replaces the broken file. The recovery is observed.
367
+ debug.log('steward.schedule-check', 'marker-recovered', { reason: redactSecretText(String(error)) });
368
+ }
369
+ else throw error;
370
+ }
338
371
  const elapsed = now.getTime() - Date.parse(previous.at ?? '');
339
372
  if (Number.isFinite(elapsed) && elapsed >= 0 && elapsed < SCHEDULE_CHECK_MS) return;
340
373
  const inventory = deps.scheduleInventory ?? (() => {
@@ -378,7 +411,7 @@ async function checkStewardSchedules(root: string, settings: StewardSettings, de
378
411
  debug.log('steward.schedule-check', 'routing', { ownerRequests, opEscalations, recovered });
379
412
  }
380
413
  debug.log('steward.schedule-check', 'checked', { count: checked.length, findings: findings.length, mode: settings.mode });
381
- writeFileSync(marker, JSON.stringify({ at: now.toISOString() }));
414
+ writeScheduleCheckMarker(marker, now);
382
415
  }
383
416
 
384
417
  function readState(path: string): { issues: Record<string, string>; digestDay?: string } {
@@ -0,0 +1,141 @@
1
+ export type HarvestInput = {
2
+ ask?: unknown;
3
+ context?: unknown;
4
+ prior?: unknown;
5
+ };
6
+
7
+ export type ReviewInvocation = {
8
+ stdout: string;
9
+ stderr?: string;
10
+ exitCode: number | null;
11
+ };
12
+
13
+ export type HarvestResult = {
14
+ outcome: 'done' | 'rework' | 'needs-human' | 'failed';
15
+ result: Record<string, unknown>;
16
+ evidence: Record<string, unknown>;
17
+ };
18
+
19
+ type ReviewRecord = Record<string, unknown> & {
20
+ pr?: string | number;
21
+ reviewed?: boolean;
22
+ verdict?: string | null;
23
+ mustFix?: unknown;
24
+ model?: string;
25
+ headCommit?: string;
26
+ currentHeadCommit?: string;
27
+ };
28
+
29
+ function object(value: unknown): value is Record<string, unknown> {
30
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
31
+ }
32
+
33
+ function expectedHead(input: HarvestInput): string | undefined {
34
+ if (object(input.context) && typeof input.context.expectedHead === 'string' && input.context.expectedHead.trim()) return input.context.expectedHead.trim();
35
+ return undefined;
36
+ }
37
+
38
+ function normalizedPr(value: unknown): string | undefined {
39
+ const raw = typeof value === 'number' && Number.isSafeInteger(value) ? String(value) : typeof value === 'string' ? value.trim() : '';
40
+ const normalized = raw.replace(/^#/, '');
41
+ return /^\d+$/.test(normalized) ? normalized : undefined;
42
+ }
43
+
44
+ function previousAttempts(input: HarvestInput): number {
45
+ if (!object(input.prior)) return 0;
46
+ const result = object(input.prior.result) ? input.prior.result : input.prior;
47
+ const attempts = result.attempts;
48
+ return Number.isSafeInteger(attempts) && (attempts as number) >= 0 ? attempts as number : 0;
49
+ }
50
+
51
+ function parseReview(stdout: string): ReviewRecord | undefined {
52
+ try {
53
+ const parsed: unknown = JSON.parse(stdout.trim());
54
+ if (Array.isArray(parsed)) {
55
+ if (parsed.length !== 1) return undefined;
56
+ return object(parsed[0]) ? parsed[0] as ReviewRecord : undefined;
57
+ }
58
+ return object(parsed) ? parsed as ReviewRecord : undefined;
59
+ } catch {
60
+ return undefined;
61
+ }
62
+ }
63
+
64
+ export async function runHarvestUnit(
65
+ input: HarvestInput,
66
+ invokeReview: (args: { pr: string; intent: string }) => Promise<ReviewInvocation>,
67
+ ): Promise<HarvestResult> {
68
+ const attempts = previousAttempts(input) + 1;
69
+ const prValue = object(input.context) ? input.context.pr : undefined;
70
+ const pr = normalizedPr(prValue);
71
+ if (!pr) {
72
+ return { outcome: 'failed', result: { attempts, error: 'context.pr must identify one pull request' }, evidence: { pr: pr || null, attempts } };
73
+ }
74
+
75
+ const context = object(input.context) ? input.context : {};
76
+ const hasContextIntent = Object.prototype.hasOwnProperty.call(context, 'reviewIntent');
77
+ const intentValue = context.reviewIntent;
78
+ const intent = hasContextIntent
79
+ ? typeof intentValue === 'string' ? intentValue.trim() : ''
80
+ : typeof input.ask === 'string' ? input.ask.trim() : '';
81
+ if (!intent) {
82
+ return { outcome: 'failed', result: { attempts, error: hasContextIntent ? 'context.reviewIntent must be a non-empty string' : 'context.reviewIntent or ask is required' }, evidence: { pr, attempts } };
83
+ }
84
+ const expected = expectedHead(input);
85
+ if (!expected || !/^[0-9a-f]{40}$/i.test(expected)) {
86
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'expected PR head is required' }, evidence: { pr, attempts, expectedHead: expected ?? null } };
87
+ }
88
+
89
+ let invocation: ReviewInvocation;
90
+ try {
91
+ invocation = await invokeReview({ pr: pr.replace(/^#/, ''), intent });
92
+ } catch (error) {
93
+ const reason = error instanceof Error ? error.message : String(error);
94
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review could not be executed' }, evidence: { pr, attempts, error: reason } };
95
+ }
96
+
97
+ const review = parseReview(invocation.stdout);
98
+ if (!review || review.reviewed !== true || typeof review.headCommit !== 'string' || typeof review.currentHeadCommit !== 'string') {
99
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review result is missing or incomplete' }, evidence: {
100
+ pr, attempts, exitCode: invocation.exitCode, stderr: invocation.stderr ?? '', stdout: invocation.stdout.slice(0, 4000),
101
+ } };
102
+ }
103
+ if (normalizedPr(review.pr) !== pr) {
104
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review result belongs to a different pull request' }, evidence: {
105
+ pr, attempts, reviewedPr: review.pr ?? null, expectedHead: expected,
106
+ } };
107
+ }
108
+ if (invocation.exitCode !== 0) {
109
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review command exited unsuccessfully' }, evidence: {
110
+ pr, attempts, exitCode: invocation.exitCode, stderr: invocation.stderr ?? '',
111
+ } };
112
+ }
113
+ if (review.headCommit !== review.currentHeadCommit || (expected !== undefined && review.headCommit !== expected)) {
114
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review head is stale or differs from expected head' }, evidence: {
115
+ pr, attempts, expectedHead: expected ?? null, reviewedHead: review.headCommit, currentHead: review.currentHeadCommit,
116
+ } };
117
+ }
118
+ if (!['pass', 'warn', 'fail'].includes(review.verdict ?? '')) {
119
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review verdict is missing or invalid' }, evidence: {
120
+ pr, attempts, verdict: review.verdict ?? null, headCommit: review.headCommit,
121
+ } };
122
+ }
123
+ if (!Array.isArray(review.mustFix) || !review.mustFix.every(item => typeof item === 'string' && item.trim().length > 0)) {
124
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review mustFix field is invalid' }, evidence: { pr, attempts, headCommit: review.headCommit } };
125
+ }
126
+
127
+ const mustFix = review.mustFix as string[];
128
+ if ((review.verdict === 'fail' && mustFix.length === 0)
129
+ || ((review.verdict === 'pass' || review.verdict === 'warn') && mustFix.length > 0)) {
130
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review verdict conflicts with mustFix findings' }, evidence: {
131
+ pr, attempts, verdict: review.verdict, mustFix, headCommit: review.headCommit,
132
+ } };
133
+ }
134
+ const evidence = {
135
+ pr, headCommit: review.headCommit, attempts, model: review.model ?? null, verdict: review.verdict ?? null,
136
+ reviewResultsJson: true, exitCode: invocation.exitCode,
137
+ };
138
+ return mustFix.length > 0
139
+ ? { outcome: 'rework', result: { pr, headCommit: review.headCommit, attempts, mustFix }, evidence }
140
+ : { outcome: 'done', result: { pr, headCommit: review.headCommit, attempts, mustFix: [] }, evidence };
141
+ }