elanous 0.2.31 → 0.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (715) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
  5. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
  8. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
  9. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
  13. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
  15. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
  16. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
  19. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
  30. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
  31. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
  37. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
  39. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
  41. package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
  44. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
  45. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
  46. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
  47. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
  48. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
  51. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
  63. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
  76. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
  80. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
  87. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
  91. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
  94. package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
  97. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
  114. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
  116. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
  117. package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
  123. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-0a07363b130182a1.js → page-398c0faa173203f7.js} +1 -1
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +9 -2
  279. package/docs/goal-context/README.md +1 -0
  280. package/graphs/default-loop.yaml +20 -3
  281. package/graphs/document-loop.yaml +21 -2
  282. package/graphs/implement-loop.yaml +11 -0
  283. package/graphs/journey/SCENARIOS.md +33 -0
  284. package/graphs/journey/recipes.yaml +1 -0
  285. package/graphs/journey/ta-journey.yaml +84 -0
  286. package/graphs/journey/units/author/author.yaml +20 -0
  287. package/graphs/journey/units/author/recipes.yaml +2 -0
  288. package/graphs/journey/units/green/green.yaml +20 -0
  289. package/graphs/journey/units/green/recipes.yaml +2 -0
  290. package/graphs/journey/units/pr/pr.yaml +20 -0
  291. package/graphs/journey/units/pr/recipes.yaml +2 -0
  292. package/graphs/journey/units/remember/recipes.yaml +2 -0
  293. package/graphs/journey/units/remember/remember.yaml +20 -0
  294. package/graphs/operate-loop.yaml +21 -2
  295. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  296. package/graphs/release-rehearsal/recipes.yaml +1 -1
  297. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  298. package/graphs/research-loop.yaml +23 -2
  299. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  300. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  301. package/graphs/units/entry/entry.yaml +50 -0
  302. package/graphs/units/entry/recipes.yaml +14 -0
  303. package/graphs/units/harvest/harvest.yaml +25 -0
  304. package/graphs/units/harvest/recipes.yaml +4 -0
  305. package/graphs/units/land/land.yaml +45 -0
  306. package/graphs/units/land/recipes.yaml +3 -0
  307. package/graphs/units/recipes.yaml +7 -0
  308. package/graphs/units/recover.yaml +39 -0
  309. package/graphs/units/reflect/recipes.yaml +3 -0
  310. package/graphs/units/reflect/reflect.yaml +15 -0
  311. package/graphs/units/task-agent-recover-review.yaml +17 -0
  312. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  313. package/graphs/units/verbs/make-doc.yaml +34 -0
  314. package/graphs/units/verbs/recipes.yaml +33 -0
  315. package/graphs/units/verbs/verify.yaml +55 -0
  316. package/graphs/work/recipes.yaml +2 -0
  317. package/graphs/work/research-report.yaml +28 -0
  318. package/package.json +1 -1
  319. package/scripts/ci-typecheck-changed.ts +95 -17
  320. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  321. package/scripts/graph-harvest-unit.ts +22 -0
  322. package/scripts/graph-units/journey-stub.ts +6 -0
  323. package/scripts/graph-units/land-enqueue.ts +78 -0
  324. package/scripts/graph-units/recover-plan.ts +15 -0
  325. package/scripts/graph-units/reflect-node.ts +88 -0
  326. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  327. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  328. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  329. package/scripts/graph-units/verbs-envelope.ts +139 -0
  330. package/scripts/hq/standby-snapshot.ts +25 -0
  331. package/scripts/measure-si-task-cpu.ts +143 -0
  332. package/scripts/public-export.ts +43 -1
  333. package/scripts/ratchets/test-interference-patterns.allowlist.txt +0 -2
  334. package/scripts/ratchets/train-side-invariants.sh +45 -0
  335. package/scripts/release-loop/auto-approve-node.ts +30 -16
  336. package/scripts/release-loop/gate-closure.ts +5 -1
  337. package/scripts/release-loop/gate-diff.ts +1 -1
  338. package/scripts/release-loop/gate-node.ts +498 -31
  339. package/scripts/release-loop/gate-partial.ts +3 -3
  340. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  341. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  342. package/scripts/release-loop/gate-triage-node.ts +5 -2
  343. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  344. package/scripts/release-loop/known-issues-node.ts +77 -8
  345. package/scripts/release-loop/preflight.ts +93 -7
  346. package/scripts/release-loop/prepare-node.ts +102 -4
  347. package/scripts/release-loop/publish-node.ts +60 -9
  348. package/scripts/release-loop/resume-cap.ts +56 -0
  349. package/scripts/release-loop/resume-release.ts +114 -15
  350. package/scripts/release-loop/resume.ts +24 -1
  351. package/scripts/release-loop/tui-sim-node.ts +8 -2
  352. package/scripts/release-loop/unattended-release.ts +8 -2
  353. package/src/acp/core-turn-bridge.ts +36 -9
  354. package/src/acp/elanous-extensions.ts +3 -0
  355. package/src/acp/reasoning-thought-buffer.ts +45 -0
  356. package/src/acp/server.ts +3 -0
  357. package/src/acp/tool-trace.ts +186 -11
  358. package/src/agent/self-ambient-cache.ts +156 -0
  359. package/src/agent/self-ambient.ts +8 -1
  360. package/src/agent/task-notification.ts +5 -0
  361. package/src/agent-substrate/acp-reviewer.ts +52 -12
  362. package/src/agent-substrate/pr-reviewer.ts +3 -1
  363. package/src/agent-substrate/review-finding-key.ts +53 -0
  364. package/src/agent-substrate/self-review-cli.ts +126 -5
  365. package/src/ask-user-question/pending-questions.ts +1 -1
  366. package/src/ask-user-question/tool.ts +22 -0
  367. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  368. package/src/autopilot/pr-manager.ts +213 -46
  369. package/src/capture/frame-state-detect.ts +39 -0
  370. package/src/capture/tui-self-report.ts +134 -6
  371. package/src/chat/index.ts +61 -15
  372. package/src/chat/pickers/modal-runtime.ts +6 -0
  373. package/src/chat/pickers/modals.ts +8 -2
  374. package/src/chat/tool-render/dispatch.ts +62 -10
  375. package/src/cli/ask-bare.ts +1 -0
  376. package/src/cli/control-cli.ts +24 -7
  377. package/src/cli/guardian-cli.ts +10 -0
  378. package/src/cli/import-cli.ts +12 -0
  379. package/src/cli/light-entry-route.ts +35 -0
  380. package/src/cli/llm-detect-cli.ts +23 -1
  381. package/src/cli/log-event-names.ts +10 -0
  382. package/src/cli/msg-cli.ts +1 -0
  383. package/src/cli/pod-cli.ts +14 -3
  384. package/src/cli/pr-cli.ts +140 -41
  385. package/src/cli/pr-land-base-read.ts +36 -0
  386. package/src/cli/pr-land-heavy-remote.ts +81 -25
  387. package/src/cli/pr-land-overlap-evidence.ts +200 -18
  388. package/src/cli/pr-land-pod-shadow-job.ts +26 -3
  389. package/src/cli/pr-land-recovery.ts +64 -0
  390. package/src/cli/pr-land-refusal.ts +20 -5
  391. package/src/cli/pty-takeover-cli.ts +94 -19
  392. package/src/cli/release-cli.ts +120 -33
  393. package/src/cli/release-run-if-ready.ts +29 -28
  394. package/src/cli/release-single-flight.ts +178 -0
  395. package/src/cli/seat-cli.ts +37 -0
  396. package/src/cli/setup-cli.ts +40 -1
  397. package/src/cli/sim-cli.ts +18 -0
  398. package/src/cli/tasks-cli.ts +149 -5
  399. package/src/context-bus/ops-events.ts +6 -2
  400. package/src/control/control-status.ts +8 -3
  401. package/src/control-plane/ledger.ts +5 -3
  402. package/src/control-plane/server.ts +5 -3
  403. package/src/core-turn/run-core-turn.ts +1 -0
  404. package/src/core-turn/run-goal-loop.ts +21 -0
  405. package/src/core-turn/short-question.ts +5 -1
  406. package/src/core-turn/types.ts +3 -0
  407. package/src/dashboard/acp-active-model.ts +42 -1
  408. package/src/dashboard/background-jobs-status.ts +66 -0
  409. package/src/dashboard/index.ts +153 -111
  410. package/src/dashboard/input/agent-wake.ts +242 -0
  411. package/src/dashboard/input/chat-main-entry-runtime.ts +5 -0
  412. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  413. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  414. package/src/dashboard/input/external-input-host.ts +23 -9
  415. package/src/dashboard/input/mouse-wiring.ts +108 -11
  416. package/src/dashboard/input/seat-autowake.ts +56 -3
  417. package/src/dashboard/log-click-runtime.ts +118 -2
  418. package/src/dashboard/seat-boot-preamble.ts +1 -1
  419. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  420. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  421. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  422. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  423. package/src/dashboard/turn-preamble.ts +163 -41
  424. package/src/dashboard/turn-session-layers.ts +4 -2
  425. package/src/dashboard/turn-start-segments.ts +222 -0
  426. package/src/dashboard/turn-stream-formatter.ts +34 -1
  427. package/src/dashboard/turn-stream-runtime.ts +2 -0
  428. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  429. package/src/display/prompt-row-owner.ts +146 -0
  430. package/src/display/resize-listener.ts +33 -2
  431. package/src/domains/guardian-tick.ts +54 -2
  432. package/src/domains/outbound-alert.ts +3 -2
  433. package/src/extractors.ts +3 -1
  434. package/src/fold-stack.ts +4 -2
  435. package/src/git-fs/index.ts +263 -36
  436. package/src/git-fs/retry.ts +4 -0
  437. package/src/git-fs/runner.ts +2 -0
  438. package/src/graph-runner/runner.ts +114 -44
  439. package/src/grok/credential.ts +5 -0
  440. package/src/harness/gate-reserve.ts +87 -0
  441. package/src/harness/harness-cli-command.ts +39 -10
  442. package/src/harness/harness-incidents.ts +17 -0
  443. package/src/harness/harness-pod-dispatch.ts +38 -1
  444. package/src/harness/harness-queue.ts +15 -0
  445. package/src/harness/harness-salvage-cli.ts +14 -2
  446. package/src/index.ts +198 -12
  447. package/src/input/external-input-queue.ts +34 -9
  448. package/src/intake-plane/already-built-hint.ts +89 -0
  449. package/src/knowhow/pack.ts +199 -0
  450. package/src/light-cli.ts +95 -0
  451. package/src/llm/route-decision.ts +36 -0
  452. package/src/llm/tool-loop-steered-rejection.ts +8 -0
  453. package/src/llm-request-shape.ts +209 -0
  454. package/src/llm.ts +221 -276
  455. package/src/loops/budget.ts +95 -0
  456. package/src/loops/msg-wake.ts +8 -2
  457. package/src/loops/orchestrator/tick.ts +24 -2
  458. package/src/loops/orchestrator/traffic.ts +132 -1
  459. package/src/maturity/feature-maturity.ts +1 -1
  460. package/src/mss/logging/log-store.ts +4 -5
  461. package/src/mss/logging/render-categories.ts +5 -0
  462. package/src/nexus/api/graphs-api.ts +22 -3
  463. package/src/nexus/api/http-server.ts +1 -1
  464. package/src/nexus/api/ops-api.ts +12 -0
  465. package/src/oauth/claude-pty-maturity.ts +66 -0
  466. package/src/oauth/codex-access-mirror.ts +55 -0
  467. package/src/oauth/fallback-chain.ts +1 -1
  468. package/src/onboarding/first-run.ts +5 -3
  469. package/src/onboarding/non-interactive.ts +64 -13
  470. package/src/onboarding.ts +10 -2
  471. package/src/ops/overview-collect.ts +36 -1
  472. package/src/ops/overview.ts +70 -2
  473. package/src/pr-tool/census.ts +41 -8
  474. package/src/pr-tool/inflight-registry.ts +296 -0
  475. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  476. package/src/pty-shell/herdr-agent-report.ts +442 -0
  477. package/src/pty-shell/pty-control-ipc.ts +5 -5
  478. package/src/pty-shell/pty-manifest.ts +12 -3
  479. package/src/pty-shell/pty-write-outcome.ts +24 -6
  480. package/src/pty-shell/tui-run-state.ts +151 -6
  481. package/src/release-loop/checklist.ts +79 -5
  482. package/src/release-loop/feature-store.ts +19 -2
  483. package/src/release-loop/placement.ts +10 -3
  484. package/src/release-loop/rehearsal.ts +205 -25
  485. package/src/release-loop/rubric.ts +16 -2
  486. package/src/seat-loop/traffic-signal.ts +2 -1
  487. package/src/self-dev/ask-launch-flow.ts +13 -0
  488. package/src/self-dev/draft-residue.ts +243 -24
  489. package/src/self-dev/draft-sweep.ts +52 -3
  490. package/src/self-dev/graph-journey-nodes.ts +10 -6
  491. package/src/self-dev/graph-journey-route.ts +60 -6
  492. package/src/self-dev/orchestrate.ts +79 -3
  493. package/src/self-dev/run-supervisor.ts +107 -12
  494. package/src/self-dev/run-types.ts +5 -1
  495. package/src/self-dev/shard-plan.ts +11 -3
  496. package/src/self-dev/shard-run.ts +103 -10
  497. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  498. package/src/self-implement/follow-up-placement.ts +79 -0
  499. package/src/self-implement/gate-artifacts.ts +15 -4
  500. package/src/self-implement/gate-baseline.ts +145 -10
  501. package/src/self-implement/gate-cli.ts +7 -2
  502. package/src/self-implement/gate-remote.ts +35 -6
  503. package/src/self-implement/goal-author-identity.ts +66 -0
  504. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  505. package/src/self-implement/goal-author.ts +4 -120
  506. package/src/self-implement/graph-overlay-yaml.ts +17 -2
  507. package/src/self-implement/graph-unit-flatten.ts +103 -0
  508. package/src/self-implement/graph-unit-resolver.ts +107 -0
  509. package/src/self-implement/graph-yaml.ts +151 -1
  510. package/src/self-implement/headless-elanous-driver.ts +1 -0
  511. package/src/self-implement/host-regate.ts +36 -4
  512. package/src/self-implement/knowhow-pack.ts +103 -0
  513. package/src/self-implement/orchestrator.ts +109 -11
  514. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  515. package/src/self-implement/review-mustfix-class.ts +203 -0
  516. package/src/self-implement/run-ledger.ts +16 -14
  517. package/src/self-implement/run-stop.ts +8 -2
  518. package/src/self-implement/seams.ts +32 -1
  519. package/src/self-implement/stop-autoheal.ts +25 -1
  520. package/src/session/chat.ts +27 -0
  521. package/src/session-runtime/index.ts +22 -267
  522. package/src/session-runtime/retry-policy.ts +2 -1
  523. package/src/shell-runner/background-surface.ts +15 -5
  524. package/src/skills/tools/agent.ts +39 -6
  525. package/src/skills/tools/list-dir.ts +11 -0
  526. package/src/skills/tools/schedule-wakeup.ts +457 -0
  527. package/src/skills/tools/shell.ts +245 -3
  528. package/src/status/bar.ts +26 -0
  529. package/src/steward/digest-delivery.ts +118 -0
  530. package/src/steward/hold-hygiene.ts +120 -0
  531. package/src/steward/release-day.ts +7 -3
  532. package/src/steward/triage.ts +47 -4
  533. package/src/surface/shell-runner-boot.ts +5 -2
  534. package/src/task-agent/harvest-unit.ts +141 -0
  535. package/src/task-agent/live-moves.ts +98 -12
  536. package/src/task-agent/parent-host.ts +93 -3
  537. package/src/task-agent/postland-card.ts +80 -1
  538. package/src/task-agent/rejudge-on-head.ts +112 -26
  539. package/src/task-agent/repair-branch-cas.ts +4 -1
  540. package/src/task-agent/repair-cycle.ts +16 -3
  541. package/src/task-agent/run-identity.ts +4 -3
  542. package/src/task-agent/shadow.ts +12 -2
  543. package/src/task-agent/task-hand.ts +76 -5
  544. package/src/task-agent/work-order-build.ts +22 -0
  545. package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
  546. package/src/task-orchestrator/surfaces/pod-command-job.ts +67 -12
  547. package/src/task-orchestrator/surfaces/pod-lease.ts +98 -0
  548. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  549. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  550. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -18
  551. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +10 -6
  552. package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
  553. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +548 -0
  554. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
  555. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  556. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +158 -3
  557. package/src/task-orchestrator/surfaces/self-implement-pod.ts +230 -43
  558. package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
  559. package/src/tool-runtime/truncation-store.ts +4 -0
  560. package/src/tui/chat/execution-badge.ts +5 -1
  561. package/src/tui/input-lag-probe.ts +230 -0
  562. package/src/tui-client/dashboard-session.ts +10 -1
  563. package/src/tui.ts +4 -0
  564. package/src/user-config/coercion.ts +36 -0
  565. package/src/user-config.ts +18 -41
  566. package/src/ux-sim/scenario.ts +314 -0
  567. package/src/version/packed-revision.json +1 -1
  568. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  571. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  572. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  573. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  577. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  579. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  580. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  587. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  588. package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
  591. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  595. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  599. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  600. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  602. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  605. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  612. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  619. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  620. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  622. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  627. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  628. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  635. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2ebb8fd59b9461f9.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  706. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  713. package/apps/pwa/out/_next/static/css/3f5fc6f96e2cf7b2.css +0 -1
  714. package/src/cli/g6a-registration-probe.ts +0 -16
  715. /package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
@@ -1,7 +1,8 @@
1
1
  import { debug } from '../debug/log.js';
2
2
  import { GRAPH_SPECS } from '../self-implement/graph-templates.js';
3
3
  import { applyGraphOverlays, defaultOverlaysDir, loadGraphOverlays, selectOverlays, type GraphOverlaySpec } from '../self-implement/graph-overlay-yaml.js';
4
- import type { GraphTemplateSpec } from '../self-implement/graph-yaml.js';
4
+ import { L1_PROTECTED_ROUTE_NODES, type GraphTemplateSpec } from '../self-implement/graph-yaml.js';
5
+ import { evaluateOverlayCondition } from '../self-implement/graph-overlay-condition.js';
5
6
  import { journeyJoinFields } from './graph-journey-nodes.js';
6
7
 
7
8
  /** ⭐ HARNESS-FULL-GRAPH 2판 — 「다음 노드」를 코드가 아니라 «그래프»가 정한다.
@@ -21,6 +22,13 @@ export interface JourneyRoute {
21
22
  readonly to: string | null;
22
23
  readonly source: 'graph' | 'code-default';
23
24
  readonly overlays: readonly string[];
25
+ readonly via?: 'outcome' | 'when';
26
+ readonly condition?: string;
27
+ readonly ambiguousConditions?: readonly string[];
28
+ readonly unobservedConditions?: readonly string[];
29
+ readonly skippedNode?: string;
30
+ readonly skipCondition?: string;
31
+ readonly skippedNodes?: readonly { readonly node: string; readonly condition: string }[];
24
32
  }
25
33
 
26
34
  /** ⛔ 캐시하지 않는다 — 여러 런을 처리하는 프로세스(데몬·대기열 tick)가 다음 발사에서 오버레이 변경을 봐야 한다.
@@ -65,12 +73,46 @@ export function readJourneyEdge(
65
73
  ): JourneyRoute {
66
74
  const { spec, applied } = journeySpec(state, deps.base ?? GRAPH_SPECS['self-implement'], deps.overlays ?? launchOverlays());
67
75
  let route: JourneyRoute = { from, on: null, label, to: null, source: 'code-default', overlays: applied };
68
- for (const edge of spec?.edges ?? []) {
69
- if (edge.from !== from) continue;
70
- if (edge.map !== undefined && Object.hasOwn(edge.map, label)) {
71
- route = { from, on: edge.on ?? null, label, to: edge.map[label]!, source: 'graph', overlays: applied };
72
- break;
76
+ const outgoing = (spec?.edges ?? []).filter(edge => edge.from === from);
77
+ const protectedFrom = L1_PROTECTED_ROUTE_NODES.has(from) || spec?.nodes.some(node => node.nodeId === from && node.kind === 'gate') ||
78
+ spec?.terminalNodes.includes(from);
79
+ const conditions = outgoing.filter(edge => edge.when !== undefined && !protectedFrom).map(edge => ({ edge, verdict: evaluateOverlayCondition(edge.when, state) }));
80
+ const matching = conditions.filter(({ verdict }) => verdict.kind === 'applies').map(({ edge }) => edge);
81
+ const unobservedConditions = conditions.filter(({ verdict }) => verdict.kind === 'key-absent').map(({ edge }) => edge.when!);
82
+ if (matching.length === 1 && unobservedConditions.length === 0 && matching[0]!.to !== undefined) {
83
+ route = { from, on: null, label, to: matching[0]!.to!, source: 'graph', overlays: applied,
84
+ via: 'when', condition: matching[0]!.when };
85
+ } else {
86
+ const mapped = outgoing.find(edge => edge.when === undefined && edge.map !== undefined && Object.hasOwn(edge.map, label));
87
+ const defaultEdge = mapped ?? outgoing.find(edge => edge.when === undefined && edge.to !== undefined);
88
+ if (defaultEdge?.map !== undefined) route = { from, on: defaultEdge.on ?? null, label,
89
+ to: defaultEdge.map[label]!, source: 'graph', overlays: applied, via: 'outcome' };
90
+ else if (defaultEdge?.to !== undefined) route = { from, on: null, label,
91
+ to: defaultEdge.to, source: 'graph', overlays: applied, via: 'outcome' };
92
+ if (matching.length > 1) route = { ...route, ambiguousConditions: matching.map(edge => edge.when!) };
93
+ if (unobservedConditions.length > 0) route = { ...route, unobservedConditions };
94
+ }
95
+ // A skipped optional node needs one unambiguous unconditional successor. Otherwise retain
96
+ // the ordinary route; neither a missing observation nor a branching node is a skip proof.
97
+ if (route.to && spec) {
98
+ const skipped: { node: string; condition: string }[] = [];
99
+ const visited = new Set<string>();
100
+ while (route.to && !visited.has(route.to)) {
101
+ visited.add(route.to);
102
+ const next = spec.nodes.find(node => node.nodeId === route.to);
103
+ if (!next?.skipWhen || next.kind === 'gate' ||
104
+ L1_PROTECTED_ROUTE_NODES.has(next.nodeId) ||
105
+ spec.terminalNodes.includes(next.nodeId) ||
106
+ evaluateOverlayCondition(next.skipWhen, state).kind !== 'applies') break;
107
+ const successors = spec.edges.filter(edge => edge.from === next.nodeId);
108
+ if (successors.length !== 1 || successors[0]?.to === undefined ||
109
+ successors[0]?.when !== undefined || (successors[0]?.fallback?.length ?? 0) > 0 ||
110
+ visited.has(successors[0].to)) break;
111
+ skipped.push({ node: next.nodeId, condition: next.skipWhen });
112
+ route = { ...route, to: successors[0]!.to! };
73
113
  }
114
+ if (skipped.length > 0) route = { ...route, skippedNode: skipped[0]!.node,
115
+ skipCondition: skipped[0]!.condition, skippedNodes: skipped };
74
116
  }
75
117
  return route;
76
118
  }
@@ -78,6 +120,18 @@ export function readJourneyEdge(
78
120
  /** 실제로 탄 간선을 남긴다 — `taken` 은 실제 다음 노드(그래프 답과 다르면 `honored: false` · 그 이유를 `reason` 에). */
79
121
  export function recordJourneyEdge(route: JourneyRoute, taken: string, reason?: string): void {
80
122
  try {
123
+ if (route.ambiguousConditions?.length) debug.log('self-implement', 'edge-ambiguous', {
124
+ graphId: 'self-implement', from: route.from, conditions: route.ambiguousConditions,
125
+ fallback: taken, ...journeyJoinFields(),
126
+ });
127
+ if (route.unobservedConditions?.length) debug.log('self-implement', 'edge-unobserved', {
128
+ graphId: 'self-implement', from: route.from, conditions: route.unobservedConditions,
129
+ fallback: taken, ...journeyJoinFields(),
130
+ });
131
+ if (route.to === taken) for (const skipped of route.skippedNodes ?? []) debug.log('self-implement', 'node-skipped', {
132
+ graphId: 'self-implement', node: skipped.node, reason: 'condition', condition: skipped.condition,
133
+ ...journeyJoinFields(),
134
+ });
81
135
  debug.log('self-implement', 'graph-edge-taken', {
82
136
  graphId: 'self-implement', ...route, taken, honored: route.to === null || route.to === taken,
83
137
  ...(reason === undefined ? {} : { reason }), ...journeyJoinFields(),
@@ -29,7 +29,7 @@ import { availableParallelism, cpus } from 'node:os';
29
29
  import { selfDevRunsDir } from './run-store.js';
30
30
  import { HARNESS_RUN_ID_ENV, normalizeRunId } from '../harness/harness-space.js';
31
31
  import { plannedSelfImplBranch } from '../harness/worktree-branch-prefix.js';
32
- import { parseGoalId } from '../self-implement/goal-author.js';
32
+ import { inspectGoalDoneBoundary, parseGoalId } from '../self-implement/goal-author.js';
33
33
  import { isTransientExecutionFailure } from './execution-transient.js';
34
34
  import type { AbandonedClassification } from '../self-implement/abandoned-classification.js';
35
35
  import type { JobKind, SelfDevGoal, SelfDevJobResult } from './run-types.js';
@@ -204,7 +204,7 @@ interface SelfDevTerminalOutcome {
204
204
  stage: string | null;
205
205
  merged: boolean | null;
206
206
  prUrl: string | null;
207
- blockReason?: 'parent-unlanded';
207
+ blockReason?: 'parent-unlanded' | 'dependency-needs-human';
208
208
  parentPrNumber?: number | null;
209
209
  parentNoPr?: true;
210
210
  }
@@ -493,6 +493,7 @@ export function classifyFailure(
493
493
  preflightWarning: PreflightWarningObservation = 'unknown',
494
494
  ): FailureKind | null {
495
495
  if (result.blockReason === 'parent-unlanded') return 'parent-unlanded';
496
+ if (result.blockReason === 'dependency-needs-human' || result.error?.code === 'GOAL_DONE_BOUNDARY_MISSING') return 'awaiting-human';
496
497
  const ledgerKind = result.failureClassification === undefined
497
498
  ? undefined
498
499
  : result.failureClassification === 'run-deadline-exceeded'
@@ -767,6 +768,8 @@ export function resolveOrchestrateConcurrency(
767
768
 
768
769
  export interface OrchestrateSelfDevOptions {
769
770
  goals: SelfDevGoal[];
771
+ /** TA 카드 출처. 생략하면 발사 환경의 ELANOUS_TASK_CARD_ID를 읽는다. */
772
+ taskCardId?: string;
770
773
  /** Original composite request. Multi-shard runs carry it to each child; omitted
771
774
  * keeps legacy callers and non-decomposed goal lists byte-for-byte unchanged. */
772
775
  parentRequest?: string;
@@ -947,6 +950,77 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
947
950
  const now = opts.now ?? Date.now;
948
951
  const runId = opts.runId ?? process.env[HARNESS_RUN_ID_ENV];
949
952
  if (runId && runId !== normalizeRunId(runId)) throw new Error(`invalid self-dev run ID: ${runId}`);
953
+ const taskCardId = opts.taskCardId ?? process.env.ELANOUS_TASK_CARD_ID;
954
+ const boundaryResults: SelfDevJobResult[] = [];
955
+ if (taskCardId?.trim()) {
956
+ const parentBoundary = inspectGoalDoneBoundary(opts.parentRequest ?? '');
957
+ const inherited: Array<{ index: number; labels: string[] }> = [];
958
+ opts = { ...opts, goals: opts.goals.map((goal, index) => {
959
+ if (goal.kind && goal.kind !== 'dev') return goal;
960
+ const missing = inspectGoalDoneBoundary(goal.feature).missing;
961
+ const lines = missing.flatMap((label) => parentBoundary.values[label] ? [`- ${label}: ${parentBoundary.values[label]}`] : []);
962
+ if (lines.length === 0) return goal;
963
+ inherited.push({ index: index + 1, labels: missing.filter((label) => parentBoundary.values[label]) });
964
+ return { ...goal, feature: `${goal.feature.trimEnd()}\n${lines.join('\n')}` };
965
+ }) };
966
+ if (inherited.length > 0) {
967
+ try { debug.log('self-dev.orchestrate', 'done-boundary-inherited', { taskCardId, inherited }); } catch { /* fail-soft */ }
968
+ }
969
+ const boundaryMissing = opts.goals.flatMap((goal, index) => {
970
+ if (goal.kind && goal.kind !== 'dev') return [];
971
+ const boundary = inspectGoalDoneBoundary(goal.feature);
972
+ return boundary.missing.length ? [{ index: index + 1, goal: goal.id ?? goal.feature.split(/\r?\n/, 1)[0]?.slice(0, 80) ?? '', missing: boundary.missing }] : [];
973
+ });
974
+ if (boundaryMissing.length > 0) {
975
+ const blockedGoalIndexes = new Set<number>(boundaryMissing.map(({ index }) => index - 1));
976
+ const blockedByBoundaryId = new Set(boundaryMissing.map(({ index }) => {
977
+ const goal = opts.goals[index - 1]!;
978
+ return goal.id ?? String(index - 1);
979
+ }));
980
+ const blockedDependents = new Map<number, string>();
981
+ let changed = true;
982
+ while (changed) {
983
+ changed = false;
984
+ opts.goals.forEach((goal, index) => {
985
+ if (blockedDependents.has(index)) return;
986
+ const goalId = goal.id ?? String(index);
987
+ const predecessor = (goal.dependsOn ?? []).find((id) => id !== goalId && blockedByBoundaryId.has(id));
988
+ if (!predecessor) return;
989
+ blockedGoalIndexes.add(index);
990
+ blockedByBoundaryId.add(goalId);
991
+ blockedDependents.set(index, predecessor);
992
+ changed = true;
993
+ });
994
+ }
995
+ for (const item of boundaryMissing.filter(({ index }) => !blockedDependents.has(index - 1))) {
996
+ const goal = opts.goals[item.index - 1]!;
997
+ boundaryResults.push({
998
+ taskId: `boundary:${taskCardId}:needs-human:${item.index}`,
999
+ feature: goal.feature,
1000
+ status: 'failed',
1001
+ stage: 'needs-human',
1002
+ stopReason: 'needs-human',
1003
+ error: { code: 'GOAL_DONE_BOUNDARY_MISSING', message: item.missing.join(' · ') },
1004
+ });
1005
+ }
1006
+ for (const [index, predecessor] of blockedDependents) {
1007
+ const goal = opts.goals[index]!;
1008
+ boundaryResults.push({
1009
+ taskId: `boundary:${taskCardId}:blocked:${index + 1}`,
1010
+ feature: goal.feature,
1011
+ status: 'blocked',
1012
+ blockReason: 'dependency-needs-human',
1013
+ stopReason: 'needs-human',
1014
+ error: { code: 'DEPENDENCY_NEEDS_HUMAN', message: `선행 needs-human: ${predecessor}` },
1015
+ });
1016
+ }
1017
+ const withheld = [...blockedGoalIndexes].map((index) => index + 1);
1018
+ try { debug.log('self-dev.orchestrate', 'done-boundary-missing', { taskCardId, boundaryMissing, withheld, action: 'needs-human', eligibleToLaunch: opts.goals.length - blockedGoalIndexes.size }); } catch { /* fail-soft */ }
1019
+ opts = { ...opts, goals: opts.goals.flatMap((goal, index) => blockedGoalIndexes.has(index)
1020
+ ? []
1021
+ : [{ ...goal, id: goal.id ?? String(index) }]) };
1022
+ }
1023
+ }
950
1024
  const pidPath = runId ? join(opts.runsDir ?? selfDevRunsDir(), runId, 'pid.json') : undefined;
951
1025
  // Only the real run directory gets a host-wide binding by default — an overridden runsDir is an isolated test.
952
1026
  const registryDir = opts.launchRegistryDir !== undefined ? opts.launchRegistryDir : opts.runsDir === undefined ? launchRegistryDir() : null;
@@ -1388,7 +1462,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
1388
1462
  // state (with disposition merged when the job has settled). Reused by
1389
1463
  // both `finish()` and the mid-run checkpoint.
1390
1464
  const buildResults = (): SelfDevJobResult[] => {
1391
- const out: SelfDevJobResult[] = [...resumedResults];
1465
+ const out: SelfDevJobResult[] = [...resumedResults, ...boundaryResults];
1392
1466
  for (const [taskId, goal] of taskByGoal) {
1393
1467
  const status = graph.getTask(taskId)?.status ?? 'failed';
1394
1468
  const resumeDisposition = resumeDispositionByGoal.get(goal);
@@ -1420,6 +1494,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
1420
1494
  ...(disp?.providerErrors ? { providerErrors: disp.providerErrors } : {}),
1421
1495
  ...(disp?.rework ? { rework: disp.rework } : {}),
1422
1496
  ...(disp?.mustFix ? { reviewMustFix: disp.mustFix } : {}),
1497
+ ...(disp?.mustFix && goal.hotPaths?.length ? { targetPaths: [...goal.hotPaths] } : {}),
1423
1498
  ...(goalCauseObservedFromFailureClassification(disp?.failureClassification) === true
1424
1499
  ? { goalCauseObserved: true } : {}),
1425
1500
  ...(disp?.runId ? { runId: disp.runId } : {}),
@@ -1496,6 +1571,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
1496
1571
  unclassified: failureKinds.unclassified,
1497
1572
  mainSyncBlocked: failureKinds.mainSyncBlocked,
1498
1573
  parentUnlanded: out.filter((r) => r.blockReason === 'parent-unlanded').length,
1574
+ dependencyNeedsHuman: out.filter((r) => r.blockReason === 'dependency-needs-human').length,
1499
1575
  failures,
1500
1576
  blockedParents: out.filter((r) => r.blockReason === 'parent-unlanded').map((r) => ({ taskId: r.taskId, blockReason: r.blockReason, parentPrNumber: r.parentPrNumber ?? null, ...(r.parentNoPr ? { parentNoPr: true } : {}) })),
1501
1577
  ...(unionDiff ? { unionDiff } : {}),
@@ -12,7 +12,10 @@ import { sweepFrozenMerges } from '../self-implement/frozen-merges.js';
12
12
  import { routeSupervisorVerdict } from './supervisor-verdict-edges.js';
13
13
  import { recordTaskAgentShadowMove, runCardFor, type TaskAgentShadowInput } from '../task-agent/shadow.js';
14
14
  import { cardPrNumber, taskAgentStatePath } from '../task-agent/task-hand.js';
15
- import { classifyMustFixRound, inferMustFixEvidence, type MustFixRoundClassification, type MustFixRoundObservation } from '../self-implement/review-mustfix-class.js';
15
+ import {
16
+ classifyMustFixRound, inferMustFixEvidence, judgeMustFixScope, proposeMustFixSplit,
17
+ type MustFixRoundClassification, type MustFixRoundObservation, type MustFixScope, type MustFixScopeJudgement, type MustFixSplitProposal,
18
+ } from '../self-implement/review-mustfix-class.js';
16
19
 
17
20
  export interface SupervisorRound {
18
21
  round: number;
@@ -115,6 +118,16 @@ export interface SupervisorDecision {
115
118
  mustFix?: MustFixRoundClassification;
116
119
  /** REVIEW-MUSTFIX-CLASSIFY — every oscillating task's measured class, so a mixed round keeps each task's decision. */
117
120
  mustFixByTask?: Record<string, MustFixRoundClassification>;
121
+ /**
122
+ * REVIEW-MUSTFIX-CLASSIFY 범위 축 — must-fix 한 줄마다 (가) in-scope / (나) split / (다) ask-owner.
123
+ * split 은 같은 런 재수리에서 빠지고 «중간 착지 ⊕ 연결 골» 제안을 싣는다(파일·칸 쓰기는 다음 조각 — 이번엔 결정 칸까지).
124
+ * ask-owner 는 칸 주인 HITL 제안. 진동 경로에서 must-fix 를 잰 조각만 — 없으면 생략(지금 동작 그대로).
125
+ */
126
+ mustFixScope?: {
127
+ byTask: Record<string, MustFixScopeJudgement[]>;
128
+ split?: Array<{ taskId: string; action: '중간 착지 ⊕ 연결 골'; proposals: MustFixSplitProposal[] }>;
129
+ askOwner?: Array<{ taskId: string; hitl: string; items: string[] }>;
130
+ };
118
131
  oscillation?: { taskIds: string[]; helper: 'review-oscillation'; signature: string; repairGoals?: Record<string, string>; heldTaskIds?: string[] };
119
132
  pendingDecision?: 'attempt-care-escalation';
120
133
  }
@@ -262,11 +275,70 @@ function classifyTaskMustFix(result: SupervisorJobResult, preceding: SupervisorR
262
275
  }
263
276
 
264
277
  /**
265
- * Classes that hold a task out of this round's same-run repair. Only ② acts in this slice; ③ recurring is
266
- * observed (decision `mustFix`/`mustFixByTask` · crossReview suggestion) but behaves as ① — acting on it is a
267
- * follow-up cell (REVIEW-MUSTFIX-CLASSIFY partial landing).
278
+ * Classes/scopes that hold a task out of this round's same-run repair: ② post-land-evidence, and (나) split when
279
+ * every must-fix item of the task is split (③ recurring items are split). A partly split task is repaired with its
280
+ * non-split items only.
281
+ */
282
+ const MUST_FIX_HELD = new Set<MustFixRoundClassification['class'] | MustFixScope>(['post-land-evidence', 'split']);
283
+ // ⚠️ 'post-land-evidence' 는 보류 «사유» 문면에만 쓰인다 — 보류 여부는 줄 단위 'split'(② 줄 포함)이 정한다.
284
+
285
+ /**
286
+ * REVIEW-MUSTFIX-CLASSIFY 범위 축 — 한 조각의 must-fix 를 줄마다 범위 판정한다. `prevItems` 는 앞 회차 원장의 같은
287
+ * 조각(또는 수리 계보) 지적 — 앞 회차가 must-fix 를 안 쟀으면 undefined(new-axis 신호를 안 낸다).
268
288
  */
269
- const MUST_FIX_HELD = new Set<MustFixRoundClassification['class']>(['post-land-evidence']);
289
+ function judgeTaskMustFixScope(
290
+ result: SupervisorJobResult, preceding: SupervisorRound | undefined, classification: MustFixRoundClassification,
291
+ ): MustFixScopeJudgement[] {
292
+ const items = mustFixFromResults([result]).items ?? [];
293
+ const pairIds = new Set([result.taskId, ...(result.oscillationRepairOf ? [result.oscillationRepairOf] : [])]);
294
+ const precedingItems = preceding?.mustFix?.items;
295
+ const prevItems = precedingItems === undefined ? undefined
296
+ : precedingItems.filter((item) => item.taskId !== undefined && pairIds.has(item.taskId));
297
+ return items.map((item) => judgeMustFixScope(item, {
298
+ ...(result.changedFiles ? { changedFiles: result.changedFiles } : {}),
299
+ ...(result.targetPaths ? { targetPaths: result.targetPaths } : {}),
300
+ ...(result.prNumber !== undefined ? { prNumber: result.prNumber } : {}),
301
+ ...(result.rework?.rounds !== undefined ? { reviewRound: result.rework.rounds } : {}),
302
+ ...(prevItems !== undefined ? { prevItems } : {}),
303
+ ...(classification.recurring ? { recurring: classification.recurring } : {}),
304
+ }));
305
+ }
306
+
307
+ /**
308
+ * 범위 판정을 결정 칸으로 접고 줄마다 관측을 남긴다 — (나) 는 «중간 착지 ⊕ 연결 골» 제안, (다) 는 칸 주인 HITL 제안.
309
+ * 실제 연결 골 파일·칸 근거 쓰기·intent 자동 주입 실행은 다음 조각.
310
+ */
311
+ function mustFixScopeDecision(
312
+ oscillating: readonly SupervisorJobResult[],
313
+ taskClasses: ReadonlyMap<string, MustFixRoundClassification>,
314
+ taskScopes: ReadonlyMap<string, MustFixScopeJudgement[]>,
315
+ ): SupervisorDecision['mustFixScope'] {
316
+ const byTask: Record<string, MustFixScopeJudgement[]> = {};
317
+ const split: NonNullable<NonNullable<SupervisorDecision['mustFixScope']>['split']> = [];
318
+ const askOwner: NonNullable<NonNullable<SupervisorDecision['mustFixScope']>['askOwner']> = [];
319
+ for (const result of oscillating) {
320
+ const judged = taskScopes.get(result.taskId) ?? [];
321
+ if (judged.length === 0 || byTask[result.taskId]) continue;
322
+ byTask[result.taskId] = judged;
323
+ const cls = taskClasses.get(result.taskId)?.class ?? 'unmeasured';
324
+ for (const j of judged) {
325
+ const action = j.scope === 'split' ? 'split-link-goal' : j.scope === 'ask-owner' ? 'ask-owner-hitl' : 'fix-same-run';
326
+ try { debug.log('self-dev.supervisor', 'mustfix-scope', { taskId: result.taskId, class: cls, scope: j.scope, signals: j.signals, action }); } catch { /* fail-open */ }
327
+ }
328
+ const splits = judged.filter((j) => j.scope === 'split');
329
+ if (splits.length) {
330
+ split.push({ taskId: result.taskId, action: '중간 착지 ⊕ 연결 골',
331
+ proposals: splits.map((j) => proposeMustFixSplit(j)) });
332
+ }
333
+ const asks = judged.filter((j) => j.scope === 'ask-owner');
334
+ if (asks.length) {
335
+ askOwner.push({ taskId: result.taskId, items: asks.map((j) => j.text),
336
+ hitl: `칸 주인에게 묻는다 — must-fix ${asks.length}건 범위 판단 불가(${[...new Set(asks.map((j) => j.reason))].join(' · ')})` });
337
+ }
338
+ }
339
+ if (Object.keys(byTask).length === 0) return undefined;
340
+ return { byTask, ...(split.length ? { split } : {}), ...(askOwner.length ? { askOwner } : {}) };
341
+ }
270
342
 
271
343
  export function decideNextRun(input: {
272
344
  results: readonly SupervisorJobResult[];
@@ -557,30 +629,52 @@ export function decideNextRun(input: {
557
629
  // REVIEW-MUSTFIX-CLASSIFY — 슈퍼바이저는 추이 대신 회차 분류를 먼저 본다(대표 10-12 «노하우가 아니라 로직으로» · 임의 임계 없음).
558
630
  // ① new-defect — 그대로 수렴(진동 수리 유지).
559
631
  // ② post-land-evidence — 증거는 착지 뒤에만 난다 ⇒ 같은 런 재수리 0, «그림자 착지 → 관측 → live» 쪼개기 결정.
560
- // ③ recurring — 수리 뒤 같은 지적 ⇒ 이 조각에선 관측만(교차 리뷰 제안을 결정에 싣고 동작은 ① 그대로 · 후속 칸).
632
+ // ③ recurring — 수리 뒤 같은 지적 ⇒ 교차 리뷰 제안을 결정에 싣고, 그 줄은 범위 축에서 (나) split 으로 같은 런 수리에서 뺀다.
561
633
  // unmeasured — 분류 불가 ⇒ 지금 동작 그대로. 분류는 조각마다 — 한 조각의 분류가 다른 조각의 수리를 끊지 않는다.
562
634
  const taskClasses = new Map(oscillating.map((result) => [result.taskId, classifyTaskMustFix(result, preceding)]));
563
- const fresh = oscillating.filter((result) => !isRepaired(result) && !MUST_FIX_HELD.has(taskClasses.get(result.taskId)!.class));
635
+ // 범위 축 — must-fix 한 줄마다 (가)/(나)/(다). 모든 줄이 (나) 면 조각을 보류하고, 일부면 (나) 를 뺀 줄로만 수리한다.
636
+ const taskScopes = new Map(oscillating.map((result) => [result.taskId,
637
+ judgeTaskMustFixScope(result, preceding, taskClasses.get(result.taskId)!)]));
638
+ const allSplit = (taskId: string): boolean => {
639
+ const judged = taskScopes.get(taskId) ?? [];
640
+ return judged.length > 0 && judged.every((j) => j.scope === 'split');
641
+ };
642
+ // 보류는 줄 단위 범위로만 가른다 — ② 줄은 범위 축에서 늘 split 이므로 ② 회차(모든 줄이 착지 뒤 증거)는 allSplit 와 같고,
643
+ // 한 줄이라도 (가)/(다) 가 남으면 그 줄은 수리 골로 간다(조각 통째 보류 금지).
644
+ const isClassHeld = (taskId: string): boolean => MUST_FIX_HELD.has('split') && allSplit(taskId);
645
+ const fresh = oscillating.filter((result) => !isRepaired(result) && !isClassHeld(result.taskId));
564
646
  const classes = [...taskClasses.values()];
565
647
  // Decision-level class: ② (the only acting class) first, then observed ③, else ①.
566
648
  const mustFixClass = classes.find((c) => c.class === 'post-land-evidence') ?? classes.find((c) => c.class === 'recurring')
567
649
  ?? classes.find((c) => c.class === 'new-defect');
568
- // Held = already repaired once, or classified ② — either way it never rides this round's rerun.
650
+ // Held = already repaired once, classified ②, or every must-fix item is (나) split — none rides this round's rerun.
569
651
  const classHeld = [...new Set(oscillating.filter((result) => !isRepaired(result)
570
- && MUST_FIX_HELD.has(taskClasses.get(result.taskId)!.class)).map((result) => result.taskId))];
652
+ && isClassHeld(result.taskId)).map((result) => result.taskId))];
571
653
  const held = [...new Set([...oscillating.filter(isRepaired).map((result) => result.taskId), ...classHeld])];
572
654
  const repairedHeld = held.filter((id) => !classHeld.includes(id));
573
655
  // Every task's measured class survives in the decision — a mixed round keeps ② split and the observed ③ cross-review suggestion both.
574
656
  const mustFixByTask: Record<string, MustFixRoundClassification> = Object.fromEntries(
575
657
  [...taskClasses].filter(([, c]) => c.class !== 'unmeasured'));
576
- const heldReasons = [...new Set(classes.filter((c) => MUST_FIX_HELD.has(c.class)).map((c) => c.reason))];
658
+ const heldReasons = [...new Set([
659
+ // 사유는 실제로 분류·범위로 보류된 조각에서만 — 수리되거나 이미 수리해 보류된 조각의 ② 사유는 싣지 않는다.
660
+ ...classHeld.map((id) => taskClasses.get(id)!).filter((c) => MUST_FIX_HELD.has(c.class)).map((c) => c.reason),
661
+ ...(classHeld.some((id) => !MUST_FIX_HELD.has(taskClasses.get(id)!.class))
662
+ ? ['must-fix 가 전부 (나) 범위 밖 — 같은 런 재수리 0, 중간 착지 ⊕ 연결 골'] : []),
663
+ ])];
577
664
  const heldReasonSuffix = heldReasons.length ? ` · ${heldReasons.join(' · ')}` : '';
665
+ // (나) split 줄은 같은 런 수리 골에서 뺀다 — 수리는 (가)·(다) 줄로만.
666
+ const repairMustFix = (result: SupervisorJobResult): string[] => {
667
+ const splitTexts = new Set((taskScopes.get(result.taskId) ?? []).filter((j) => j.scope === 'split').map((j) => j.text));
668
+ return (result.reviewMustFix ?? []).filter((text) => !splitTexts.has(text));
669
+ };
578
670
  const repairGoals: Record<string, string> = Object.fromEntries(fresh.flatMap((result) => {
579
- const goal = result.prNumber && result.reviewMustFix?.length
671
+ const mustFix = repairMustFix(result);
672
+ const goal = result.prNumber && mustFix.length
580
673
  ? authorRepairGoal({ pr: result.prNumber, category: 'review-oscillation', originalRequest: result.feature,
581
- mustFix: result.reviewMustFix }) : null;
674
+ mustFix }) : null;
582
675
  return goal ? [[result.taskId, goal]] : [];
583
676
  }));
677
+ const mustFixScope = mustFixScopeDecision(oscillating, taskClasses, taskScopes);
584
678
  // A caller that declares it cannot run the authored goal (false), or one that can but has no goal for every fresh
585
679
  // oscillating task, would turn add-repair-task into a same-strategy relaunch — stop for a human instead.
586
680
  // Undefined is the pure decision (caller unknown): it names the first repair as the goal contract asks.
@@ -606,6 +700,7 @@ export function decideNextRun(input: {
606
700
  ...(action === 'stop' ? { stopReason: 'review-oscillating' as const } : {}),
607
701
  ...(mustFixClass ? { mustFix: mustFixClass } : {}),
608
702
  ...(Object.keys(mustFixByTask).length ? { mustFixByTask } : {}),
703
+ ...(mustFixScope ? { mustFixScope } : {}),
609
704
  oscillation: { taskIds, helper: 'review-oscillation', signature, ...(Object.keys(repairGoals).length ? { repairGoals } : {}),
610
705
  ...(action === 'add-repair-task' && held.length ? { heldTaskIds: held } : {}) },
611
706
  pendingDecision: 'attempt-care-escalation',
@@ -98,7 +98,7 @@ export interface SelfDevJobResult {
98
98
  /** Commits this child added against its own `--base`. 0 is not completion progress. */
99
99
  commitsAheadOfBase?: number;
100
100
  /** A dependency is done but its result is not on main; no child was launched. */
101
- blockReason?: 'parent-unlanded';
101
+ blockReason?: 'parent-unlanded' | 'dependency-needs-human';
102
102
  parentPrNumber?: number;
103
103
  /** The upstream completed in a worktree without opening a PR. */
104
104
  parentNoPr?: true;
@@ -127,6 +127,10 @@ export interface SelfDevJobResult {
127
127
  oscillationRepairOf?: string;
128
128
  /** Verbatim final reviewer must-fix items for a bounded helper repair. */
129
129
  reviewMustFix?: string[];
130
+ /** REVIEW-MUSTFIX-CLASSIFY 범위 축 — PR 변경 파일. undefined = 안 쟀다(범위 판정은 ask-owner 로 기운다 · 생산자는 다음 조각). */
131
+ changedFiles?: string[];
132
+ /** REVIEW-MUSTFIX-CLASSIFY 범위 축 — 골 대상 경로(goal.hotPaths). undefined = 골이 선언하지 않았다. */
133
+ targetPaths?: string[];
130
134
  /** Whether the child review actually ran; omitted preserves legacy producers. */
131
135
  reviewed?: boolean;
132
136
  /** Why the child did not run review; omitted preserves legacy review-unobserved handling. */
@@ -7,6 +7,11 @@ export interface GateTestShard {
7
7
  plannedSeconds: number;
8
8
  }
9
9
 
10
+ /** A requested shard count cannot hold the measured files; more shards may make the same plan valid. */
11
+ export class GateShardCapacityError extends Error {
12
+ constructor(message: string) { super(message); this.name = 'Error'; }
13
+ }
14
+
10
15
  /** Keep real child/PTY tests out of ordinary self-gate shards, within the caller's shard budget. */
11
16
  export function planSelfGateSpawnSeparatedShards(
12
17
  files: readonly string[],
@@ -19,8 +24,11 @@ export function planSelfGateSpawnSeparatedShards(
19
24
  const spawn = unique.filter(isGateSpawnLaneFile);
20
25
  const regular = unique.filter((file) => !isGateSpawnLaneFile(file));
21
26
  if (!spawn.length || !regular.length) return planGateTestShards(unique, rssMb, seconds, budgetGiB, shardCount);
22
- if (shardCount < 2) throw new Error('self gate spawn lane needs at least two shards when regular and spawn tests coexist');
23
- const spawnCount = Math.min(3, spawn.length, shardCount - 1);
27
+ if (shardCount < 2) throw new GateShardCapacityError('self gate spawn lane needs at least two shards when regular and spawn tests coexist');
28
+ // Three spawn bundles are the normal lane width, not a memory ceiling. A 5 GiB spawn file cannot share an 8 GiB
29
+ // bundle with another such file; retain lane isolation while allowing the measured plan to grow past three.
30
+ const neededSpawn = planGateTestShards(spawn, rssMb, seconds, budgetGiB).length;
31
+ const spawnCount = Math.min(spawn.length, shardCount - 1, Math.max(3, neededSpawn));
24
32
  const planned = [
25
33
  ...planGateTestShards(regular, rssMb, seconds, budgetGiB, shardCount - spawnCount),
26
34
  ...planGateTestShards(spawn, rssMb, seconds, budgetGiB, spawnCount),
@@ -65,7 +73,7 @@ export function planGateTestShards(
65
73
  if (!shard) {
66
74
  const totalRssMb = sorted.reduce((sum, candidate) => sum + rssMb.get(candidate)!, 0);
67
75
  const largestRssMb = rssMb.get(sorted[0]!)!;
68
- throw new Error(`test files exceed ${shardCount} shard memory budgets (files=${unique.length} · totalRssMb=${Math.round(totalRssMb)} · largestRssMb=${Math.round(largestRssMb)} · budgetMb=${capacity} · neededShards≥${Math.ceil(totalRssMb / capacity)})`);
76
+ throw new GateShardCapacityError(`test files exceed ${shardCount} shard memory budgets (files=${unique.length} · totalRssMb=${Math.round(totalRssMb)} · largestRssMb=${Math.round(largestRssMb)} · budgetMb=${capacity} · neededShards≥${Math.ceil(totalRssMb / capacity)})`);
69
77
  }
70
78
  shard.files.push(file);
71
79
  shard.plannedRssMb += rss;
@@ -1,12 +1,12 @@
1
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
1
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statfsSync, statSync, writeFileSync } from 'node:fs';
2
+ import { availableParallelism, freemem, tmpdir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import { debug, redactSecretText } from '../debug/log.js';
5
5
  import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
6
6
  import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
7
7
  import { withBaselineWorktree } from '../self-implement/gate-baseline.js';
8
8
  import { aggregateGateTestShards, type GateShardAttempt, type GateShardAggregate } from './shard-aggregate.js';
9
- import { planFixedGateTestShards, planSelfGateSpawnSeparatedShards, type GateTestShard } from './shard-plan.js';
9
+ import { GateShardCapacityError, planFixedGateTestShards, planSelfGateSpawnSeparatedShards, type GateTestShard } from './shard-plan.js';
10
10
  import { isGateSpawnLaneFile } from './spawn-lane-files.js';
11
11
 
12
12
  export interface ShardRunResult {
@@ -15,11 +15,16 @@ export interface ShardRunResult {
15
15
  attempts: GateShardAttempt[];
16
16
  reason?: string;
17
17
  measurementFailures?: number;
18
- /** Present only for opt-in `--fixed-shard-distribution` (no RSS pre-measurement). Absent = the measured planner. */
19
- distribution?: 'fixed';
18
+ /** The measured RSS plan needed more bundles than the requested count. */
19
+ expandedFrom?: number;
20
+ /** A fixed plan selected explicitly, or after the measured plan exceeds host expansion capacity. */
21
+ distribution?: 'fixed' | 'fixed-cap-fallback';
22
+ fallbackReason?: string;
20
23
  /** OP FU (MK #8178 shard-9) — raw evidence of every failed shard process (exit≠0 · signal · no JUnit). Observation only:
21
24
  * the aggregate never reads it. Absent = no shard process reported failure output. */
22
25
  failureEvidence?: ShardFailureEvidence[];
26
+ /** Latest failed attempt's reason for each incomplete shard; copied into the gate artifact summary. */
27
+ unmeasuredByShard?: Record<string, string>;
23
28
  }
24
29
 
25
30
  /** What a failed shard process leaves behind so «test failure vs runner error» can be told apart after the fact. */
@@ -42,6 +47,38 @@ export interface ShardFailureEvidence extends ShardFailureOutput {
42
47
  export interface ShardRunMode {
43
48
  /** OP FU — sorted round-robin into `count` shards, zero pre-measurement runs. Default off: the measured planner. */
44
49
  fixedDistribution?: boolean;
50
+ /** Measured on the executing host; override only for deterministic planning tests. */
51
+ hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number };
52
+ }
53
+
54
+ function hostResources(): ShardRunMode['hostResources'] | undefined {
55
+ try {
56
+ const tmp = statfsSync(tmpdir());
57
+ // Linux page cache is reclaimable. `freemem()` alone saw only ~10 GiB on a WSL host
58
+ // with 24 GiB MemAvailable and would incorrectly cap a two-shard plan at one.
59
+ let freeMemoryGiB = freemem() / (1024 ** 3);
60
+ if (process.platform === 'linux') {
61
+ const availableKiB = /^MemAvailable:\s+(\d+)\s+kB/m.exec(readFileSync('/proc/meminfo', 'utf8'))?.[1];
62
+ if (availableKiB) freeMemoryGiB = Number(availableKiB) / (1024 ** 2);
63
+ }
64
+ return {
65
+ cores: availableParallelism(),
66
+ freeMemoryGiB,
67
+ freeTmpGiB: Number(tmp.bavail) * Number(tmp.bsize) / (1024 ** 3),
68
+ };
69
+ } catch { return undefined; }
70
+ }
71
+
72
+ /** One expansion slot needs one CPU, one shard memory budget, and 1 GiB of free tmp space.
73
+ * Explicitly requested shards remain the caller's choice; this only limits automatic growth. */
74
+ export function maxAutomaticShardCount(requested: number, budgetGiB: number, resources: ShardRunMode['hostResources']): number {
75
+ if (!resources || !Number.isFinite(budgetGiB) || budgetGiB <= 0) return requested;
76
+ const limit = Math.min(
77
+ Math.floor(resources.cores),
78
+ Math.floor(resources.freeMemoryGiB / budgetGiB),
79
+ Math.floor(resources.freeTmpGiB),
80
+ );
81
+ return Math.max(requested, Number.isFinite(limit) ? limit : requested);
45
82
  }
46
83
 
47
84
  export type ShardProcess = (cwd: string, files: readonly string[]) => {
@@ -155,13 +192,45 @@ export function runShardedGateTests(
155
192
  }
156
193
  }
157
194
  const measurementFailures = failedMeasurements.length || undefined;
158
- let shards: GateTestShard[];
195
+ const fixedAtHostCap = (maxCount: number, reason: string): ShardRunResult => {
196
+ try {
197
+ const fixed = planFixedGateTestShards(files, maxCount);
198
+ debug.log('self-dev.shard', 'host-cap-fixed-fallback', { requested: count, cap: maxCount,
199
+ files: new Set(files).size, reason, measurementFailures: measurementFailures ?? 0 });
200
+ return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed-cap-fallback',
201
+ fallbackReason: reason, ...(measurementFailures ? { measurementFailures } : {}) };
202
+ } catch (error) {
203
+ return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [],
204
+ reason: `host-cap fixed fallback failed: ${String(error)}; measured plan: ${reason}`,
205
+ ...(measurementFailures ? { measurementFailures } : {}) };
206
+ }
207
+ };
208
+ let shards: GateTestShard[] | undefined;
209
+ let plannedCount = count;
159
210
  try {
160
- shards = planSelfGateSpawnSeparatedShards(files, rss, seconds, budgetGiB, count);
211
+ const fileCount = new Set(files).size;
212
+ const totalRss = [...rss.values()].reduce((sum, value) => sum + value, 0);
213
+ const lowerBound = Number.isFinite(budgetGiB) && budgetGiB > 0 ? Math.ceil(totalRss / (budgetGiB * 1024)) : count;
214
+ plannedCount = Math.max(count, Math.min(fileCount, lowerBound));
215
+ // The requested count may exceed the number of files. Only expansion is bounded by file count.
216
+ const maxCount = Math.max(count, Math.min(fileCount, maxAutomaticShardCount(count, budgetGiB, mode.hostResources ?? hostResources())));
217
+ if (plannedCount > maxCount) return fixedAtHostCap(maxCount, `host shard expansion cap ${maxCount} < needed ${plannedCount} (requested ${count}, measured RSS sum ${Math.round(totalRss)} MiB, budget ${budgetGiB} GiB)`);
218
+ for (; plannedCount <= maxCount; plannedCount++) {
219
+ try { shards = planSelfGateSpawnSeparatedShards(files, rss, seconds, budgetGiB, plannedCount); break; }
220
+ catch (error) {
221
+ if (!(error instanceof GateShardCapacityError)) throw error;
222
+ if (plannedCount === maxCount) return fixedAtHostCap(maxCount, `host shard expansion cap ${maxCount} < needed ≥${maxCount + 1} (requested ${count}, ${error.message})`);
223
+ }
224
+ }
161
225
  } catch (error) {
162
226
  return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [], reason: String(error), ...(measurementFailures ? { measurementFailures } : {}) };
163
227
  }
164
- return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree), ...(measurementFailures ? { measurementFailures } : {}) };
228
+ if (!shards) return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [], reason: 'shard planning produced no result' };
229
+ if (plannedCount > count) debug.log('self-dev.shard', 'plan-expanded', {
230
+ requested: count, planned: shards.length, files: new Set(files).size, budgetGiB,
231
+ measurementFailures: measurementFailures ?? 0,
232
+ });
233
+ return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
165
234
  }
166
235
 
167
236
  /** Shared by the measured and the fixed planner: current + baseline per shard, one retry round, one aggregate. */
@@ -214,8 +283,32 @@ function runPlannedShards(
214
283
  return aggregateGateTestShards(shards, attempts);
215
284
  });
216
285
  const evidence = failureEvidence.length ? { failureEvidence } : {};
217
- if ('retryShardIds' in baseline) return { aggregate: baseline, shards, attempts, ...evidence };
218
- return { aggregate: { status: 'unmeasured', retryShardIds: shards.map((shard) => shard.id) }, shards, attempts, reason: baseline.log, ...evidence };
286
+ if ('retryShardIds' in baseline) return {
287
+ aggregate: baseline, shards, attempts, ...evidence,
288
+ ...(baseline.retryShardIds.length ? { unmeasuredByShard: incompleteShardReasons(baseline.retryShardIds, attempts) } : {}),
289
+ };
290
+ const retryShardIds = shards.map((shard) => shard.id);
291
+ return {
292
+ aggregate: { status: 'unmeasured', retryShardIds }, shards, attempts, reason: baseline.log, ...evidence,
293
+ unmeasuredByShard: Object.fromEntries(retryShardIds.map((id) => [id, `baseline worktree: ${redactSecretText(baseline.log).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500)}`])),
294
+ };
295
+ }
296
+
297
+ function incompleteShardReasons(shardIds: readonly string[], attempts: readonly GateShardAttempt[]): Record<string, string> {
298
+ return Object.fromEntries(shardIds.map((id) => {
299
+ const latest = attempts.filter((attempt) => attempt.shardId === id).at(-1);
300
+ if (!latest) return [id, 'no shard attempt recorded'];
301
+ const side = (name: string, rc: number | null, signal: string | null | undefined, junit: string | undefined, diagnostic: string | undefined): string => {
302
+ const safeDiagnostic = diagnostic ? redactSecretText(diagnostic).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500) : undefined;
303
+ return `${name}: exit ${rc ?? 'unavailable'}, signal ${signal ?? 'none'}, JUnit ${junit === undefined ? 'missing' : 'present'}`
304
+ + (safeDiagnostic ? `; ${safeDiagnostic}` : '');
305
+ };
306
+ const statuses = [
307
+ side('current', latest.currentExitCode, latest.currentSignal, latest.currentJUnit, latest.currentDiagnostic),
308
+ ...(latest.baselineFiles?.length === 0 ? [] : [side('baseline', latest.baselineExitCode, latest.baselineSignal, latest.baselineJUnit, latest.baselineDiagnostic)]),
309
+ ];
310
+ return [id, `${statuses.join(' · ')} · aggregate rejected (incomplete, malformed JUnit, or exit/JUnit mismatch)`];
311
+ }));
219
312
  }
220
313
 
221
314
  export function selfGateShardTimeoutMs(files: readonly string[]): number {