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.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
- package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
- package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
- package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
- package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
- package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
- package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
- package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
- package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
- package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
- package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-0a07363b130182a1.js → page-398c0faa173203f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
- package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +1 -0
- package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +26 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/bin/elanous.mjs +9 -2
- package/docs/goal-context/README.md +1 -0
- package/graphs/default-loop.yaml +20 -3
- package/graphs/document-loop.yaml +21 -2
- package/graphs/implement-loop.yaml +11 -0
- package/graphs/journey/SCENARIOS.md +33 -0
- package/graphs/journey/recipes.yaml +1 -0
- package/graphs/journey/ta-journey.yaml +84 -0
- package/graphs/journey/units/author/author.yaml +20 -0
- package/graphs/journey/units/author/recipes.yaml +2 -0
- package/graphs/journey/units/green/green.yaml +20 -0
- package/graphs/journey/units/green/recipes.yaml +2 -0
- package/graphs/journey/units/pr/pr.yaml +20 -0
- package/graphs/journey/units/pr/recipes.yaml +2 -0
- package/graphs/journey/units/remember/recipes.yaml +2 -0
- package/graphs/journey/units/remember/remember.yaml +20 -0
- package/graphs/operate-loop.yaml +21 -2
- package/graphs/overlays/stop-heal-ladder.yaml +1 -1
- package/graphs/release-rehearsal/recipes.yaml +1 -1
- package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
- package/graphs/research-loop.yaml +23 -2
- package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
- package/graphs/units/dispatch-pod/recipes.yaml +14 -0
- package/graphs/units/entry/entry.yaml +50 -0
- package/graphs/units/entry/recipes.yaml +14 -0
- package/graphs/units/harvest/harvest.yaml +25 -0
- package/graphs/units/harvest/recipes.yaml +4 -0
- package/graphs/units/land/land.yaml +45 -0
- package/graphs/units/land/recipes.yaml +3 -0
- package/graphs/units/recipes.yaml +7 -0
- package/graphs/units/recover.yaml +39 -0
- package/graphs/units/reflect/recipes.yaml +3 -0
- package/graphs/units/reflect/reflect.yaml +15 -0
- package/graphs/units/task-agent-recover-review.yaml +17 -0
- package/graphs/units/task-agent-recover-wait.yaml +17 -0
- package/graphs/units/verbs/make-doc.yaml +34 -0
- package/graphs/units/verbs/recipes.yaml +33 -0
- package/graphs/units/verbs/verify.yaml +55 -0
- package/graphs/work/recipes.yaml +2 -0
- package/graphs/work/research-report.yaml +28 -0
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +95 -17
- package/scripts/docs/generate-graph-anatomy.ts +19 -2
- package/scripts/graph-harvest-unit.ts +22 -0
- package/scripts/graph-units/journey-stub.ts +6 -0
- package/scripts/graph-units/land-enqueue.ts +78 -0
- package/scripts/graph-units/recover-plan.ts +15 -0
- package/scripts/graph-units/reflect-node.ts +88 -0
- package/scripts/graph-units/ta-journey-observe.ts +109 -0
- package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
- package/scripts/graph-units/verbs/verify-stage.ts +75 -0
- package/scripts/graph-units/verbs-envelope.ts +139 -0
- package/scripts/hq/standby-snapshot.ts +25 -0
- package/scripts/measure-si-task-cpu.ts +143 -0
- package/scripts/public-export.ts +43 -1
- package/scripts/ratchets/test-interference-patterns.allowlist.txt +0 -2
- package/scripts/ratchets/train-side-invariants.sh +45 -0
- package/scripts/release-loop/auto-approve-node.ts +30 -16
- package/scripts/release-loop/gate-closure.ts +5 -1
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-node.ts +498 -31
- package/scripts/release-loop/gate-partial.ts +3 -3
- package/scripts/release-loop/gate-radius-shadow.ts +138 -0
- package/scripts/release-loop/gate-traffic-mode.ts +128 -0
- package/scripts/release-loop/gate-triage-node.ts +5 -2
- package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
- package/scripts/release-loop/known-issues-node.ts +77 -8
- package/scripts/release-loop/preflight.ts +93 -7
- package/scripts/release-loop/prepare-node.ts +102 -4
- package/scripts/release-loop/publish-node.ts +60 -9
- package/scripts/release-loop/resume-cap.ts +56 -0
- package/scripts/release-loop/resume-release.ts +114 -15
- package/scripts/release-loop/resume.ts +24 -1
- package/scripts/release-loop/tui-sim-node.ts +8 -2
- package/scripts/release-loop/unattended-release.ts +8 -2
- package/src/acp/core-turn-bridge.ts +36 -9
- package/src/acp/elanous-extensions.ts +3 -0
- package/src/acp/reasoning-thought-buffer.ts +45 -0
- package/src/acp/server.ts +3 -0
- package/src/acp/tool-trace.ts +186 -11
- package/src/agent/self-ambient-cache.ts +156 -0
- package/src/agent/self-ambient.ts +8 -1
- package/src/agent/task-notification.ts +5 -0
- package/src/agent-substrate/acp-reviewer.ts +52 -12
- package/src/agent-substrate/pr-reviewer.ts +3 -1
- package/src/agent-substrate/review-finding-key.ts +53 -0
- package/src/agent-substrate/self-review-cli.ts +126 -5
- package/src/ask-user-question/pending-questions.ts +1 -1
- package/src/ask-user-question/tool.ts +22 -0
- package/src/autopilot/build/llm-conflict-merge.ts +56 -10
- package/src/autopilot/pr-manager.ts +213 -46
- package/src/capture/frame-state-detect.ts +39 -0
- package/src/capture/tui-self-report.ts +134 -6
- package/src/chat/index.ts +61 -15
- package/src/chat/pickers/modal-runtime.ts +6 -0
- package/src/chat/pickers/modals.ts +8 -2
- package/src/chat/tool-render/dispatch.ts +62 -10
- package/src/cli/ask-bare.ts +1 -0
- package/src/cli/control-cli.ts +24 -7
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/import-cli.ts +12 -0
- package/src/cli/light-entry-route.ts +35 -0
- package/src/cli/llm-detect-cli.ts +23 -1
- package/src/cli/log-event-names.ts +10 -0
- package/src/cli/msg-cli.ts +1 -0
- package/src/cli/pod-cli.ts +14 -3
- package/src/cli/pr-cli.ts +140 -41
- package/src/cli/pr-land-base-read.ts +36 -0
- package/src/cli/pr-land-heavy-remote.ts +81 -25
- package/src/cli/pr-land-overlap-evidence.ts +200 -18
- package/src/cli/pr-land-pod-shadow-job.ts +26 -3
- package/src/cli/pr-land-recovery.ts +64 -0
- package/src/cli/pr-land-refusal.ts +20 -5
- package/src/cli/pty-takeover-cli.ts +94 -19
- package/src/cli/release-cli.ts +120 -33
- package/src/cli/release-run-if-ready.ts +29 -28
- package/src/cli/release-single-flight.ts +178 -0
- package/src/cli/seat-cli.ts +37 -0
- package/src/cli/setup-cli.ts +40 -1
- package/src/cli/sim-cli.ts +18 -0
- package/src/cli/tasks-cli.ts +149 -5
- package/src/context-bus/ops-events.ts +6 -2
- package/src/control/control-status.ts +8 -3
- package/src/control-plane/ledger.ts +5 -3
- package/src/control-plane/server.ts +5 -3
- package/src/core-turn/run-core-turn.ts +1 -0
- package/src/core-turn/run-goal-loop.ts +21 -0
- package/src/core-turn/short-question.ts +5 -1
- package/src/core-turn/types.ts +3 -0
- package/src/dashboard/acp-active-model.ts +42 -1
- package/src/dashboard/background-jobs-status.ts +66 -0
- package/src/dashboard/index.ts +153 -111
- package/src/dashboard/input/agent-wake.ts +242 -0
- package/src/dashboard/input/chat-main-entry-runtime.ts +5 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/external-input-host.ts +23 -9
- package/src/dashboard/input/mouse-wiring.ts +108 -11
- package/src/dashboard/input/seat-autowake.ts +56 -3
- package/src/dashboard/log-click-runtime.ts +118 -2
- package/src/dashboard/seat-boot-preamble.ts +1 -1
- package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
- package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
- package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
- package/src/dashboard/turn-preamble.ts +163 -41
- package/src/dashboard/turn-session-layers.ts +4 -2
- package/src/dashboard/turn-start-segments.ts +222 -0
- package/src/dashboard/turn-stream-formatter.ts +34 -1
- package/src/dashboard/turn-stream-runtime.ts +2 -0
- package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
- package/src/display/prompt-row-owner.ts +146 -0
- package/src/display/resize-listener.ts +33 -2
- package/src/domains/guardian-tick.ts +54 -2
- package/src/domains/outbound-alert.ts +3 -2
- package/src/extractors.ts +3 -1
- package/src/fold-stack.ts +4 -2
- package/src/git-fs/index.ts +263 -36
- package/src/git-fs/retry.ts +4 -0
- package/src/git-fs/runner.ts +2 -0
- package/src/graph-runner/runner.ts +114 -44
- package/src/grok/credential.ts +5 -0
- package/src/harness/gate-reserve.ts +87 -0
- package/src/harness/harness-cli-command.ts +39 -10
- package/src/harness/harness-incidents.ts +17 -0
- package/src/harness/harness-pod-dispatch.ts +38 -1
- package/src/harness/harness-queue.ts +15 -0
- package/src/harness/harness-salvage-cli.ts +14 -2
- package/src/index.ts +198 -12
- package/src/input/external-input-queue.ts +34 -9
- package/src/intake-plane/already-built-hint.ts +89 -0
- package/src/knowhow/pack.ts +199 -0
- package/src/light-cli.ts +95 -0
- package/src/llm/route-decision.ts +36 -0
- package/src/llm/tool-loop-steered-rejection.ts +8 -0
- package/src/llm-request-shape.ts +209 -0
- package/src/llm.ts +221 -276
- package/src/loops/budget.ts +95 -0
- package/src/loops/msg-wake.ts +8 -2
- package/src/loops/orchestrator/tick.ts +24 -2
- package/src/loops/orchestrator/traffic.ts +132 -1
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/mss/logging/log-store.ts +4 -5
- package/src/mss/logging/render-categories.ts +5 -0
- package/src/nexus/api/graphs-api.ts +22 -3
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +12 -0
- package/src/oauth/claude-pty-maturity.ts +66 -0
- package/src/oauth/codex-access-mirror.ts +55 -0
- package/src/oauth/fallback-chain.ts +1 -1
- package/src/onboarding/first-run.ts +5 -3
- package/src/onboarding/non-interactive.ts +64 -13
- package/src/onboarding.ts +10 -2
- package/src/ops/overview-collect.ts +36 -1
- package/src/ops/overview.ts +70 -2
- package/src/pr-tool/census.ts +41 -8
- package/src/pr-tool/inflight-registry.ts +296 -0
- package/src/prompt-library/gpt6-family-addendum.ts +14 -1
- package/src/pty-shell/herdr-agent-report.ts +442 -0
- package/src/pty-shell/pty-control-ipc.ts +5 -5
- package/src/pty-shell/pty-manifest.ts +12 -3
- package/src/pty-shell/pty-write-outcome.ts +24 -6
- package/src/pty-shell/tui-run-state.ts +151 -6
- package/src/release-loop/checklist.ts +79 -5
- package/src/release-loop/feature-store.ts +19 -2
- package/src/release-loop/placement.ts +10 -3
- package/src/release-loop/rehearsal.ts +205 -25
- package/src/release-loop/rubric.ts +16 -2
- package/src/seat-loop/traffic-signal.ts +2 -1
- package/src/self-dev/ask-launch-flow.ts +13 -0
- package/src/self-dev/draft-residue.ts +243 -24
- package/src/self-dev/draft-sweep.ts +52 -3
- package/src/self-dev/graph-journey-nodes.ts +10 -6
- package/src/self-dev/graph-journey-route.ts +60 -6
- package/src/self-dev/orchestrate.ts +79 -3
- package/src/self-dev/run-supervisor.ts +107 -12
- package/src/self-dev/run-types.ts +5 -1
- package/src/self-dev/shard-plan.ts +11 -3
- package/src/self-dev/shard-run.ts +103 -10
- package/src/self-implement/elanous-tui-spawn.ts +14 -0
- package/src/self-implement/follow-up-placement.ts +79 -0
- package/src/self-implement/gate-artifacts.ts +15 -4
- package/src/self-implement/gate-baseline.ts +145 -10
- package/src/self-implement/gate-cli.ts +7 -2
- package/src/self-implement/gate-remote.ts +35 -6
- package/src/self-implement/goal-author-identity.ts +66 -0
- package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
- package/src/self-implement/goal-author.ts +4 -120
- package/src/self-implement/graph-overlay-yaml.ts +17 -2
- package/src/self-implement/graph-unit-flatten.ts +103 -0
- package/src/self-implement/graph-unit-resolver.ts +107 -0
- package/src/self-implement/graph-yaml.ts +151 -1
- package/src/self-implement/headless-elanous-driver.ts +1 -0
- package/src/self-implement/host-regate.ts +36 -4
- package/src/self-implement/knowhow-pack.ts +103 -0
- package/src/self-implement/orchestrator.ts +109 -11
- package/src/self-implement/pod-warm-pool-profile.ts +45 -0
- package/src/self-implement/review-mustfix-class.ts +203 -0
- package/src/self-implement/run-ledger.ts +16 -14
- package/src/self-implement/run-stop.ts +8 -2
- package/src/self-implement/seams.ts +32 -1
- package/src/self-implement/stop-autoheal.ts +25 -1
- package/src/session/chat.ts +27 -0
- package/src/session-runtime/index.ts +22 -267
- package/src/session-runtime/retry-policy.ts +2 -1
- package/src/shell-runner/background-surface.ts +15 -5
- package/src/skills/tools/agent.ts +39 -6
- package/src/skills/tools/list-dir.ts +11 -0
- package/src/skills/tools/schedule-wakeup.ts +457 -0
- package/src/skills/tools/shell.ts +245 -3
- package/src/status/bar.ts +26 -0
- package/src/steward/digest-delivery.ts +118 -0
- package/src/steward/hold-hygiene.ts +120 -0
- package/src/steward/release-day.ts +7 -3
- package/src/steward/triage.ts +47 -4
- package/src/surface/shell-runner-boot.ts +5 -2
- package/src/task-agent/harvest-unit.ts +141 -0
- package/src/task-agent/live-moves.ts +98 -12
- package/src/task-agent/parent-host.ts +93 -3
- package/src/task-agent/postland-card.ts +80 -1
- package/src/task-agent/rejudge-on-head.ts +112 -26
- package/src/task-agent/repair-branch-cas.ts +4 -1
- package/src/task-agent/repair-cycle.ts +16 -3
- package/src/task-agent/run-identity.ts +4 -3
- package/src/task-agent/shadow.ts +12 -2
- package/src/task-agent/task-hand.ts +76 -5
- package/src/task-agent/work-order-build.ts +22 -0
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +67 -12
- package/src/task-orchestrator/surfaces/pod-lease.ts +98 -0
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
- package/src/task-orchestrator/surfaces/pod-pool.ts +76 -18
- package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +10 -6
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +548 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +158 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +230 -43
- package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
- package/src/tool-runtime/truncation-store.ts +4 -0
- package/src/tui/chat/execution-badge.ts +5 -1
- package/src/tui/input-lag-probe.ts +230 -0
- package/src/tui-client/dashboard-session.ts +10 -1
- package/src/tui.ts +4 -0
- package/src/user-config/coercion.ts +36 -0
- package/src/user-config.ts +18 -41
- package/src/ux-sim/scenario.ts +314 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
- package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-2ebb8fd59b9461f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
- package/apps/pwa/out/_next/static/css/3f5fc6f96e2cf7b2.css +0 -1
- package/src/cli/g6a-registration-probe.ts +0 -16
- /package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
|
@@ -51,6 +51,8 @@ export interface HeavyRemoteResult {
|
|
|
51
51
|
reason?: string;
|
|
52
52
|
elapsedMs: number;
|
|
53
53
|
evidencePath: string;
|
|
54
|
+
/** Redacted stdout/stderr from a failed remote gate; never a reusable pass. */
|
|
55
|
+
failureLogPath?: string;
|
|
54
56
|
rootPlan?: RootPlanSummary | null;
|
|
55
57
|
interferenceMeasured?: boolean;
|
|
56
58
|
}
|
|
@@ -60,6 +62,8 @@ export interface HeavyRemoteDeps {
|
|
|
60
62
|
runRemote?: (input: Parameters<typeof runOnRemote>[0], runner: GateRemoteRunner) => RemoteRunOutcome;
|
|
61
63
|
settings?: ReturnType<typeof resolveGateRemoteSettings>;
|
|
62
64
|
now?: () => number;
|
|
65
|
+
/** Test seam — same cadence as self gate (`dispatchHeavyCheck`): sleep at most 15s while a host stays busy. */
|
|
66
|
+
sleep?: (ms: number) => void;
|
|
63
67
|
observe?: (event: string, data: Record<string, unknown>) => void;
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -157,6 +161,38 @@ function failedGateSummary(stdout: Buffer, stderr: Buffer): string | undefined {
|
|
|
157
161
|
return bounded.length ? bounded.join(' | ') : undefined;
|
|
158
162
|
}
|
|
159
163
|
|
|
164
|
+
/** The self-gate baseline prints one failure per line after its count header. Keep only distinct test paths here. */
|
|
165
|
+
function failedGateFiles(stdout: Buffer, stderr: Buffer): string | undefined {
|
|
166
|
+
const files = { introduced: new Set<string>(), preexisting: new Set<string>() };
|
|
167
|
+
for (const line of `${stdout.toString('utf8')}\n${stderr.toString('utf8')}`.split(/\r?\n/)) {
|
|
168
|
+
const match = /^- (introduced|preexisting):\s+(\S+\.(?:test|spec)\.[cm]?[jt]sx?)(?:\s+>|\s|$)/.exec(line.trim());
|
|
169
|
+
if (match) files[match[1] as keyof typeof files].add(match[2]!);
|
|
170
|
+
}
|
|
171
|
+
const parts = (['introduced', 'preexisting'] as const).filter((kind) => files[kind].size > 0)
|
|
172
|
+
.map((kind) => { const names = [...files[kind]].sort(); return `${kind}-files=${names.slice(0, 5).map((name) => redactSecretText(name).slice(0, 160)).join(',')}${names.length > 5 ? `,+${names.length - 5}` : ''}`; });
|
|
173
|
+
return parts.length ? parts.join(' · ') : undefined;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Remote scratch is deleted on exit. Preserve a bounded, redacted copy before returning a refusal. */
|
|
177
|
+
function writeFailedGateLog(path: string, stdout: Buffer, stderr: Buffer): string | undefined {
|
|
178
|
+
// One latest refusal log per PR; repeated attempts replace it atomically instead of accumulating files.
|
|
179
|
+
const logPath = `${path}.failure.log`;
|
|
180
|
+
const tempPath = `${logPath}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
|
|
181
|
+
const maxBytes = 2 * 1024 * 1024;
|
|
182
|
+
const render = (label: string, bytes: Buffer): string => {
|
|
183
|
+
const safe = Buffer.from(redactSecretText(bytes.toString('utf8')), 'utf8');
|
|
184
|
+
const clipped = safe.length > maxBytes
|
|
185
|
+
? `${safe.subarray(0, maxBytes / 2).toString('utf8')}\n[remote log middle truncated]\n${safe.subarray(-maxBytes / 2).toString('utf8')}` : safe.toString('utf8');
|
|
186
|
+
return `=== ${label} (${bytes.length} bytes${safe.length > maxBytes ? ', middle truncated' : ''}) ===\n${clipped}\n`;
|
|
187
|
+
};
|
|
188
|
+
try {
|
|
189
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
190
|
+
writeFileSync(tempPath, render('stdout', stdout) + render('stderr', stderr), { mode: 0o600, flag: 'wx' });
|
|
191
|
+
renameSync(tempPath, logPath);
|
|
192
|
+
return logPath;
|
|
193
|
+
} catch { rmSync(tempPath, { force: true }); return undefined; }
|
|
194
|
+
}
|
|
195
|
+
|
|
160
196
|
/** No local gate fallback: host refusal, an unmeasured run, and a failed gate all block landing. */
|
|
161
197
|
export function ensurePrLandHeavyRemote(input: HeavyRemoteInput, deps: HeavyRemoteDeps = {}): HeavyRemoteResult {
|
|
162
198
|
const path = evidencePath(input);
|
|
@@ -170,48 +206,66 @@ export function ensurePrLandHeavyRemote(input: HeavyRemoteInput, deps: HeavyRemo
|
|
|
170
206
|
}
|
|
171
207
|
const cached = matchingEvidence(path, input);
|
|
172
208
|
if (cached) return { ok: true, host: cached.host, source: 'cached', elapsedMs: 0, evidencePath: path, rootPlan: cached.rootPlan, interferenceMeasured: cached.interferenceMeasured };
|
|
173
|
-
const
|
|
209
|
+
const now = deps.now ?? Date.now;
|
|
210
|
+
const sleep = deps.sleep ?? ((ms: number) => { if (ms > 0) Bun.sleepSync(ms); });
|
|
211
|
+
const started = now();
|
|
212
|
+
const deadline = started + settings.slotWaitSeconds * 1000;
|
|
174
213
|
let outcome: RemoteRunOutcome = { kind: 'busy' };
|
|
175
214
|
const primaryHost: PrLandHeavyHost = settings.host;
|
|
176
215
|
let selectedHost: PrLandHeavyHost = primaryHost;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
const hosts = [primaryHost, ...PR_LAND_HEAVY_HOSTS.filter((candidate) => candidate !== primaryHost)];
|
|
217
|
+
wait: for (;;) {
|
|
218
|
+
for (const host of hosts) {
|
|
219
|
+
selectedHost = host;
|
|
220
|
+
try {
|
|
221
|
+
outcome = (deps.runRemote ?? runOnRemote)({
|
|
222
|
+
repo: input.repo, host, mirror: settings.mirror, commit: input.head,
|
|
223
|
+
refs: [input.main], hostCap: gateRemoteHostCap(settings, host), installPwa: true, stableCheckout: true,
|
|
224
|
+
// Test the tree GitHub will merge: scratch-checkout the reviewed head, merge the pinned main tip there,
|
|
225
|
+
// then run typecheck and self gate (changed tests and PWA reach/build) at that exact pair.
|
|
226
|
+
// The detached integration commit stays on the selected host and never changes the PR branch.
|
|
227
|
+
argv: (sha) => ['sh', '-c',
|
|
187
228
|
'git -c user.name=elanous-gate -c user.email=gate@localhost -c commit.gpgsign=false merge --no-ff --no-edit "$1" && TSC_BASE_REF="$1" bun run scripts/ci-typecheck-changed.ts --local && bun bin/elanous.mjs self gate --changed --base "$1" --local --shards 4 && bun scripts/pr-land-extra-remote-gates.ts "$1"',
|
|
188
229
|
'sh', sha(input.main)],
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
230
|
+
}, deps.runner ?? realGateRemoteRunner);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
outcome = { kind: 'infra', reason: `exception: ${error instanceof Error ? error.message : String(error)}` };
|
|
233
|
+
}
|
|
234
|
+
// A completed run or infrastructure failure is a verdict. Only a full host slot asks for another host.
|
|
235
|
+
if (outcome.kind !== 'busy') break wait;
|
|
192
236
|
}
|
|
193
|
-
//
|
|
194
|
-
|
|
237
|
+
// Both allowlisted hosts were busy. Wait the same slotWaitSeconds window as self gate, then retry.
|
|
238
|
+
debug.log('pr.land', 'host-busy', { host: selectedHost, occupied: outcome.occupied ?? null, slotWaitSeconds: settings.slotWaitSeconds });
|
|
239
|
+
const left = deadline - now();
|
|
240
|
+
if (left <= 0) break;
|
|
241
|
+
sleep(Math.min(15_000, left));
|
|
242
|
+
if (now() >= deadline) break;
|
|
195
243
|
}
|
|
196
|
-
const elapsedMs = Math.max(0,
|
|
244
|
+
const elapsedMs = Math.max(0, now() - started);
|
|
197
245
|
const observe = deps.observe ?? ((event: string, data: Record<string, unknown>) => debug.log('pr.land', event, data));
|
|
198
246
|
const actualHost = outcome.kind === 'ran' ? outcome.host : undefined;
|
|
199
247
|
const base = { pr: input.pr, head: input.head, main: input.main, host: actualHost ?? null, attemptedHost: selectedHost, elapsedMs };
|
|
200
248
|
// The outcome must identify the selected allowlisted host; the configured host alone is not evidence.
|
|
201
249
|
if (outcome.kind !== 'ran' || outcome.commit !== input.head || outcome.rc !== 0 || outcome.host !== selectedHost) {
|
|
202
250
|
const summary = outcome.kind === 'ran' && outcome.rc !== 0 ? failedGateSummary(outcome.stdout, outcome.stderr) : undefined;
|
|
251
|
+
// A different host cannot attest to this gate, so do not promote its file list into the refusal.
|
|
252
|
+
const files = outcome.kind === 'ran' && outcome.rc !== 0 && outcome.host === selectedHost && outcome.commit === input.head
|
|
253
|
+
? failedGateFiles(outcome.stdout, outcome.stderr) : undefined;
|
|
254
|
+
const failureLogPath = outcome.kind === 'ran' ? writeFailedGateLog(path, outcome.stdout, outcome.stderr) : undefined;
|
|
203
255
|
const reason = outcome.kind === 'ran'
|
|
204
256
|
? outcome.host !== selectedHost
|
|
205
|
-
? `gate-host-mismatch (${outcome.host})`
|
|
206
|
-
: `gate-rc-${outcome.rc}${outcome.commit !== input.head ? '-head-mismatch' : ''}${summary ? ` · remote: ${summary}` : ''}`
|
|
257
|
+
? `gate-host-mismatch (${outcome.host})${failureLogPath ? ` · remote-log: ${failureLogPath}` : ''}`
|
|
258
|
+
: `gate-rc-${outcome.rc}${outcome.commit !== input.head ? '-head-mismatch' : ''}${files ? ` · ${files}` : ''}${summary ? ` · remote: ${summary}` : ''}${failureLogPath ? ` · remote-log: ${failureLogPath}` : ' · remote-log: unavailable'}`
|
|
207
259
|
: outcome.kind === 'busy' ? 'gate-host-busy' : outcome.reason;
|
|
208
|
-
observe('heavy-remote', { ...base, outcome: outcome.kind === 'ran' ? 'fail' : 'unmeasured', reason });
|
|
209
|
-
return { ok: false, ...(actualHost ? { host: actualHost } : {}), attemptedHost: selectedHost, source: 'unmeasured', reason, elapsedMs, evidencePath: path };
|
|
260
|
+
observe('heavy-remote', { ...base, outcome: outcome.kind === 'ran' ? 'fail' : 'unmeasured', reason, failureLogPath: failureLogPath ?? null });
|
|
261
|
+
return { ok: false, ...(actualHost ? { host: actualHost } : {}), attemptedHost: selectedHost, source: 'unmeasured', reason, elapsedMs, evidencePath: path, ...(failureLogPath ? { failureLogPath } : {}) };
|
|
210
262
|
}
|
|
211
263
|
const extraGates = extraGatesFromOutput(outcome.stdout);
|
|
212
264
|
if (!extraGates) {
|
|
213
|
-
|
|
214
|
-
|
|
265
|
+
const failureLogPath = writeFailedGateLog(path, outcome.stdout, outcome.stderr);
|
|
266
|
+
const reason = `extra-global-unmeasured${failureLogPath ? ` · remote-log: ${failureLogPath}` : ' · remote-log: unavailable'}`;
|
|
267
|
+
observe('heavy-remote', { ...base, outcome: 'unmeasured', reason, failureLogPath: failureLogPath ?? null });
|
|
268
|
+
return { ok: false, host: selectedHost, attemptedHost: selectedHost, source: 'unmeasured', reason, elapsedMs, evidencePath: path, ...(failureLogPath ? { failureLogPath } : {}) };
|
|
215
269
|
}
|
|
216
270
|
const evidence: HeavyRemoteEvidence = {
|
|
217
271
|
schema: 2, pr: input.pr, head: input.head, main: input.main, host: selectedHost,
|
|
@@ -225,8 +279,10 @@ export function ensurePrLandHeavyRemote(input: HeavyRemoteInput, deps: HeavyRemo
|
|
|
225
279
|
renameSync(temp, path);
|
|
226
280
|
} catch (error) {
|
|
227
281
|
rmSync(temp, { force: true });
|
|
228
|
-
|
|
229
|
-
|
|
282
|
+
const failureLogPath = writeFailedGateLog(path, outcome.stdout, outcome.stderr);
|
|
283
|
+
const reason = `evidence-write-failed: ${error instanceof Error ? error.message : String(error)}${failureLogPath ? ` · remote-log: ${failureLogPath}` : ' · remote-log: unavailable'}`;
|
|
284
|
+
observe('heavy-remote', { ...base, outcome: 'unmeasured', reason, failureLogPath: failureLogPath ?? null });
|
|
285
|
+
return { ok: false, host: selectedHost, attemptedHost: selectedHost, source: 'unmeasured', reason, elapsedMs, evidencePath: path, ...(failureLogPath ? { failureLogPath } : {}) };
|
|
230
286
|
}
|
|
231
287
|
observe('heavy-remote', { ...base, outcome: 'pass', evidencePath: path, rootPlan: evidence.rootPlan, interferenceMeasured: evidence.interferenceMeasured });
|
|
232
288
|
return { ok: true, host: selectedHost, source: 'remote', elapsedMs, evidencePath: path, rootPlan: evidence.rootPlan, interferenceMeasured: evidence.interferenceMeasured };
|
|
@@ -25,6 +25,7 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
25
25
|
import { debug } from '../debug/log.js';
|
|
26
26
|
import type { CmdRunner } from '../autopilot/pr-manager.js';
|
|
27
27
|
import { parseReviewResultOutput } from '../task-agent/review-result-capture.js';
|
|
28
|
+
import { verifyVirtualRebasePatch } from './pr-land-virtual-rebase.js';
|
|
28
29
|
|
|
29
30
|
const SHA40 = /^[0-9a-f]{40}$/i;
|
|
30
31
|
|
|
@@ -35,7 +36,7 @@ interface OverlapEvidenceFile {
|
|
|
35
36
|
gate?: { head: string; baseCommit: string; passed: boolean };
|
|
36
37
|
/** `self review --json` stdout 을 받은 파일(TA: `<state>/review-results/<card>-<pr>-<head접두 10~40>.json`); 내용의 전체 head도 확인한다. */
|
|
37
38
|
reviewResult: string;
|
|
38
|
-
/**
|
|
39
|
+
/** Evidence-file override for explicitly replaced failed reviews. Each reason is the verifier's refusal reason. */
|
|
39
40
|
supersedes?: { reviewResult: string; reason: string }[];
|
|
40
41
|
/** OPEN follow-up PR that owns the findings intentionally split from this landing. */
|
|
41
42
|
followupPr?: number;
|
|
@@ -45,7 +46,12 @@ export type OverlapEvidenceVerdict =
|
|
|
45
46
|
| { ok: true; mode: 'already-ancestor'; reviewResult: string }
|
|
46
47
|
| { ok: true; mode: 'rebased'; baseTip: string; reviewResult: string }
|
|
47
48
|
| { ok: true; mode: 'base-advanced-disjoint'; baseTip: string; gateBase: string; windowCommits: number; reviewResult: string }
|
|
48
|
-
| { ok: false; reason: string };
|
|
49
|
+
| { ok: false; reason: string; baseTip?: string };
|
|
50
|
+
|
|
51
|
+
/** Resolve CLI-supplied evidence against the selected repository, not the caller's shell cwd. */
|
|
52
|
+
export function resolveOverlapEvidencePath(evidencePath: string, cwd: string): string {
|
|
53
|
+
return resolve(cwd, evidencePath);
|
|
54
|
+
}
|
|
49
55
|
|
|
50
56
|
export interface VerifyOverlapEvidenceInput {
|
|
51
57
|
evidencePath: string;
|
|
@@ -98,8 +104,12 @@ function checkSelectedReviewAttempts(input: VerifyOverlapEvidenceInput, e: Parti
|
|
|
98
104
|
const entries = e.supersedes;
|
|
99
105
|
if (entries !== undefined && (!Array.isArray(entries) || entries.length === 0)) return { ok: false, reason: 'review-supersedes-invalid' };
|
|
100
106
|
const superseded = new Map<string, string>();
|
|
107
|
+
const resolvedPriorAccepted: string[] = [];
|
|
101
108
|
let selectedTime: number | undefined;
|
|
102
|
-
|
|
109
|
+
let selectedRecord: Record<string, unknown> | undefined;
|
|
110
|
+
try { selectedRecord = lastReviewRecord(input.readFile(selected)); } catch { return { ok: false, reason: 'review-unreadable' }; }
|
|
111
|
+
const hasResolvedPrior = hasResolvedPriorDeclaration(selectedRecord);
|
|
112
|
+
if (entries?.length || hasResolvedPrior) {
|
|
103
113
|
try { selectedTime = input.reviewMtime(selected); } catch { return { ok: false, reason: 'review-attempt-time-unmeasured' }; }
|
|
104
114
|
if (!Number.isFinite(selectedTime)) return { ok: false, reason: 'review-attempt-time-unmeasured' };
|
|
105
115
|
}
|
|
@@ -122,9 +132,22 @@ function checkSelectedReviewAttempts(input: VerifyOverlapEvidenceInput, e: Parti
|
|
|
122
132
|
if (superseded.has(path)) return { ok: false, reason: 'review-supersedes-passing' };
|
|
123
133
|
continue;
|
|
124
134
|
}
|
|
125
|
-
if (superseded.
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
if (superseded.has(path)) {
|
|
136
|
+
if (superseded.get(path) !== review.reason) return { ok: false, reason: `review-attempt-not-superseded: ${basename(path)} (${review.reason})` };
|
|
137
|
+
if (!/^review-(verdict-fail|must-fix-[1-9][0-9]*)$/.test(review.reason)) {
|
|
138
|
+
return { ok: false, reason: `review-supersedes-not-failed: ${basename(path)} (${review.reason})` };
|
|
139
|
+
}
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (!/^review-(verdict-fail|must-fix-[1-9][0-9]*)$/.test(review.reason)
|
|
143
|
+
|| !selectedRecord || !reviewAttemptExplicitlyResolved(input, selectedRecord, path, head)) {
|
|
144
|
+
return { ok: false, reason: `review-attempt-not-superseded: ${basename(path)} (${review.reason})` };
|
|
145
|
+
}
|
|
146
|
+
resolvedPriorAccepted.push(path);
|
|
147
|
+
let failedTime: number;
|
|
148
|
+
try { failedTime = input.reviewMtime(path); } catch { return { ok: false, reason: 'review-attempt-time-unmeasured' }; }
|
|
149
|
+
if (!Number.isFinite(failedTime) || selectedTime === undefined || failedTime >= selectedTime) {
|
|
150
|
+
return { ok: false, reason: 'review-selected-not-later-than-failure' };
|
|
128
151
|
}
|
|
129
152
|
}
|
|
130
153
|
if (entries?.length) {
|
|
@@ -144,11 +167,137 @@ function checkSelectedReviewAttempts(input: VerifyOverlapEvidenceInput, e: Parti
|
|
|
144
167
|
head,
|
|
145
168
|
selected,
|
|
146
169
|
superseded: [...superseded.entries()].map(([reviewResult, reason]) => ({ reviewResult, reason })),
|
|
170
|
+
resolvedPriorAccepted,
|
|
147
171
|
followupPr: e.followupPr ?? null,
|
|
148
172
|
});
|
|
149
173
|
return { ok: true };
|
|
150
174
|
}
|
|
151
175
|
|
|
176
|
+
function lastReviewRecord(text: string): Record<string, unknown> | undefined {
|
|
177
|
+
const lines = text.split('\n').reverse();
|
|
178
|
+
for (const line of lines) {
|
|
179
|
+
if (!line.trim().startsWith('{')) continue;
|
|
180
|
+
let value: unknown;
|
|
181
|
+
try { value = JSON.parse(line); } catch { continue; }
|
|
182
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
183
|
+
const result = value as Record<string, unknown>;
|
|
184
|
+
if (result.pr !== undefined && (('verdict' in result && Array.isArray(result.mustFix)) || typeof result.error === 'string')) return result;
|
|
185
|
+
}
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function hasResolvedPriorDeclaration(review: Record<string, unknown> | undefined): boolean {
|
|
190
|
+
if (!review) return false;
|
|
191
|
+
const value = review.resolvedPrior;
|
|
192
|
+
if (Array.isArray(value) && value.length > 0) return true;
|
|
193
|
+
if (value && typeof value === 'object' && Object.keys(value).length > 0) return true;
|
|
194
|
+
return [review.intent, review.intentBlock, review.reviewIntent, review.reviewIntentBlock]
|
|
195
|
+
.some((intent) => typeof intent === 'string' && /resolved prior|prior review findings resolved/i.test(intent));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function normalizedFinding(value: string): string {
|
|
199
|
+
return value.trim().replace(/\s+/g, ' ').toLowerCase();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function containsUnresolvedClaim(value: string): boolean {
|
|
203
|
+
return /\b(?:unresolved|not(?:\s+yet)?[\s-]+resolved|not(?:\s+yet)?[\s-]+fixed|not(?:\s+yet)?[\s-]+addressed|still[\s-]+open|remains?[\s-]+open|still[\s-]+present|status\s*[:=]\s*(?:open|unresolved|pending|in[- ]progress))\b/i.test(value);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function containsUnresolvedDeclaration(value: unknown): boolean {
|
|
207
|
+
if (typeof value === 'string') return containsUnresolvedClaim(value);
|
|
208
|
+
if (Array.isArray(value)) return value.some(containsUnresolvedDeclaration);
|
|
209
|
+
if (!value || typeof value !== 'object') return false;
|
|
210
|
+
const record = value as Record<string, unknown>;
|
|
211
|
+
if (record.resolved === false || (typeof record.status === 'string' && /^(?:open|unresolved|pending|in[- ]progress)$/i.test(record.status))) return true;
|
|
212
|
+
return Object.values(record).some(containsUnresolvedDeclaration);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function referencesReview(value: unknown, path: string): boolean {
|
|
216
|
+
return typeof value === 'string' && (value === path || value === basename(path));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function findingList(value: unknown): string[] {
|
|
220
|
+
const values = Array.isArray(value) ? value : typeof value === 'string' ? [value] : [];
|
|
221
|
+
return values.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** A later same-head pass/mf0 review may resolve prior attempts only when it names every finding explicitly. */
|
|
225
|
+
function reviewAttemptExplicitlyResolved(input: VerifyOverlapEvidenceInput, selected: Record<string, unknown>, failedPath: string, head: string): boolean {
|
|
226
|
+
let failed: Record<string, unknown> | undefined;
|
|
227
|
+
try { failed = lastReviewRecord(input.readFile(failedPath)); } catch { return false; }
|
|
228
|
+
if (!failed || failed.pr === undefined || String(failed.pr) !== String(input.pr)
|
|
229
|
+
|| (typeof failed.headCommit === 'string' && failed.headCommit.toLowerCase() !== head)
|
|
230
|
+
|| (typeof failed.currentHeadCommit === 'string' && failed.currentHeadCommit.toLowerCase() !== head)) return false;
|
|
231
|
+
const rawFindings = findingList(failed.mustFix).map((finding) => finding.trim());
|
|
232
|
+
const findings = rawFindings.map(normalizedFinding);
|
|
233
|
+
if (findings.length === 0) return false;
|
|
234
|
+
|
|
235
|
+
const declared = selected.resolvedPrior;
|
|
236
|
+
if (declared !== undefined && containsUnresolvedDeclaration(declared)) return false;
|
|
237
|
+
const intentBlocks = [selected.intent, selected.intentBlock, selected.reviewIntent, selected.reviewIntentBlock]
|
|
238
|
+
.filter((value): value is string => typeof value === 'string');
|
|
239
|
+
// A resolution in one field cannot override an OPEN/PENDING declaration in another.
|
|
240
|
+
if (intentBlocks.some(containsUnresolvedClaim)) return false;
|
|
241
|
+
|
|
242
|
+
let resolved: string[] = [];
|
|
243
|
+
if (Array.isArray(declared)) {
|
|
244
|
+
for (const entry of declared) {
|
|
245
|
+
if (typeof entry === 'string') {
|
|
246
|
+
if (containsUnresolvedClaim(entry)) continue;
|
|
247
|
+
// A string can be an exact finding axis or an explicit "filename: finding" row.
|
|
248
|
+
const line = entry.trim();
|
|
249
|
+
if (rawFindings.includes(line)) resolved.push(line);
|
|
250
|
+
const prefix = `${basename(failedPath)}: `;
|
|
251
|
+
if (line.startsWith(prefix)) {
|
|
252
|
+
const declaredFinding = line.slice(prefix.length).trim();
|
|
253
|
+
const index = rawFindings.indexOf(declaredFinding);
|
|
254
|
+
if (index >= 0) resolved.push(findings[index]!);
|
|
255
|
+
}
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;
|
|
259
|
+
const item = entry as Record<string, unknown>;
|
|
260
|
+
const ref = item.reviewResult ?? item.review ?? item.path;
|
|
261
|
+
if (ref !== undefined && !referencesReview(ref, failedPath)) continue;
|
|
262
|
+
if (item.head !== undefined && (typeof item.head !== 'string' || item.head.toLowerCase() !== head)) continue;
|
|
263
|
+
if (item.headCommit !== undefined && (typeof item.headCommit !== 'string' || item.headCommit.toLowerCase() !== head)) continue;
|
|
264
|
+
if (item.resolved === false || item.status === 'unresolved'
|
|
265
|
+
|| Object.values(item).some((value) => typeof value === 'string' && containsUnresolvedClaim(value))) continue;
|
|
266
|
+
const listed = findingList(item.mustFix ?? item.resolvedMustFix ?? item.findings ?? item.axes ?? item.finding ?? item.axis);
|
|
267
|
+
if (listed.some(containsUnresolvedClaim)) continue;
|
|
268
|
+
if (ref === undefined && listed.every((finding) => rawFindings.includes(finding.trim()))) {
|
|
269
|
+
resolved.push(...listed.filter((finding) => rawFindings.includes(finding.trim())));
|
|
270
|
+
} else if (ref !== undefined) {
|
|
271
|
+
resolved.push(...listed.filter((finding) => rawFindings.includes(finding.trim())));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if (declared && typeof declared === 'object') {
|
|
275
|
+
const record = declared as Record<string, unknown>;
|
|
276
|
+
const value = record[failedPath] ?? record[basename(failedPath)];
|
|
277
|
+
resolved.push(...findingList(value).filter((finding) => !containsUnresolvedClaim(finding) && rawFindings.includes(finding.trim())));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
for (const intent of intentBlocks) {
|
|
281
|
+
const lines = intent.split(/\r?\n/);
|
|
282
|
+
const header = lines.findIndex((line) => /^resolved prior review findings:\s*$/i.test(line.trim()));
|
|
283
|
+
if (header < 0) continue;
|
|
284
|
+
// Only explicit rows under the resolution header count. A finding quoted in
|
|
285
|
+
// background prose is evidence of context, not a declaration of repair.
|
|
286
|
+
const prefix = `- ${basename(failedPath)}:`;
|
|
287
|
+
for (const raw of lines.slice(header + 1)) {
|
|
288
|
+
const line = raw.trim();
|
|
289
|
+
if (!line) continue;
|
|
290
|
+
if (!line.startsWith('- ')) break;
|
|
291
|
+
if (!line.startsWith(prefix)) continue;
|
|
292
|
+
const declaredFinding = line.slice(prefix.length).trim();
|
|
293
|
+
const index = rawFindings.indexOf(declaredFinding);
|
|
294
|
+
if (index >= 0) resolved.push(findings[index]!);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const resolvedSet = new Set(resolved.map(normalizedFinding));
|
|
298
|
+
return findings.every((finding) => resolvedSet.has(finding));
|
|
299
|
+
}
|
|
300
|
+
|
|
152
301
|
type Checked = { ok: false; reason: string; baseTip?: string; gateBase?: string; windowCommits?: number }
|
|
153
302
|
| (OverlapEvidenceVerdict & { ok: true; baseTip?: string });
|
|
154
303
|
|
|
@@ -175,17 +324,7 @@ function checkReview(input: Pick<VerifyOverlapEvidenceInput, 'pr' | 'readFile'>,
|
|
|
175
324
|
if (review.pr !== input.pr) return { ok: false, reason: 'review-pr-mismatch', baseTip };
|
|
176
325
|
if (!review.head || review.head.toLowerCase() !== head) return { ok: false, reason: 'review-head-mismatch', baseTip };
|
|
177
326
|
// The capture parser projects away model provenance; inspect the same last result-shaped line here.
|
|
178
|
-
|
|
179
|
-
for (const line of text.split('\n').reverse()) {
|
|
180
|
-
if (!line.trim().startsWith('{')) continue;
|
|
181
|
-
let value: unknown;
|
|
182
|
-
try { value = JSON.parse(line); } catch { continue; }
|
|
183
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
184
|
-
const result = value as Record<string, unknown>;
|
|
185
|
-
if (result.pr === undefined || !(('verdict' in result && Array.isArray(result.mustFix)) || typeof result.error === 'string')) continue;
|
|
186
|
-
raw = result;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
327
|
+
const raw = lastReviewRecord(text);
|
|
189
328
|
if (raw) {
|
|
190
329
|
const actualBackend = typeof raw.actualBackend === 'string' ? raw.actualBackend.trim().toLowerCase() : '';
|
|
191
330
|
const model = typeof raw.model === 'string' ? raw.model.trim().toLowerCase() : '';
|
|
@@ -222,6 +361,47 @@ function checkReview(input: Pick<VerifyOverlapEvidenceInput, 'pr' | 'readFile'>,
|
|
|
222
361
|
return { ok: true, reviewResult: e.reviewResult };
|
|
223
362
|
}
|
|
224
363
|
|
|
364
|
+
/** Reuse the evidence-selected review when a pinned head needs a read-only virtual rebase. */
|
|
365
|
+
export function verifyOverlapEvidenceVirtualRebase(input: VerifyOverlapEvidenceInput, baseTip: string):
|
|
366
|
+
{ ok: true; reviewResult: string; patchId: string } | { ok: false; reason: string; baseTip?: string } {
|
|
367
|
+
const head = input.expectedHead.toLowerCase();
|
|
368
|
+
if (!SHA40.test(head) || !SHA40.test(baseTip)) return { ok: false, reason: 'virtual-rebase-invalid-sha' };
|
|
369
|
+
let raw: unknown;
|
|
370
|
+
try { raw = JSON.parse(input.readFile(input.evidencePath)); }
|
|
371
|
+
catch { return { ok: false, reason: 'evidence-unreadable' }; }
|
|
372
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return { ok: false, reason: 'evidence-not-object' };
|
|
373
|
+
const evidence = raw as Partial<OverlapEvidenceFile>;
|
|
374
|
+
const evidencePr = typeof evidence.pr === 'number' ? evidence.pr
|
|
375
|
+
: typeof evidence.pr === 'string' && /^[0-9]+$/.test(evidence.pr) ? Number(evidence.pr) : NaN;
|
|
376
|
+
if (!Number.isSafeInteger(evidencePr) || evidencePr !== input.pr) return { ok: false, reason: 'evidence-pr-mismatch' };
|
|
377
|
+
if (typeof evidence.head !== 'string' || evidence.head.toLowerCase() !== head) return { ok: false, reason: 'evidence-head-mismatch' };
|
|
378
|
+
const gate = evidence.gate;
|
|
379
|
+
if (!gate || typeof gate !== 'object') return { ok: false, reason: 'gate-missing' };
|
|
380
|
+
if (gate.passed !== true) return { ok: false, reason: 'gate-not-passed' };
|
|
381
|
+
if (typeof gate.head !== 'string' || gate.head.toLowerCase() !== head) return { ok: false, reason: 'gate-head-mismatch' };
|
|
382
|
+
if (typeof gate.baseCommit !== 'string' || !SHA40.test(gate.baseCommit)) return { ok: false, reason: 'gate-base-unmeasured' };
|
|
383
|
+
const review = checkReview(input, evidence, head, baseTip);
|
|
384
|
+
if (!review.ok) return review;
|
|
385
|
+
const attempts = checkSelectedReviewAttempts(input, evidence, head);
|
|
386
|
+
if (!attempts.ok) return attempts;
|
|
387
|
+
const remote = input.run('git', ['ls-remote', input.remote, `refs/heads/${input.branch}`], { cwd: input.cwd });
|
|
388
|
+
if (!remote.ok || remote.out.trim().split(/\s+/)[0]?.toLowerCase() !== baseTip.toLowerCase()) {
|
|
389
|
+
return { ok: false, reason: 'virtual-rebase-base-advanced' };
|
|
390
|
+
}
|
|
391
|
+
const local = input.run('git', ['rev-parse', '--verify', `refs/remotes/${input.remote}/${input.branch}`], { cwd: input.cwd });
|
|
392
|
+
if (!local.ok || local.out.trim().toLowerCase() !== baseTip.toLowerCase()) {
|
|
393
|
+
return { ok: false, reason: 'virtual-rebase-base-stale-or-unmeasured' };
|
|
394
|
+
}
|
|
395
|
+
const patch = verifyVirtualRebasePatch({ cwd: input.cwd, baseTip, head });
|
|
396
|
+
if (!patch.ok) return patch;
|
|
397
|
+
const oldBase = patch.oldBase.toLowerCase();
|
|
398
|
+
const gateBase = gate.baseCommit.toLowerCase();
|
|
399
|
+
if (!input.run('git', ['merge-base', '--is-ancestor', gateBase, oldBase], { cwd: input.cwd }).ok) {
|
|
400
|
+
return { ok: false, reason: 'gate-base-not-ancestor-of-old-base' };
|
|
401
|
+
}
|
|
402
|
+
return { ok: true, reviewResult: review.reviewResult, patchId: patch.patchId };
|
|
403
|
+
}
|
|
404
|
+
|
|
225
405
|
type WindowResult = { ok: true; windowCommits: number } | { ok: false; reason: string; windowCommits?: number };
|
|
226
406
|
|
|
227
407
|
/**
|
|
@@ -431,7 +611,9 @@ export function verifyOverlapEvidence(input: VerifyOverlapEvidenceInput): Overla
|
|
|
431
611
|
gateBase: (verdict.ok ? (verdict.mode === 'base-advanced-disjoint' ? verdict.gateBase : undefined) : verdict.gateBase) ?? null,
|
|
432
612
|
windowCommits: (verdict.ok ? (verdict.mode === 'base-advanced-disjoint' ? verdict.windowCommits : undefined) : verdict.windowCommits) ?? null,
|
|
433
613
|
});
|
|
434
|
-
if (!verdict.ok) return
|
|
614
|
+
if (!verdict.ok) return (verdict.reason.startsWith('not-rebased:') || verdict.reason.startsWith('base-stale-overlap:')) && verdict.baseTip
|
|
615
|
+
? { ok: false, reason: verdict.reason, baseTip: verdict.baseTip }
|
|
616
|
+
: { ok: false, reason: verdict.reason };
|
|
435
617
|
if (verdict.mode === 'already-ancestor') return { ok: true, mode: 'already-ancestor', reviewResult: verdict.reviewResult };
|
|
436
618
|
if (verdict.mode === 'base-advanced-disjoint') {
|
|
437
619
|
return { ok: true, mode: 'base-advanced-disjoint', baseTip: verdict.baseTip!, gateBase: verdict.gateBase, windowCommits: verdict.windowCommits, reviewResult: verdict.reviewResult };
|
|
@@ -7,6 +7,9 @@ import type { RootPlanSummary } from './pr-land-heavy-remote.js';
|
|
|
7
7
|
|
|
8
8
|
const SHA = /^[0-9a-f]{40}$/i;
|
|
9
9
|
const MARKER = 'ELANOUS_PRLAND_SHADOW';
|
|
10
|
+
/** Shadow evidence is optional; it must not hold a ready landing for the Pod's 45-minute deadline. */
|
|
11
|
+
export const LANDING_POD_SHADOW_HOST_TIMEOUT_MS = 10 * 60_000;
|
|
12
|
+
export const LANDING_POD_SHADOW_STATUS_UNREADABLE_MS = 60_000;
|
|
10
13
|
|
|
11
14
|
export interface LandingPodShadowInput { head: string; main: string }
|
|
12
15
|
export interface LandingPodShadowVerdict {
|
|
@@ -42,12 +45,32 @@ export function landingPodShadowScript(head: string, main: string): string {
|
|
|
42
45
|
export async function runLandingPodShadowJob(input: LandingPodShadowInput, deps: {
|
|
43
46
|
runPod?: (options: RunPodCommandOptions) => Promise<PodCommandResult>;
|
|
44
47
|
readLog?: (path: string) => string;
|
|
48
|
+
/** Deterministic timer seam for the host deadline. */
|
|
49
|
+
armTimeout?: (onTimeout: () => void, ms: number) => () => void;
|
|
45
50
|
} = {}): Promise<LandingPodShadowVerdict> {
|
|
46
51
|
const script = landingPodShadowScript(input.head, input.main);
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
const armTimeout = deps.armTimeout ?? ((onTimeout: () => void, ms: number) => {
|
|
54
|
+
const timer = setTimeout(onTimeout, ms);
|
|
55
|
+
return () => clearTimeout(timer);
|
|
50
56
|
});
|
|
57
|
+
const disarm = armTimeout(() => {
|
|
58
|
+
const reason = new Error(`pod shadow: host timeout after ${LANDING_POD_SHADOW_HOST_TIMEOUT_MS}ms`);
|
|
59
|
+
controller.abort(reason);
|
|
60
|
+
}, LANDING_POD_SHADOW_HOST_TIMEOUT_MS);
|
|
61
|
+
let job: PodCommandResult;
|
|
62
|
+
try {
|
|
63
|
+
// Wait for the runner to observe abort and finish Job/Secret/lease cleanup before landing continues.
|
|
64
|
+
job = await (deps.runPod ?? runPodCommand)({
|
|
65
|
+
command: ['bash', '-lc', script], clone: true, source: { kind: 'commit', sha: input.head },
|
|
66
|
+
returnLogs: true, deadlineSeconds: 45 * 60,
|
|
67
|
+
statusUnreadableMs: LANDING_POD_SHADOW_STATUS_UNREADABLE_MS,
|
|
68
|
+
hostDeadlineAtMs: Date.now() + LANDING_POD_SHADOW_HOST_TIMEOUT_MS,
|
|
69
|
+
signal: controller.signal,
|
|
70
|
+
});
|
|
71
|
+
} finally {
|
|
72
|
+
disarm();
|
|
73
|
+
}
|
|
51
74
|
let log: string;
|
|
52
75
|
try { log = (deps.readLog ?? ((path: string) => readFileSync(path, 'utf8')))(join(job.artifactsDir, 'child.log')); }
|
|
53
76
|
catch (error) {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { classifyPrLandRefusal } from './pr-land-refusal.js';
|
|
2
|
+
import { readJourneyEdge } from '../self-dev/graph-journey-route.js';
|
|
3
|
+
|
|
4
|
+
/** A recover unit selects a next action. The train or TA still owns every effect. */
|
|
5
|
+
export interface PrLandRecoveryContext {
|
|
6
|
+
refusal: string;
|
|
7
|
+
pr?: number;
|
|
8
|
+
head?: string;
|
|
9
|
+
isDraft?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PrLandRecoveryPlan {
|
|
13
|
+
outcome: 'rework' | 'needs-human' | 'failed';
|
|
14
|
+
result: { action: 'wait-retry' | 'request-review' | 'needs-human' | 'none'; pr?: number; head?: string; delayMs?: number; reason: string };
|
|
15
|
+
evidence: { refusal: string; label: string; route: string | null; source: string };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function planPrLandRecovery(context: PrLandRecoveryContext): PrLandRecoveryPlan {
|
|
19
|
+
const raw = typeof context.refusal === 'string' ? context.refusal : '';
|
|
20
|
+
const lines = raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
21
|
+
// Callers must extract exactly one refusal line. A second diagnostic may be
|
|
22
|
+
// unmarked (for example `error: review-missing`), so never select a line
|
|
23
|
+
// from a larger transcript and mistake it for the whole verdict.
|
|
24
|
+
const refusal = lines.length === 1 ? lines[0]! : raw.trim();
|
|
25
|
+
const label = classifyPrLandRefusal(refusal, { isDraft: context.isDraft });
|
|
26
|
+
const route = readJourneyEdge('merge', label);
|
|
27
|
+
const evidence = { refusal: refusal.slice(0, 500), label, route: route.to, source: route.source };
|
|
28
|
+
const pr = Number.isSafeInteger(context.pr) && context.pr! > 0 ? context.pr : undefined;
|
|
29
|
+
const head = typeof context.head === 'string' && /^[0-9a-f]{40}$/i.test(context.head) ? context.head.toLowerCase() : undefined;
|
|
30
|
+
if (!refusal || !pr || !head) return { outcome: 'failed', result: { action: 'none', reason: 'pinned PR, head and refusal are required' }, evidence };
|
|
31
|
+
if (lines.length !== 1 || !refusal.startsWith('✗')) return { outcome: 'needs-human', result: { action: 'needs-human', pr, head, reason: `expected one marked refusal line, observed ${lines.length} nonempty lines` }, evidence };
|
|
32
|
+
if (route.source !== 'graph') return { outcome: 'needs-human', result: { action: 'needs-human', pr, head, reason: 'refusal has no declared graph route' }, evidence };
|
|
33
|
+
if (label === 'gate-host-busy' && route.to === 'next-move') {
|
|
34
|
+
return { outcome: 'rework', result: { action: 'wait-retry', pr, head, delayMs: 30_000, reason: 'remote gate host busy; retry through existing admission after delay' }, evidence };
|
|
35
|
+
}
|
|
36
|
+
if (label === 'review-missing' && route.to === 'review') {
|
|
37
|
+
return { outcome: 'rework', result: { action: 'request-review', pr, head, reason: 'request exact-head review through existing review gate' }, evidence };
|
|
38
|
+
}
|
|
39
|
+
return { outcome: 'needs-human', result: { action: 'needs-human', pr, head, reason: `${label} requires the existing ${route.to ?? 'unknown'} admission before another landing` }, evidence };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A graph call_entry cannot turn one refusal into another action. */
|
|
43
|
+
export function planPrLandRecoveryForEntry(context: PrLandRecoveryContext, entry: string): PrLandRecoveryPlan {
|
|
44
|
+
const plan = planPrLandRecovery(context);
|
|
45
|
+
// The default entry keeps the original read-only planner contract.
|
|
46
|
+
if (entry === 'plan') return plan;
|
|
47
|
+
if (entry === 'human-review') {
|
|
48
|
+
if (plan.outcome === 'needs-human' && plan.result.action === 'needs-human') return plan;
|
|
49
|
+
return { outcome: 'failed', result: { action: 'none', reason: `recover entry ${entry} does not match ${plan.result.action}` }, evidence: plan.evidence };
|
|
50
|
+
}
|
|
51
|
+
if (entry === 'request-review' || entry === 'wait-retry') {
|
|
52
|
+
if (plan.outcome === 'rework' && plan.result.action === entry) return plan;
|
|
53
|
+
return {
|
|
54
|
+
outcome: 'failed',
|
|
55
|
+
result: { action: 'none', reason: `recover entry ${entry} does not match ${plan.result.action}` },
|
|
56
|
+
evidence: plan.evidence,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
outcome: 'failed',
|
|
61
|
+
result: { action: 'none', reason: `unknown recover entry: ${entry}` },
|
|
62
|
+
evidence: plan.evidence,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
import { readJourneyEdge, recordJourneyEdge } from '../self-dev/graph-journey-route.js';
|
|
2
2
|
import { debug } from '../debug/log.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
export type PrLandRefusal = 'draft' | 'head-branch' | 'not-ancestor' | 'review-missing'
|
|
4
|
+
/** Observed `pr land` refusal reasons. Classification never retries a landing. */
|
|
5
|
+
export type PrLandRefusal = 'draft' | 'head-branch' | 'not-ancestor' | 'review-missing'
|
|
6
|
+
| 'gate-host-busy' | 'gate-merge-conflict' | 'gate-touch-clean'
|
|
7
|
+
| 'pr-base-unreadable' | 'public-export-leak' | 'other';
|
|
6
8
|
|
|
7
9
|
export function classifyPrLandRefusal(message: string, context: { isDraft?: boolean } = {}): PrLandRefusal {
|
|
8
10
|
if (context.isDraft === true && message.startsWith('✗ expected-head: PR OPEN non-draft')) return 'draft';
|
|
9
11
|
if (message.startsWith('✗ branch: PR head branch와 현재 브랜치가 다릅니다.')) return 'head-branch';
|
|
10
12
|
if (message.startsWith('✗ ancestor-auto: ancestor-auto-not-ancestor:')) return 'not-ancestor';
|
|
11
13
|
if (/^✗ (?:ancestor-auto|overlap-evidence): (?:review-missing|review-not-reviewed|review-error|review-no-result|review-unreadable|review-pr-mismatch|review-head-mismatch|review-path-not-for-this-pr-head|review-verdict-null|review-must-fix-unknown)(?:\b|$)/.test(message)) return 'review-missing';
|
|
14
|
+
if (message.startsWith('✗ heavy-remote: PR base=unreadable ≠ main')) return 'pr-base-unreadable';
|
|
15
|
+
if (/^✗ heavy-remote: (?:원격|병합 직전 원격|node-b) 게이트 gate-host-busy(?:\b|\s|$)/.test(message)) return 'gate-host-busy';
|
|
16
|
+
if (message.startsWith('✗ heavy-remote: 원격 게이트 gate-rc-1 · remote: stdout: CONFLICT (content): Merge conflict')) return 'gate-merge-conflict';
|
|
17
|
+
if (message.startsWith('✗ heavy-remote: 원격 게이트 gate-rc-1 · remote: stderr: 건드린 src/scripts 파일과 baseline 밖 test 파일은 tsc 클린이어야 합니다(touch-clean).')) return 'gate-touch-clean';
|
|
18
|
+
if (message.startsWith('✗ public-export-leak: 바뀐 파일')) return 'public-export-leak';
|
|
12
19
|
return 'other';
|
|
13
20
|
}
|
|
14
21
|
|
|
22
|
+
/** Direct landing failures are observed only when today's refusal shape is recognized. */
|
|
23
|
+
export function observeDirectPrLandRefusal(message: string): void {
|
|
24
|
+
if (classifyPrLandRefusal(message) === 'other') return;
|
|
25
|
+
observePrLandRefusal(message);
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
/** Read the declared recovery edge and observe the refusal. No recovery command runs here. */
|
|
16
29
|
export function observePrLandRefusal(message: string, context: { isDraft?: boolean } = {}): void {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
try {
|
|
31
|
+
const route = readJourneyEdge('merge', classifyPrLandRefusal(message, context));
|
|
32
|
+
if (route.to !== null) recordJourneyEdge(route, route.to, 'pr-land-refused; recovery-execution=none');
|
|
33
|
+
else debug.log('self-implement', 'graph-edge-unresolved', { from: 'merge', label: route.label, reason: 'pr-land-refused; recovery-execution=none' });
|
|
34
|
+
} catch { /* An observation failure must never change the landing refusal. */ }
|
|
20
35
|
}
|