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,10 +1,9 @@
1
- import { closeSync, mkdirSync, openSync, rmSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
1
  import { debug } from '../debug/log.js';
4
2
  import { releaseLedgerRoot } from '../instance/resolve.js';
5
3
  import { adviseLaunch, compareLaunchAdvice } from '../harness/launch-advice.js';
6
4
  import type { QueuePool } from '../harness/harness-queue.js';
7
5
  import type { ReleaseReadiness } from '../../scripts/release-loop/release-readiness.js';
6
+ import { ReleaseRunClaimConflict, releaseRunLockOwnerAlive, withDirectReleaseRunLock, withForceReleaseRunMarker } from './release-single-flight.js';
8
7
 
9
8
  export type ReleaseIfReadySkip = { skipped: true; reason: Exclude<ReleaseReadiness, { ready: true }>['reason']; detail: string };
10
9
 
@@ -16,6 +15,8 @@ export async function runReleaseIfReady<T>(version: string, deps: {
16
15
  now?: () => Date;
17
16
  advice?: typeof adviseLaunch;
18
17
  pool?: () => QueuePool | undefined;
18
+ /** Explicit operator override: keep readiness checks, bypass only the same-version lock. */
19
+ forceNew?: boolean;
19
20
  }): Promise<ReleaseIfReadySkip | { skipped: false; result: T }> {
20
21
  const skip = (readiness: Exclude<ReleaseReadiness, { ready: true }>): ReleaseIfReadySkip => {
21
22
  const detail = readiness.reason === 'checklist-blocked'
@@ -24,36 +25,36 @@ export async function runReleaseIfReady<T>(version: string, deps: {
24
25
  debug.log('release-loop.readiness', readiness.reason, { version, detail });
25
26
  return { skipped: true, reason: readiness.reason, detail };
26
27
  };
27
- const readiness = await deps.readiness(version);
28
+ const ledgerRoot = deps.ledgerRoot ?? releaseLedgerRoot();
29
+ const readiness = await deps.readiness(version, { isPidAlive: deps.forceNew ? () => false
30
+ : (pid) => releaseRunLockOwnerAlive(version, ledgerRoot, pid) });
28
31
  if (!readiness.ready) return skip(readiness);
29
32
 
30
- const dir = join(deps.ledgerRoot ?? releaseLedgerRoot(), 'release', version);
31
- mkdirSync(dir, { recursive: true });
32
- const lock = join(dir, 'run.lock');
33
- let fd: number;
34
- try { fd = openSync(lock, 'wx', 0o600); }
35
- catch (error) {
36
- if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
33
+ if (deps.forceNew) return withForceReleaseRunMarker(version, ledgerRoot, async () => {
34
+ const atStart = await deps.readiness(version, { isPidAlive: () => false });
35
+ if (!atStart.ready) return skip(atStart);
36
+ return { skipped: false, result: await deps.run() };
37
+ });
38
+
39
+ try {
40
+ return await withDirectReleaseRunLock(version, ledgerRoot, async () => {
41
+ // This call still checks publication and checklist, but must not treat our own lock as another runner.
42
+ const insideLock = await deps.readiness(version, { isPidAlive: () => false });
43
+ if (!insideLock.ready) return skip(insideLock);
44
+ debug.log('release-loop.readiness', 'ready', { version });
45
+ try {
46
+ const advice = (deps.advice ?? adviseLaunch)({ pool: deps.pool?.(), caller: 'release-run' });
47
+ const { kind } = compareLaunchAdvice(advice, 'launched');
48
+ debug.log('resource.advice', 'launch-advice', { caller: 'release-run', verdict: advice.verdict, why: advice.why, actual: 'launched', kind, version });
49
+ } catch {
50
+ // Shadow only: a throwing advice seam must never affect the launch decision or result.
51
+ }
52
+ return { skipped: false, result: await deps.run() };
53
+ }, { pid: deps.pid, now: deps.now });
54
+ } catch (error) {
55
+ if (!(error instanceof ReleaseRunClaimConflict)) throw error;
37
56
  const detail = 'run.lock already exists';
38
57
  debug.log('release-loop.readiness', 'already-running', { version, detail });
39
58
  return { skipped: true, reason: 'already-running', detail };
40
59
  }
41
- try {
42
- writeFileSync(fd, `${JSON.stringify({ pid: deps.pid ?? process.pid, startedAt: (deps.now ?? (() => new Date()))().toISOString() })}\n`);
43
- // This call still checks publication and checklist, but must not treat our own lock as another runner.
44
- const insideLock = await deps.readiness(version, { isPidAlive: () => false });
45
- if (!insideLock.ready) return skip(insideLock);
46
- debug.log('release-loop.readiness', 'ready', { version });
47
- try {
48
- const advice = (deps.advice ?? adviseLaunch)({ pool: deps.pool?.(), caller: 'release-run' });
49
- const { kind } = compareLaunchAdvice(advice, 'launched');
50
- debug.log('resource.advice', 'launch-advice', { caller: 'release-run', verdict: advice.verdict, why: advice.why, actual: 'launched', kind, version });
51
- } catch {
52
- // Shadow only: a throwing advice seam must never affect the launch decision or result.
53
- }
54
- return { skipped: false, result: await deps.run() };
55
- } finally {
56
- closeSync(fd);
57
- rmSync(lock);
58
- }
59
60
  }
@@ -0,0 +1,178 @@
1
+ import { closeSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { join } from 'node:path';
4
+ import { Database } from 'bun:sqlite';
5
+ import { graphRunAlive, type GraphRunState } from '../graph-runner/runner.js';
6
+ import { psProcessStartMs, START_TOLERANCE_MS } from '../harness/harness-stop.js';
7
+
8
+ export interface ActiveReleaseRun {
9
+ runId: string;
10
+ pid: number;
11
+ startedAt: string;
12
+ }
13
+
14
+ export class ReleaseRunClaimConflict extends Error {
15
+ readonly code = 'EEXIST';
16
+ constructor() { super('release run claim already exists'); }
17
+ }
18
+
19
+ function isPidAlive(pid: number): boolean {
20
+ try { process.kill(pid, 0); return true; }
21
+ catch (error) {
22
+ if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false;
23
+ if ((error as NodeJS.ErrnoException).code === 'EPERM') return true;
24
+ throw error;
25
+ }
26
+ }
27
+
28
+ /** The saved graph run is the authority for an active release, not a process-name match. */
29
+ export function findActiveReleaseRun(version: string, ledgerRoot: string): ActiveReleaseRun | undefined {
30
+ const dir = join(ledgerRoot, 'graph-runs', 'release-loop');
31
+ let names: string[];
32
+ try { names = readdirSync(dir).filter((name) => name.endsWith('.json')); }
33
+ catch (error) {
34
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;
35
+ throw error;
36
+ }
37
+ const runs: ActiveReleaseRun[] = [];
38
+ for (const name of names) {
39
+ try {
40
+ const state = JSON.parse(readFileSync(join(dir, name), 'utf8')) as {
41
+ graphId?: unknown; runId?: unknown; status?: unknown; pid?: unknown; pidStartedAt?: unknown; startedAt?: unknown;
42
+ input?: { version?: unknown };
43
+ };
44
+ if (state.graphId !== 'release-loop' || state.status !== 'running' || state.input?.version !== version
45
+ || typeof state.runId !== 'string' || typeof state.startedAt !== 'string'
46
+ || typeof state.pid !== 'number' || !Number.isSafeInteger(state.pid) || state.pid <= 0
47
+ || graphRunAlive(state as GraphRunState) !== true) continue;
48
+ runs.push({ runId: state.runId, pid: state.pid, startedAt: state.startedAt });
49
+ } catch (error) {
50
+ if (error instanceof SyntaxError || (error as NodeJS.ErrnoException).code === 'ENOENT') continue;
51
+ throw error;
52
+ }
53
+ }
54
+ return runs.sort((a, b) => b.startedAt.localeCompare(a.startedAt))[0];
55
+ }
56
+
57
+ export function readReleaseRunLock(version: string, ledgerRoot: string): { pid?: number; startedAt?: string; pidStartedAt?: string } | undefined {
58
+ try {
59
+ const value = JSON.parse(readFileSync(join(ledgerRoot, 'release', version, 'run.lock'), 'utf8')) as { pid?: unknown; startedAt?: unknown; pidStartedAt?: unknown };
60
+ return { pid: typeof value.pid === 'number' ? value.pid : undefined,
61
+ startedAt: typeof value.startedAt === 'string' ? value.startedAt : undefined,
62
+ pidStartedAt: typeof value.pidStartedAt === 'string' ? value.pidStartedAt : undefined };
63
+ } catch (error) {
64
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;
65
+ if (error instanceof SyntaxError) return {};
66
+ throw error;
67
+ }
68
+ }
69
+
70
+ /** A live PID belongs to this lock only if its process birth still matches. */
71
+ export function releaseRunLockOwnerAlive(version: string, ledgerRoot: string, pid: number): boolean {
72
+ const owner = readReleaseRunLock(version, ledgerRoot);
73
+ if (!owner || owner.pid !== pid || !isPidAlive(pid)) return false;
74
+ const actual = psProcessStartMs(pid);
75
+ // A failed birth probe must not let a second launch reclaim a live PID's lock.
76
+ if (actual === null) return true;
77
+ const recorded = Date.parse(owner.pidStartedAt ?? '');
78
+ if (Number.isFinite(recorded)) return Math.abs(actual - recorded) <= START_TOLERANCE_MS;
79
+ // Older locks have only their claim time. A process born after that claim reused the PID.
80
+ const claimedAt = Date.parse(owner.startedAt ?? '');
81
+ return Number.isFinite(claimedAt) && actual <= claimedAt + START_TOLERANCE_MS;
82
+ }
83
+
84
+ function claimDb(ledgerRoot: string): Database {
85
+ mkdirSync(join(ledgerRoot, 'release'), { recursive: true });
86
+ const db = new Database(join(ledgerRoot, 'release', 'run-lock-claim.sqlite'), { create: true });
87
+ db.exec('PRAGMA busy_timeout = 5000');
88
+ db.exec('CREATE TABLE IF NOT EXISTS force_starts (token TEXT PRIMARY KEY, version TEXT NOT NULL, pid INTEGER NOT NULL, pid_started_at TEXT NOT NULL, started_at TEXT NOT NULL)');
89
+ return db;
90
+ }
91
+
92
+ type ForceStart = { token: string; version: string; pid: number; pid_started_at: string; started_at: string };
93
+ function forceStartAlive(row: ForceStart): boolean {
94
+ if (!isPidAlive(row.pid)) return false;
95
+ const actual = psProcessStartMs(row.pid);
96
+ return actual === null || Math.abs(actual - Date.parse(row.pid_started_at)) <= START_TOLERANCE_MS;
97
+ }
98
+
99
+ function liveForceStart(db: Database, version: string): ForceStart | undefined {
100
+ const rows = db.query('SELECT token, version, pid, pid_started_at, started_at FROM force_starts WHERE version = ?').all(version) as ForceStart[];
101
+ for (const row of rows) {
102
+ if (forceStartAlive(row)) return row;
103
+ db.query('DELETE FROM force_starts WHERE token = ?').run(row.token);
104
+ }
105
+ return undefined;
106
+ }
107
+
108
+ export function readActiveForceReleaseRun(version: string, ledgerRoot: string): ActiveReleaseRun | undefined {
109
+ const db = claimDb(ledgerRoot);
110
+ try {
111
+ const row = liveForceStart(db, version);
112
+ return row && { runId: 'pending', pid: row.pid, startedAt: row.started_at };
113
+ } finally { db.close(); }
114
+ }
115
+
116
+ /** Force runs bypass refusal but publish a claim before launching so later normal runs refuse. */
117
+ export async function withForceReleaseRunMarker<T>(version: string, ledgerRoot: string, run: () => Promise<T>): Promise<T> {
118
+ const db = claimDb(ledgerRoot);
119
+ const token = randomUUID();
120
+ try {
121
+ db.exec('BEGIN IMMEDIATE');
122
+ try {
123
+ const pidStartedAt = psProcessStartMs(process.pid) ?? Date.now() - process.uptime() * 1000;
124
+ db.query('INSERT INTO force_starts (token, version, pid, pid_started_at, started_at) VALUES (?, ?, ?, ?, ?)')
125
+ .run(token, version, process.pid, new Date(pidStartedAt).toISOString(), new Date().toISOString());
126
+ db.exec('COMMIT');
127
+ } catch (error) { db.exec('ROLLBACK'); throw error; }
128
+ return await run();
129
+ } finally {
130
+ db.query('DELETE FROM force_starts WHERE token = ?').run(token);
131
+ db.close();
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Atomic claim closes the gap before the graph's first saved state. SQLite serializes
137
+ * stale-lock reclamation among direct entrants; a scheduled entrant only uses O_EXCL,
138
+ * so it either wins after removal or sees the direct entrant's new file.
139
+ */
140
+ export async function withDirectReleaseRunLock<T>(version: string, ledgerRoot: string, run: () => Promise<T>,
141
+ owner: { pid?: number; now?: () => Date } = {}): Promise<T> {
142
+ const dir = join(ledgerRoot, 'release', version);
143
+ mkdirSync(dir, { recursive: true });
144
+ const lock = join(dir, 'run.lock');
145
+ const db = claimDb(ledgerRoot);
146
+ const token = randomUUID();
147
+ let fd: number | undefined;
148
+ try {
149
+ db.exec('BEGIN IMMEDIATE');
150
+ try {
151
+ if (liveForceStart(db, version)) {
152
+ throw new ReleaseRunClaimConflict();
153
+ }
154
+ const existing = readReleaseRunLock(version, ledgerRoot);
155
+ if (existing?.pid && !releaseRunLockOwnerAlive(version, ledgerRoot, existing.pid)) rmSync(lock, { force: true });
156
+ fd = openSync(lock, 'wx', 0o600);
157
+ const pid = owner.pid ?? process.pid;
158
+ const pidStartedAt = psProcessStartMs(pid) ?? Date.now() - process.uptime() * 1000;
159
+ writeFileSync(fd, `${JSON.stringify({ pid, pidStartedAt: new Date(pidStartedAt).toISOString(), startedAt: (owner.now ?? (() => new Date()))().toISOString(), token })}\n`);
160
+ db.exec('COMMIT');
161
+ } catch (error) {
162
+ if (fd !== undefined) { closeSync(fd); rmSync(lock, { force: true }); fd = undefined; }
163
+ db.exec('ROLLBACK');
164
+ if ((error as NodeJS.ErrnoException).code === 'EEXIST') throw new ReleaseRunClaimConflict();
165
+ throw error;
166
+ }
167
+ } finally { db.close(); }
168
+ try { return await run(); }
169
+ finally {
170
+ if (fd !== undefined) closeSync(fd);
171
+ try {
172
+ const current = JSON.parse(readFileSync(lock, 'utf8')) as { token?: unknown };
173
+ if (current.token === token) rmSync(lock);
174
+ } catch (error) {
175
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
176
+ }
177
+ }
178
+ }
@@ -3,6 +3,7 @@ import { existsSync, lstatSync, readFileSync, realpathSync, statSync } from 'nod
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join, relative, sep } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
+ import { LAST_SESSION_FILE } from '../dashboard/seat-local-instructions.js';
6
7
  import { redactSecretText } from '../debug/log.js';
7
8
  import { defaultMsgStorePath, readUnreadCount } from '../msg/msg-store.js';
8
9
  import { parseKnowhowItems, splitKnowhow } from '../seat-loop/seat-knowhow.js';
@@ -96,6 +97,40 @@ export function renderSeatBootCard(seat: string, sections: ReadonlyArray<SeatBoo
96
97
  return out.join('\n');
97
98
  }
98
99
 
100
+ /** 자리의 현재 역할 선언 한 줄만 부트 카드에 싣는다. 긴 지시문 본문은 카드로 복사하지 않는다. */
101
+ function seatRoleSection(home: string, seat: string): { source: string; updated: string; rows: readonly string[]; reason?: string } {
102
+ const root = join(home, 'elanous-hq');
103
+ const path = join(root, 'seats', seat, 'AGENTS.local.md');
104
+ if (!existsSync(path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 파일 없음' };
105
+ try {
106
+ if (!isRegularSeatPath(home, root, path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 일반 경로가 아님' };
107
+ const role = readFileSync(path, 'utf8').slice(0, 4096).split(/\r?\n/)
108
+ .map(line => line.match(/^\s*#?\s*역할\s*=\s*(.+)$/)?.[1])
109
+ .find(Boolean);
110
+ return { source: path, updated: statSync(path).mtime.toISOString(), rows: role ? [`역할: ${clean(role)}`] : [],
111
+ ...(role ? {} : { reason: '미관측: 역할 선언 없음' }) };
112
+ } catch {
113
+ return { source: path, updated: '미상', rows: [], reason: '미관측: 읽기 실패' };
114
+ }
115
+ }
116
+
117
+ /** «지난 세션» 절 — TUI 가 대화 끝마다 자리 작업 디렉터리 루트에 갈아 쓰는 `LAST_SESSION_FILE`(`dashboard/seat-local-instructions.ts`)이 곧 지난 세션의 정본이다.
118
+ * 카드도 같은 정본을 읽는다 — 머리 보일러플레이트(`## …`)는 빼고 요약 줄만 실는다. */
119
+ function lastSessionSection(home: string, seat: string): { source: string; updated: string; rows: readonly string[]; reason?: string } {
120
+ const path = join(home, 'elanous-hq', 'seats', seat, LAST_SESSION_FILE);
121
+ if (!existsSync(path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 파일 없음' };
122
+ try {
123
+ if (!isRegularSeatPath(home, join(home, 'elanous-hq'), path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 일반 경로가 아님' };
124
+ const rows = readFileSync(path, 'utf8').slice(0, 256_000).split(/\r?\n/)
125
+ .filter(line => line.trim() && !/^#{1,6}\s/.test(line))
126
+ .slice(0, MAX_ROWS)
127
+ .map(line => clean(line.replace(/^[-*]\s*/, '')));
128
+ return { source: path, updated: statSync(path).mtime.toISOString(), rows, ...(rows.length ? {} : { reason: '미관측: 요약 줄 없음' }) };
129
+ } catch {
130
+ return { source: path, updated: '미상', rows: [], reason: '미관측: 읽기 실패' };
131
+ }
132
+ }
133
+
99
134
  /** 자리 카드의 파일·우편 절(동기) — `eln seat boot` 와 TUI 세션 부트(`dashboard/seat-boot-preamble.ts`)가 같이 쓴다. */
100
135
  export function collectSeatBootSections(seat: string, options: { home: string; msgPath: string }): { sections: SeatBootSection[]; unread: number | null } {
101
136
  const root = join(options.home, 'elanous-hq', 'seat-state');
@@ -104,11 +139,13 @@ export function collectSeatBootSections(seat: string, options: { home: string; m
104
139
  try { unread = readUnreadCount(seat, options.msgPath); }
105
140
  catch { /* unavailable is not a measured zero */ }
106
141
  const sections: SeatBootSection[] = [
142
+ { title: '자리 역할', ...seatRoleSection(options.home, seat) },
107
143
  { title: 'msg 원장', source: options.msgPath, updated: unread === null ? '미상' : new Date().toISOString(), rows: [`안 읽은 msg ${unread ?? '미관측'} (${seat})`] },
108
144
  { title: 'HANDOFF', ...metadata(options.home, root, join(seatDir, 'HANDOFF.md'), 'markdown') },
109
145
  { title: 'inbox', ...metadata(options.home, root, join(seatDir, 'inbox.md'), 'markdown') },
110
146
  { title: '수확 주장', ...metadata(options.home, root, join(seatDir, 'harvest-claims.tsv'), 'tsv') },
111
147
  { title: '예약', ...metadata(options.home, root, join(seatDir, 'scheduled.tsv'), 'tsv') },
148
+ { title: '지난 세션', ...lastSessionSection(options.home, seat) },
112
149
  { title: '공통 메모리 색인', ...metadata(options.home, root, join(root, 'memory', 'MEMORY.md'), 'memory') },
113
150
  ];
114
151
  return { sections, unread };
@@ -182,10 +182,47 @@ function reportCliSkills(deps: SetupCliDeps, apply: boolean): string[] {
182
182
  return lines;
183
183
  }
184
184
 
185
+ /** 최초 셋업 묶음 제안(읽기 전용). 등급·승인 어휘는 문서 원전을 그대로 쓴다 —
186
+ * 묶음·층 구성 = 내부 문서 `RESEARCH-plugins-connectors-baseline-2026-09-30` §4(0층 «키 없이 항상 켬»),
187
+ * 항목별 보안 등급·승인 = 같은 문서 §5. §5 표에 등급이 없는 0층 항목(Edge/macOS TTS·스킬)은
188
+ * 등급을 지어내지 않기 위해 목록에서 뺀다. 실제 설치·자격 부여는 승인 뒤 후속 조각(plan-then-apply). */
189
+ interface SetupBundleItem {
190
+ name: string;
191
+ grade: string;
192
+ approval: string;
193
+ }
194
+
195
+ const DEFAULT_SETUP_BUNDLE: readonly SetupBundleItem[] = [
196
+ { name: '셸·파일(작업 트리 안)', grade: '쓰기(로컬)', approval: '기존 모래상자·워크트리 규칙' },
197
+ { name: 'WebFetch', grade: '읽기', approval: '불요' },
198
+ { name: 'WebSearch(무료 DuckDuckGo·Jina)', grade: '읽기', approval: '불요' },
199
+ { name: 'GitHub 공개 읽기(무인증)', grade: '읽기', approval: '불요' },
200
+ { name: 'PDF/HWP 읽기', grade: '읽기', approval: '불요' },
201
+ { name: '비전', grade: '읽기', approval: '불요' },
202
+ { name: 'Obsidian 검색', grade: '읽기', approval: '불요' },
203
+ { name: 'Obsidian 쓰기', grade: '쓰기(로컬)', approval: 'vault-write-guard' },
204
+ { name: '기억·일정', grade: '쓰기(로컬)', approval: '기존 모래상자·워크트리 규칙' },
205
+ { name: 'CDP 브라우저 탐색·읽기', grade: '읽기(네트워크)', approval: '불요(클릭·입력은 쓰기 → 승인)' },
206
+ ];
207
+
208
+ function formatDefaultBundleProposal(): string[] {
209
+ return [
210
+ 'Setup: 기본 플러그인·커넥터 묶음 제안 (읽기 전용)',
211
+ `묶음 1/1: 기본 묶음 — 키 없이 항상 켬(0층) · 항목 ${DEFAULT_SETUP_BUNDLE.length}개`,
212
+ ...DEFAULT_SETUP_BUNDLE.map((item) => `- ${item.name} — 보안 등급: ${item.grade} · 승인: ${item.approval}`),
213
+ '후속 층(승인 뒤 조각): 1층 로그인된 CLI 재사용 · 2층 원격 MCP 한 번 OAuth · 3층 채널',
214
+ '제안은 표시만 합니다 — 승인 전 설치 0 · 자격 쓰기 0 · 승인 뒤 설치는 `elanous plugin add <spec>` 경로로(후속 조각)',
215
+ ];
216
+ }
217
+
185
218
  export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}): void {
186
219
  const out = deps.out ?? { log: (value: string) => console.log(value), error: (value: string) => console.error(value) };
187
220
  const setExitCode = deps.setExitCode ?? ((code: number) => { process.exitCode = code; });
188
221
  const doctorRunner = deps.runDoctor ?? runDoctor;
222
+ const isFirstRunSetup = (): boolean => deps.firstRunTopics ?? (!deps.getUserConfig && !existsSync(userConfigPath()));
223
+ const showDefaultBundleProposal = (): void => {
224
+ for (const line of formatDefaultBundleProposal()) out.log(line);
225
+ };
189
226
  const showCliSkills = (apply: boolean) => {
190
227
  out.log('Setup: CLI skills (public GitHub repository reads remain available without login)');
191
228
  for (const line of reportCliSkills(deps, apply)) out.log(line);
@@ -206,6 +243,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
206
243
  if (opts.nonInteractive) {
207
244
  out.log(formatSetupReport(doctor, setupSteps(deps), true));
208
245
  showCliSkills(false);
246
+ if (isFirstRunSetup()) showDefaultBundleProposal();
209
247
  for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
210
248
  setExitCode(0);
211
249
  return;
@@ -215,7 +253,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
215
253
  setExitCode(1);
216
254
  return;
217
255
  }
218
- const isFirstRun = deps.firstRunTopics ?? (!deps.getUserConfig && !existsSync(userConfigPath()));
256
+ const isFirstRun = isFirstRunSetup();
219
257
  let steps = setupSteps(deps);
220
258
  const provider = steps[1]!;
221
259
  if (!provider.complete) {
@@ -230,6 +268,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
230
268
  }
231
269
  out.log(formatSetupReport(doctor, steps, false));
232
270
  showCliSkills(false);
271
+ if (isFirstRun) showDefaultBundleProposal();
233
272
  for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
234
273
  let configured = (deps.getUserConfig ?? getUserConfig)();
235
274
  if (!configured.starter?.topics && configured.watch?.enabled !== false
@@ -0,0 +1,18 @@
1
+ import type { Command } from 'commander';
2
+ import { runScenarioFile } from '../ux-sim/scenario.js';
3
+
4
+ export function registerSimCommands(program: Command): void {
5
+ const sim = program.command('sim').description('격리 시나리오를 실행하고 화면·로그 기대값을 대조한다');
6
+ sim.command('run <scenario-file>')
7
+ .description('등록된 UX simulation 시나리오를 test 우주에서 실행한다')
8
+ .action(async (scenarioFile: string) => {
9
+ try {
10
+ const result = await runScenarioFile(scenarioFile);
11
+ console.log(JSON.stringify(result));
12
+ if (!result.pass) process.exitCode = 1;
13
+ } catch (error) {
14
+ console.error(`sim run: ${error instanceof Error ? error.message : String(error)}`);
15
+ process.exitCode = 2;
16
+ }
17
+ });
18
+ }
@@ -162,10 +162,17 @@ export interface DefaultTaskLauncherDeps {
162
162
  launchHoldActive?: () => boolean;
163
163
  /** HQ 판(시험 주입). */
164
164
  localVersion?: string;
165
+ /** HQ-owned, refresh-less Codex access mirror to install before a remote parent launch. */
166
+ codexAccessMirror?: () => Promise<{ elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number } | null>;
167
+ /** Isolated integration seam; production still reads the HQ rotation snapshot and config directly. */
168
+ ownerCodexRotation?: () => ReturnType<typeof import('../oauth/codex-account-store.js').inspectCodexRotation>;
169
+ ownerCodexRotationConfig?: { accountOrder?: readonly string[]; thresholdPercentByAccount?: Readonly<Record<string, unknown>> };
165
170
  /** 원격 → 로컬 되돌림 알림(시험 주입). 기본 = stderr 한 줄. */
166
171
  notice?: (line: string) => void;
167
172
  }
168
173
 
174
+ class NoEligibleOwnerCodexAccountError extends Error {}
175
+
169
176
  /**
170
177
  * HARNESS-PARENT-ON-MSB1 — 켜져 있고 발사 전 점검이 통과하면 원격(ssh)에서 부모를 띄운다(PR 까지만 · 병합은 HQ).
171
178
  * 막히면 null — 호출부가 종전 로컬 발사로 간다(관측: task-agent parent-host-fallback).
@@ -185,6 +192,52 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
185
192
  try { debug.log('task-agent', 'parent-host-fallback', { host: target.host, runId: context.runId, gaps, facts }); } catch { /* fail-soft */ }
186
193
  notice(`[parent-host] ${target.host} 로 못 띄움 — ${multi ? '다음 호스트 또는 로컬 발사로 간다' : '로컬 발사로 간다'}: ${gaps.join(' · ')}`);
187
194
  };
195
+ let accessMirror: { elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number } | null | undefined;
196
+ const getAccessMirror = async (): Promise<{ elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number } | null> => {
197
+ if (accessMirror !== undefined) return accessMirror;
198
+ if (deps.codexAccessMirror) {
199
+ accessMirror = await deps.codexAccessMirror();
200
+ return accessMirror;
201
+ }
202
+ const [pod, authStore, codex, hq] = await Promise.all([
203
+ import('../task-orchestrator/surfaces/self-implement-pod.js'),
204
+ import('../oauth/store.js'),
205
+ import('../oauth/codex.js'),
206
+ import('../hq/hq.js'),
207
+ ]);
208
+ const { inspectCodexRotation } = await import('../oauth/codex-account-store.js');
209
+ const { planOwnerCodexMirrorCandidates, podAccountThresholdPercent } = await import('../task-orchestrator/surfaces/pod-account-broker.js');
210
+ const { getUserConfig } = await import('../user-config.js');
211
+ const rotation = deps.ownerCodexRotation?.() ?? inspectCodexRotation();
212
+ const config = getUserConfig();
213
+ const ownerConfig = deps.ownerCodexRotationConfig;
214
+ const candidates = [...rotation.candidates];
215
+ const eligible = planOwnerCodexMirrorCandidates(candidates, {
216
+ accountOrder: ownerConfig?.accountOrder ?? config.llm?.codexAccountOrder ?? [],
217
+ thresholdPercentByAccount: ownerConfig?.thresholdPercentByAccount ?? config.llm?.codexAccountRotationThresholdPercentByAccount,
218
+ });
219
+ if (candidates.length > 0 && eligible.length === 0) throw new NoEligibleOwnerCodexAccountError('HQ 소유 Codex 계정이 모두 사용 임계에 도달해 원격 부모 발사를 거부한다');
220
+ const prerefreshDeps = {
221
+ credentials: (account: string) => pod.hostCredentials(account, authStore.authStorePath(), () => '', { requireExplicitChatgptAuthMode: true }),
222
+ refresh: (account: string) => codex.refreshCodexAccountHome(account),
223
+ isLeaseHolder: () => hq.hqFenceDecision('ledger-cli').run,
224
+ };
225
+ for (const candidate of eligible) {
226
+ // The account's refresh token stays on HQ. Only the selected account's access-only mirror crosses SSH.
227
+ let credential: Awaited<ReturnType<typeof pod.podCodexCredentialWithPrerefresh>> = null;
228
+ try { credential = await pod.podCodexCredentialWithPrerefresh(candidate.name, prerefreshDeps); }
229
+ catch { continue; }
230
+ if (!credential) continue;
231
+ accessMirror = { elanousAuth: credential.elanousAuth, codexAuth: credential.codexAuth, account: candidate.name,
232
+ ...(candidate.usedPercent !== undefined ? { usedPercent: candidate.usedPercent } : {}),
233
+ thresholdPercent: podAccountThresholdPercent(candidate.name, {
234
+ thresholdPercentByAccount: ownerConfig?.thresholdPercentByAccount ?? config.llm?.codexAccountRotationThresholdPercentByAccount,
235
+ }) };
236
+ return accessMirror;
237
+ }
238
+ accessMirror = null;
239
+ return accessMirror;
240
+ };
188
241
  if (cwd) {
189
242
  failed(targets[0]!, ['project-target-is-local']);
190
243
  return null;
@@ -204,8 +257,37 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
204
257
  launchHoldActive = readLandingFreeze(prodInstanceRoot())?.holdLaunches === true;
205
258
  }
206
259
  } catch { launchHoldActive = true; /* 못 읽으면 막힌 것으로(fail-closed) */ }
207
- const capacities = Object.fromEntries(multi ? targets.map((target) => [target.host, parentHostModule.readParentHostCapacity(target, deps.ssh)]) : []);
208
- const ordered = multi ? parentHostModule.orderParentHosts(targets, context.runId, capacities) : targets;
260
+ const podGoal = context.substrate === 'pod' ? context.podGoal : undefined;
261
+ // 부모에서 잰 메모리 선택자만 원격 자식에도 넘긴다. 로컬의 나머지 환경·자격은 SSH 로 복사하지 않는다.
262
+ const remoteEnv = { ...context.env };
263
+ // These labels describe an HQ-selected Codex access mirror; never forward an inherited label by itself.
264
+ delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT;
265
+ delete remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT;
266
+ delete remoteEnv.ELANOUS_REMOTE_CODEX_THRESHOLD_PERCENT;
267
+ if (podGoal) for (const key of ['ELANOUS_POD_MEMORY_TIER', 'ELANOUS_POD_MEMORY', 'ELANOUS_POD_MEMORY_HIGH', 'ELANOUS_POD_MEMORY_LITE', 'ELANOUS_POD_GOAL_TYPE'] as const) {
268
+ const value = context.env[key] ?? process.env[key];
269
+ if (value !== undefined) remoteEnv[key] = value;
270
+ }
271
+ const memoryLimit = podGoal ? (await import('../task-orchestrator/surfaces/self-implement-pod.js')).podMemoryLimitFor(podGoal, remoteEnv).limit : undefined;
272
+ const fits = Object.fromEntries(targets.map((target) => {
273
+ const fit = memoryLimit
274
+ ? parentHostModule.readParentHostPodFit(target, memoryLimit, deps.ssh)
275
+ : { state: 'unmeasured' as const, memoryLimit: '', requiredBytes: null, allocatableBytes: null, reason: 'pod-context-unmeasured' };
276
+ try { debug.log('task-agent.parent-host', 'pod-fit', { host: target.host, runId: context.runId, ...fit }); } catch { /* fail-soft */ }
277
+ if (fit.state === 'never-fits') notice(`[parent-host] ${target.host} 제외 — ${fit.reason}: Pod ${fit.memoryLimit} (${fit.requiredBytes} bytes) > node allocatable ${fit.allocatableBytes} bytes`);
278
+ return [target.host, fit];
279
+ }));
280
+ const eligible = targets.filter((target) => fits[target.host]?.state !== 'never-fits');
281
+ if (!eligible.length) {
282
+ const details = targets.map((target) => `${target.host}: Pod ${fits[target.host]!.memoryLimit} (${fits[target.host]!.requiredBytes} bytes) > node allocatable ${fits[target.host]!.allocatableBytes} bytes`).join(' · ');
283
+ throw new Error(`parent-host memory-never-fits — ${details}; local fallback refused`);
284
+ }
285
+ const capacities = Object.fromEntries(multi ? eligible.map((target) => [target.host, parentHostModule.readParentHostCapacity(target, deps.ssh)]) : []);
286
+ const measured = eligible.filter((target) => fits[target.host]?.state === 'fits');
287
+ const unknown = eligible.filter((target) => fits[target.host]?.state !== 'fits');
288
+ const ordered = multi
289
+ ? [...parentHostModule.orderParentHosts(measured, context.runId, capacities), ...parentHostModule.orderParentHosts(unknown, context.runId, capacities)]
290
+ : eligible;
209
291
  for (const target of ordered) {
210
292
  if (multi && (!capacities[target.host] || capacities[target.host]!.approvalHeadroom <= 0)) {
211
293
  failed(target, ['capacity-unavailable']);
@@ -217,7 +299,27 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
217
299
  if (!preflight.ok) { failed(target, preflight.gaps, preflight.facts); continue; }
218
300
  if (preflight.warnings.length) notice(`⚠ ${target.host} 자격: ${preflight.warnings.join(' · ')}`);
219
301
  try {
220
- const launched = parentHostModule.launchRemoteParent(target, args, context.env, deps.ssh);
302
+ if (parentHostModule.shouldInstallRemoteCodexAccess(context.effectiveChildProvider)) {
303
+ let mirror: { elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number } | null = null;
304
+ let mirrorReason = 'credential-source-empty';
305
+ try { mirror = await getAccessMirror(); }
306
+ catch (error) {
307
+ if (error instanceof NoEligibleOwnerCodexAccountError) throw error;
308
+ mirrorReason = 'credential-source-error';
309
+ }
310
+ if (mirror) parentHostModule.installRemoteCodexAccess(target, mirror, deps.ssh);
311
+ else {
312
+ try { debug.log('task-agent.parent-host', 'codex-access-mirror-unavailable', { host: target.host, runId: context.runId, reason: mirrorReason }); } catch { /* fail-soft */ }
313
+ failed(target, ['codex-access-mirror-unavailable']);
314
+ return null;
315
+ }
316
+ if (mirror.account) {
317
+ remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT = mirror.account;
318
+ remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT = mirror.usedPercent === undefined ? 'unknown' : String(mirror.usedPercent);
319
+ if (mirror.thresholdPercent !== undefined) remoteEnv.ELANOUS_REMOTE_CODEX_THRESHOLD_PERCENT = String(mirror.thresholdPercent);
320
+ }
321
+ }
322
+ const launched = parentHostModule.launchRemoteParent(target, args, remoteEnv, deps.ssh);
221
323
  try { debug.log('task-agent', 'parent-host-launched', { host: target.host, runId: context.runId, pid: launched.pid, log: launched.log }); } catch { /* fail-soft */ }
222
324
  return { runId: context.runId, parentHost: { host: target.host, ...(target.configDir ? { configDir: target.configDir } : {}), pid: launched.pid, log: launched.log } };
223
325
  } catch (error) {
@@ -398,6 +500,7 @@ function taskCardLines(card: TaskCard): string[] {
398
500
  return [
399
501
  [card.id, card.status, card.seat ?? '-', card.checklistId ?? '-', card.createdAt, card.text].join('\t'),
400
502
  ...cardIdentityLines(card),
503
+ ...(card.targetPaths !== undefined ? [`대상 경로: ${card.targetPaths.length ? card.targetPaths.join(' · ') : '(유효한 경로 없음)'}`] : []),
401
504
  ...(card.mission ? [`미션: ${card.mission} · after: ${card.after?.length ? card.after.join(', ') : '-'}`] : []),
402
505
  ...runLinkLine(card),
403
506
  ...liveMoveLines(card),
@@ -1578,7 +1681,45 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
1578
1681
  : {});
1579
1682
  try { debug.log('task-agent', 'remote-rejudge-bind', binding); } catch { /* fail-soft */ }
1580
1683
  }
1581
- ids = id ? [id] : rejudgeCandidates(readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {});
1684
+ if (id) ids = [id];
1685
+ else {
1686
+ const maxAgeHours = (await import('../user-config.js')).getUserConfig().taskAgent?.rejudgeMaxAgeHours ?? 72;
1687
+ const cards = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {};
1688
+ const candidates = rejudgeCandidates(cards, { maxAgeHours, onAgeSkip: (card, ageHours) => {
1689
+ try { debug.log('task-agent', 'rejudge-age-skip', { card: card.id, ageHours, maxAgeHours }); } catch { /* fail-soft */ }
1690
+ } });
1691
+ const { capturedLandReview } = await import('../task-agent/review-result-capture.js');
1692
+ const { defaultPrHead, defaultReviewRepoCandidates } = await import('../task-agent/live-moves.js');
1693
+ const currentHeads = new Map<string, string>();
1694
+ // Priority is a hint, not a gate. Consider only the three newest candidates;
1695
+ // a non-mf0 card still consumes one of those three places. Everyone else runs in age order.
1696
+ const priorityCandidates = candidates.slice(0, 3);
1697
+ let headProbes = 0;
1698
+ for (const cardId of priorityCandidates) {
1699
+ const card = cards[cardId];
1700
+ if (!card || typeof card.pr !== 'object' || !card.pr?.url) continue;
1701
+ const pr = card.pr.number;
1702
+ const lastHead = card.reviewRequests?.filter((entry) => entry.pr === pr).at(-1)?.head;
1703
+ if (!lastHead || capturedLandReview(card, pr, lastHead)?.mustFixCount !== 0) continue;
1704
+ let repos: readonly import('../task-agent/live-moves.js').ReviewRepoCandidate[] = [];
1705
+ try { repos = (deps.rejudge?.live?.repoCandidates ?? defaultReviewRepoCandidates)(card); } catch { /* no trusted repo */ }
1706
+ const repo = repos[0];
1707
+ if (!repo) continue;
1708
+ headProbes++;
1709
+ let view: Awaited<ReturnType<typeof defaultPrHead>>;
1710
+ try { view = await (deps.rejudge?.live?.prHead
1711
+ ? deps.rejudge.live.prHead(pr, repo.cwd)
1712
+ : defaultPrHead(pr, repo.cwd, (args, options) => spawnSync('gh', args, {
1713
+ encoding: 'utf8', timeout: 3_000, env: options.env, ...(options.cwd ? { cwd: options.cwd } : {}),
1714
+ }))); } catch { view = null; }
1715
+ if (view?.state === 'OPEN' && view.url === card.pr.url) currentHeads.set(cardId, view.head);
1716
+ }
1717
+ if (candidates.length > priorityCandidates.length) {
1718
+ try { debug.log('task-agent', 'rejudge-head-priority-probe-cap', { considered: priorityCandidates.length,
1719
+ probed: headProbes, totalCandidates: candidates.length, max: 3 }); } catch { /* fail-soft */ }
1720
+ }
1721
+ ids = rejudgeCandidates(cards, { maxAgeHours, currentHeads });
1722
+ }
1582
1723
  } catch (error) {
1583
1724
  out(error instanceof Error ? error.message : '과제 카드 읽기 실패'); process.exitCode = 1; return;
1584
1725
  }
@@ -1586,6 +1727,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
1586
1727
  const liveMoves = deps.rejudge?.liveMoves ?? await configuredTaskAgentLiveMoves();
1587
1728
  const repairBudget = opts.all ? { max: (await import('../user-config.js')).getUserConfig().taskAgent?.repairMaxPerTick ?? 3,
1588
1729
  requested: 0, capped: 0 } : undefined;
1730
+ const reviewBudget = opts.all ? { max: 1, requested: 0 } : undefined;
1731
+ const landBudget = opts.all ? { max: 1, requested: 0 } : undefined;
1589
1732
  const all = [];
1590
1733
  for (const cardId of ids) {
1591
1734
  await mirrorRemoteCardLedger(cardId, deps);
@@ -1594,7 +1737,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
1594
1737
  }
1595
1738
  let outcomes: Awaited<ReturnType<typeof rejudgeCardOnHead>>;
1596
1739
  try { outcomes = await rejudgeCardOnHead(cardId, { ...deps.rejudge, liveMoves,
1597
- ...(repairBudget ? { repairBudget } : {}), live: { ...deps.rejudge?.live, statePath } }); } catch (error) {
1740
+ ...(repairBudget ? { repairBudget } : {}), ...(reviewBudget ? { reviewBudget } : {}), ...(landBudget ? { landBudget } : {}),
1741
+ live: { ...deps.rejudge?.live, statePath } }); } catch (error) {
1598
1742
  // 카드 하나의 예외가 --all 의 나머지 카드 판단을 멈추지 않게 — 사유를 남기고 다음 카드로.
1599
1743
  const reason = (error instanceof Error ? error.message : String(error)).slice(-300);
1600
1744
  try { debug.log('task-agent', 'rejudge-on-head', { card: cardId, pr: null, fromHead: null, toHead: null, step: 'target', decision: 'rejudge-threw', reason }, { level: 'warn' }); } catch { /* fail-soft */ }