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
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// 구현을 교체(누적 아님). 기존 PR 없으면 새로 생성.
|
|
10
10
|
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
12
13
|
import { githubAutomationToken } from '../auth/github-app-token.js';
|
|
13
14
|
import { debug } from '../debug/log.js';
|
|
14
15
|
import { POD_GITHUB_CREDENTIAL_TOKEN_ENV, POD_GITHUB_CREDENTIAL_URL_ENV } from '../nexus/api/pod-credential-api.js';
|
|
@@ -17,7 +18,9 @@ import { DEFAULT_BRANCH_WORKTREE_BASE } from '../git-fs/worktree.js';
|
|
|
17
18
|
import { isElanousRuntimeArtifactPath } from '../self-implement/gate-scope.js';
|
|
18
19
|
import { isTransientExecutionFailure } from '../self-dev/execution-transient.js';
|
|
19
20
|
import { withGhRestFallback } from './gh-rest-fallback.js';
|
|
20
|
-
import { cellIdFromBody, guardNewPr, parseDiffHunks, readOpenPrs, recordGuardUnmeasured, type GuardVerdict, type Seat } from '../pr-tool/census.js';
|
|
21
|
+
import { cardIdFromBody, cellIdFromBody, guardNewPr, hasCardMarker, parseDiffHunks, readOpenPrs, recordGuardUnmeasured, type GuardVerdict, type HunkOverlapMode, type Seat } from '../pr-tool/census.js';
|
|
22
|
+
import { labelsForAxis, PR_LABEL_NAMES } from '../github/pr-labels.js';
|
|
23
|
+
import { getUserConfig } from '../user-config.js';
|
|
21
24
|
|
|
22
25
|
/** ★ stderr 캡처(대표 2026-07-21·관측 갭) — 종전엔 stdout 만 담아 git/gh 실패 사유가 소실됐다
|
|
23
26
|
* (705308: makePr 실패가 bare null 로 뭉뚱그려져 triage 가 "인증·네트워크"로 환각 오라우팅).
|
|
@@ -117,7 +120,8 @@ export interface UpsertPrResult { url: string; reused: boolean }
|
|
|
117
120
|
* 특히 `noop`(nothing to commit)은 **실패가 아니라 이미 반영된 no-op** — 호출부가 정직 PASS 처리.
|
|
118
121
|
* 나머지 reason(add/commit/push/gh)은 진짜 실패로 detail(stderr)과 함께 관측·pr-failed. */
|
|
119
122
|
export type UpsertPrOutcome =
|
|
120
|
-
| { ok: true; url: string; reused: boolean; labelsApplied?: boolean; labelsOmitted?: boolean
|
|
123
|
+
| { ok: true; url: string; reused: boolean; labelsApplied?: boolean; labelsOmitted?: boolean;
|
|
124
|
+
supersededPr?: number }
|
|
121
125
|
| { ok: false; reason: 'add' | 'commit' | 'base' | 'noop' | 'push' | 'gh' | 'guard'; detail: string };
|
|
122
126
|
|
|
123
127
|
/** 관측된 문면 두 가지:
|
|
@@ -321,13 +325,163 @@ function seatFromEnvironment(): Seat | null {
|
|
|
321
325
|
return value === 'OP' || value === 'TC' || value === 'MK' || value === 'UX' ? value : null;
|
|
322
326
|
}
|
|
323
327
|
|
|
328
|
+
/** PR-GUARD-HUNK-WARN: config `prTool.hunkOverlap` — 'refuse' 만 옛 거부, 없거나 그 밖은 'warn'. */
|
|
329
|
+
export function configuredHunkOverlapMode(raw: Record<string, unknown> | undefined = getUserConfig().raw): HunkOverlapMode {
|
|
330
|
+
const prTool = raw?.prTool as { hunkOverlap?: unknown } | undefined;
|
|
331
|
+
return prTool?.hunkOverlap === 'refuse' ? 'refuse' : 'warn';
|
|
332
|
+
}
|
|
333
|
+
|
|
324
334
|
function defaultPrCreateGuard(input: { cwd: string; base: string | undefined; seat: Seat | null; body: string }, run: CmdRunner): GuardVerdict {
|
|
325
335
|
if (!input.base) return guardNewPr({ files: null, seat: input.seat }, { status: 'unknown', reason: '비교 base 없음' });
|
|
326
336
|
const diff = run('git', ['-C', input.cwd, 'diff', '--name-only', '-z', `${input.base}...HEAD`]);
|
|
327
337
|
const files = diff.ok ? diff.out.split('\0').filter(Boolean) : null;
|
|
328
338
|
const patch = run('git', ['-C', input.cwd, 'diff', '--unified=0', `${input.base}...HEAD`]);
|
|
329
339
|
if (!patch.ok) return guardNewPr({ files: null, seat: input.seat }, { status: 'unknown', reason: `후보 수정 줄 조회 실패: ${patch.err || patch.out}` });
|
|
330
|
-
|
|
340
|
+
const boundRaw = process.env.ELANOUS_TASK_BOUND_PR;
|
|
341
|
+
const boundPrNumber = boundRaw && /^[1-9]\d*$/.test(boundRaw) ? Number(boundRaw) : undefined;
|
|
342
|
+
return guardNewPr({ files, seat: input.seat, cellId: cellIdFromBody(input.body), cardId: cardIdFromBody(input.body),
|
|
343
|
+
...(boundPrNumber && Number.isSafeInteger(boundPrNumber) ? { boundPrNumber } : {}),
|
|
344
|
+
hunks: parseDiffHunks(patch.out), hunkOverlap: configuredHunkOverlapMode() }, readOpenPrs(run, { cwd: input.cwd, ...(files ? { candidateFiles: files } : {}) }));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function editExistingPr(run: CmdRunner, input: UpsertPrInput, url: string): UpsertPrOutcome {
|
|
348
|
+
const opts = { cwd: input.worktreePath };
|
|
349
|
+
const detailOf = (r: CmdResult) => (r.err || r.out || '').slice(0, 300);
|
|
350
|
+
const editArgs = ['pr', 'edit', url, '--title', input.title, '--body', input.body];
|
|
351
|
+
const explicitBase = input.base?.trim();
|
|
352
|
+
if (explicitBase && !isBranchSelfRef(explicitBase, input.branch)) editArgs.push('--base', prBaseFromComparison(explicitBase));
|
|
353
|
+
for (const label of new Set((input.labels ?? []).map(label => label.trim()).filter(Boolean))) editArgs.push('--add-label', label);
|
|
354
|
+
const edited = run('gh', editArgs, opts);
|
|
355
|
+
if (!edited.ok) return { ok: false, reason: 'gh', detail: detailOf(edited) || 'gh pr edit 실패' };
|
|
356
|
+
if (input.draft !== undefined) {
|
|
357
|
+
const stateR = run('gh', ['pr', 'view', url, '--json', 'isDraft', '-q', '.isDraft'], opts);
|
|
358
|
+
const raw = stateR.out.trim();
|
|
359
|
+
if (!stateR.ok || (raw !== 'true' && raw !== 'false'))
|
|
360
|
+
return { ok: false, reason: 'gh', detail: detailOf(stateR) || `draft 상태 조회 실패(isDraft=${raw || 'empty'})` };
|
|
361
|
+
if (input.draft === false && raw === 'true') {
|
|
362
|
+
const ready = run('gh', ['pr', 'ready', url], opts);
|
|
363
|
+
if (!ready.ok) return { ok: false, reason: 'gh', detail: detailOf(ready) || 'gh pr ready 실패' };
|
|
364
|
+
} else if (input.draft === true && raw === 'false') {
|
|
365
|
+
const undo = run('gh', ['pr', 'ready', url, '--undo'], opts);
|
|
366
|
+
if (!undo.ok) return { ok: false, reason: 'gh', detail: detailOf(undo) || 'gh pr ready --undo 실패' };
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (input.reuseComment) run('gh', ['pr', 'comment', url, '--body', input.reuseComment], opts);
|
|
370
|
+
return { ok: true, url, reused: true };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** Same-card rework may have a new run branch. Merge the bound PR head into that work,
|
|
374
|
+
* then update the bound branch with a plain fast-forward push. Every identity read is
|
|
375
|
+
* checked again after the inventory snapshot; an ambiguous or moved PR stays refused. */
|
|
376
|
+
function reuseSameCellPr(run: CmdRunner, input: UpsertPrInput, target: NonNullable<GuardVerdict['sameCellReuse']>, recheck: () => GuardVerdict): UpsertPrOutcome {
|
|
377
|
+
const cwd = input.worktreePath;
|
|
378
|
+
const fail = (detail: string): UpsertPrOutcome => ({ ok: false, reason: 'guard', detail: `same-cell reuse: ${detail}` });
|
|
379
|
+
if (!/^[0-9a-f]{40}$/i.test(target.headSha) || !Number.isSafeInteger(target.number) || target.number < 1
|
|
380
|
+
|| cellIdFromBody(input.body) !== target.cellId || cardIdFromBody(input.body) !== target.cardId)
|
|
381
|
+
return fail('candidate identity mismatch');
|
|
382
|
+
const validBranch = run('git', ['-C', cwd, 'check-ref-format', '--branch', target.branch]);
|
|
383
|
+
if (!validBranch.ok) return fail('PR branch name invalid');
|
|
384
|
+
const viewFields = 'state,headRefOid,headRefName,body,isCrossRepository,url,isDraft,labels';
|
|
385
|
+
const view = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
386
|
+
if (!view.ok) return fail('PR identity read failed');
|
|
387
|
+
let pr: Record<string, unknown>;
|
|
388
|
+
try { pr = JSON.parse(view.out) as Record<string, unknown>; } catch { return fail('PR identity malformed'); }
|
|
389
|
+
if (pr.state !== 'OPEN' || pr.isCrossRepository !== false || pr.headRefOid !== target.headSha
|
|
390
|
+
|| pr.headRefName !== target.branch || typeof pr.body !== 'string'
|
|
391
|
+
|| cellIdFromBody(pr.body) !== target.cellId
|
|
392
|
+
|| (target.legacyBound ? hasCardMarker(pr.body) || process.env.ELANOUS_TASK_BOUND_PR !== String(target.number)
|
|
393
|
+
: cardIdFromBody(pr.body) !== target.cardId)
|
|
394
|
+
|| typeof pr.url !== 'string' || extractPrNumber(pr.url) !== target.number)
|
|
395
|
+
return fail('PR state, head, repository, or card lineage changed');
|
|
396
|
+
const remoteRef = `refs/heads/${target.branch}`;
|
|
397
|
+
const remote = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
398
|
+
if (!remote.ok || remote.out.trim() !== `${target.headSha}\t${remoteRef}`) return fail('remote head changed');
|
|
399
|
+
const localRef = `refs/elanous/pr-reuse/${target.number}-${target.headSha.slice(0, 12)}`;
|
|
400
|
+
const fetched = run('git', ['-C', cwd, 'fetch', 'origin', `${remoteRef}:${localRef}`]);
|
|
401
|
+
const fetchedHead = fetched.ok ? run('git', ['-C', cwd, 'rev-parse', localRef]) : undefined;
|
|
402
|
+
if (!fetched.ok || !fetchedHead?.ok || fetchedHead.out.trim() !== target.headSha) return fail('PR head fetch mismatch');
|
|
403
|
+
const merged = run('git', ['-C', cwd, 'merge', '--no-edit', target.headSha]);
|
|
404
|
+
if (!merged.ok) {
|
|
405
|
+
const aborted = run('git', ['-C', cwd, 'merge', '--abort']);
|
|
406
|
+
if (!aborted.ok) return fail(`PR head merge abort failed: ${(aborted.err || aborted.out).slice(0, 220)}`);
|
|
407
|
+
// A conflicting same-card draft cannot be fast-forwarded. Preserve this run's
|
|
408
|
+
// head on its own branch, and let the returned new PR URL bind the card.
|
|
409
|
+
if (pr.isDraft !== true) return fail('conflicting PR is not a draft');
|
|
410
|
+
const clean = run('git', ['-C', cwd, 'status', '--porcelain', '--untracked-files=no']);
|
|
411
|
+
if (!clean.ok || clean.out.trim()) return fail('worktree changed after merge abort');
|
|
412
|
+
const before = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
413
|
+
let old: Record<string, unknown>;
|
|
414
|
+
try { old = JSON.parse(before.out) as Record<string, unknown>; } catch { return fail('PR pre-create identity malformed'); }
|
|
415
|
+
const remoteNow = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
416
|
+
const latest = recheck().sameCellReuse;
|
|
417
|
+
if (!before.ok || old.state !== 'OPEN' || old.isDraft !== true || old.headRefOid !== target.headSha
|
|
418
|
+
|| old.headRefName !== target.branch || old.body !== pr.body || old.url !== pr.url
|
|
419
|
+
|| !remoteNow.ok || remoteNow.out.trim() !== `${target.headSha}\t${remoteRef}`
|
|
420
|
+
|| !latest || latest.number !== target.number || latest.branch !== target.branch
|
|
421
|
+
|| latest.headSha !== target.headSha || latest.cellId !== target.cellId
|
|
422
|
+
|| latest.cardId !== target.cardId || Boolean(latest.legacyBound) !== Boolean(target.legacyBound))
|
|
423
|
+
return fail('PR changed before superseding draft');
|
|
424
|
+
const newRef = `refs/heads/${input.branch}`;
|
|
425
|
+
if (!run('git', ['-C', cwd, 'check-ref-format', '--branch', input.branch]).ok) return fail('new run branch name invalid');
|
|
426
|
+
const newRemote = run('git', ['-C', cwd, 'ls-remote', '--heads', 'origin', newRef]);
|
|
427
|
+
if (!newRemote.ok || newRemote.out.trim()) return fail('new run branch already exists or remote unreadable');
|
|
428
|
+
const localHead = run('git', ['-C', cwd, 'rev-parse', 'HEAD']);
|
|
429
|
+
if (!localHead.ok || !/^[0-9a-f]{40}$/i.test(localHead.out.trim())) return fail('new run head unreadable');
|
|
430
|
+
// Upload the commit through a unique scratch ref. GitHub's create-ref API then
|
|
431
|
+
// atomically refuses a concurrent writer of the intended branch name.
|
|
432
|
+
const scratch = `elanous-pr-create/${randomUUID()}`;
|
|
433
|
+
const scratchRef = `refs/heads/${scratch}`;
|
|
434
|
+
const uploaded = run('git', ['-C', cwd, 'push', 'origin', `HEAD:${scratchRef}`]);
|
|
435
|
+
if (!uploaded.ok) return fail(`new run object upload failed: ${(uploaded.err || uploaded.out).slice(0, 220)}`);
|
|
436
|
+
const repository = run('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], { cwd });
|
|
437
|
+
const repoName = repository.out.trim();
|
|
438
|
+
const createdRef = repository.ok && /^[^/\s]+\/[^/\s]+$/.test(repoName)
|
|
439
|
+
? run('gh', ['api', '--method', 'POST', `repos/${repoName}/git/refs`, '-f', `ref=${newRef}`, '-f', `sha=${localHead.out.trim()}`], { cwd })
|
|
440
|
+
: { ok: false, out: '', err: 'repository identity unavailable' };
|
|
441
|
+
const removedScratch = run('git', ['-C', cwd, 'push', 'origin', `:${scratchRef}`]);
|
|
442
|
+
if (!removedScratch.ok) debug.log('autopilot.pr-manager', 'same-cell-scratch-cleanup-failed',
|
|
443
|
+
{ scratchRef, detail: removedScratch.err || removedScratch.out,
|
|
444
|
+
stderr: removedScratch.err ?? '', stdout: removedScratch.out, truncated: false }, { level: 'warn' });
|
|
445
|
+
if (!createdRef.ok) return fail(`new run branch create refused: ${(createdRef.err || createdRef.out).slice(0, 220)}`);
|
|
446
|
+
const stateLabels = new Set(labelsForAxis('state').map(label => label.name));
|
|
447
|
+
const labels = [...new Set([...(input.labels ?? []).filter(label => !stateLabels.has(label as typeof PR_LABEL_NAMES.running)),
|
|
448
|
+
PR_LABEL_NAMES.running, ...(input.seat ? [`seat:${input.seat}`] : [])])];
|
|
449
|
+
const body = `${input.body.trimEnd()}\n\nSupersedes: #${target.number}`;
|
|
450
|
+
const create = ['pr', 'create', '--draft', '--head', input.branch, '--title', input.title, '--body', body];
|
|
451
|
+
const base = input.base?.trim();
|
|
452
|
+
if (base && !isBranchSelfRef(base, input.branch)) create.push('--base', prBaseFromComparison(base));
|
|
453
|
+
for (const label of labels) create.push('--label', label);
|
|
454
|
+
const created = run('gh', create, { cwd });
|
|
455
|
+
const newUrl = created.out.trim();
|
|
456
|
+
const newNumber = extractPrNumber(newUrl);
|
|
457
|
+
if (!created.ok || !newNumber) return { ok: false, reason: 'gh', detail: `superseding draft create failed: ${(created.err || created.out).slice(0, 220)}` };
|
|
458
|
+
debug.log('autopilot.pr-manager', 'same-cell-conflict-new-draft',
|
|
459
|
+
{ oldPr: target.number, newPr: newNumber, cardId: target.cardId, oldDraftCleanup: 'deferred' });
|
|
460
|
+
return { ok: true, url: newUrl, reused: false, supersededPr: target.number };
|
|
461
|
+
}
|
|
462
|
+
if (!run('git', ['-C', cwd, 'merge-base', '--is-ancestor', target.headSha, 'HEAD']).ok) return fail('PR head is not ancestor of result');
|
|
463
|
+
const finalView = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
464
|
+
let finalPr: Record<string, unknown>;
|
|
465
|
+
try { finalPr = JSON.parse(finalView.out) as Record<string, unknown>; } catch { return fail('PR pre-push identity read failed'); }
|
|
466
|
+
if (!finalView.ok || finalPr.state !== 'OPEN' || finalPr.isCrossRepository !== false
|
|
467
|
+
|| finalPr.headRefOid !== target.headSha || finalPr.headRefName !== target.branch
|
|
468
|
+
|| typeof finalPr.body !== 'string' || cellIdFromBody(finalPr.body) !== target.cellId
|
|
469
|
+
|| (target.legacyBound ? hasCardMarker(finalPr.body) || process.env.ELANOUS_TASK_BOUND_PR !== String(target.number)
|
|
470
|
+
: cardIdFromBody(finalPr.body) !== target.cardId)
|
|
471
|
+
|| finalPr.url !== pr.url) return fail('PR changed before push');
|
|
472
|
+
const finalRemote = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
473
|
+
if (!finalRemote.ok || finalRemote.out.trim() !== `${target.headSha}\t${remoteRef}`) return fail('remote head changed before push');
|
|
474
|
+
const latest = recheck().sameCellReuse;
|
|
475
|
+
if (!latest || latest.number !== target.number || latest.branch !== target.branch
|
|
476
|
+
|| latest.headSha !== target.headSha || latest.cellId !== target.cellId
|
|
477
|
+
|| latest.cardId !== target.cardId || Boolean(latest.legacyBound) !== Boolean(target.legacyBound))
|
|
478
|
+
return fail('OPEN PR inventory changed before push');
|
|
479
|
+
// The result descends from the exact fetched head. The explicit lease binds the
|
|
480
|
+
// remote update to that head, so a delete or move between reads cannot be revived.
|
|
481
|
+
const pushed = run('git', ['-C', cwd, 'push', `--force-with-lease=${remoteRef}:${target.headSha}`, 'origin', `HEAD:${remoteRef}`]);
|
|
482
|
+
if (!pushed.ok) return fail(`fast-forward push refused: ${(pushed.err || pushed.out).slice(0, 220)}`);
|
|
483
|
+
debug.log('autopilot.pr-manager', 'same-cell-reused', { pr: target.number, cellId: target.cellId, cardId: target.cardId, branch: target.branch });
|
|
484
|
+
return editExistingPr(run, input, pr.url);
|
|
331
485
|
}
|
|
332
486
|
|
|
333
487
|
/** ★ PR 매니저 팩토리(대표 2026-07-12) — CmdRunner 주입(테스트 스텁). 실 배선은 기본 러너. */
|
|
@@ -489,11 +643,37 @@ export function makePrManager(
|
|
|
489
643
|
}
|
|
490
644
|
// ahead > 0 + 내용차 존재 → 이미 커밋된 산출. commit 스킵하고 아래 push + PR 로 fall-through.
|
|
491
645
|
}
|
|
646
|
+
// 카드 계보를 아는 재작업은 새 run 가지를 발사하기 전에 같은 칸 PR 을 찾는다.
|
|
647
|
+
// 같은 카드로 증명된 단일 PR 만 기존 가지를 빠른 전진시킨다. 다른 계보·모호한 목록은 종전 가드다.
|
|
648
|
+
const candidateCardId = cardIdFromBody(input.body);
|
|
649
|
+
if (hasCardMarker(input.body) && !candidateCardId)
|
|
650
|
+
return { ok: false, reason: 'guard', detail: 'candidate card lineage is ambiguous' };
|
|
651
|
+
const earlyGuard = candidateCardId && checkCreate
|
|
652
|
+
? checkCreate({ cwd, base: comparisonBase, seat: input.seat ?? seatFromEnvironment(), body: input.body }, run)
|
|
653
|
+
: undefined;
|
|
654
|
+
const freshGuard = () => checkCreate!({ cwd, base: comparisonBase, seat: input.seat ?? seatFromEnvironment(), body: input.body }, run);
|
|
655
|
+
if (earlyGuard?.sameCellReuse) return reuseSameCellPr(run, input, earlyGuard.sameCellReuse, freshGuard);
|
|
656
|
+
if (earlyGuard?.status === 'refuse') return { ok: false, reason: 'guard', detail: earlyGuard.reasons.map(reason => `${reason.code}: ${reason.detail}`).join('; ') };
|
|
657
|
+
const earlyInventoryUnknown = !!candidateCardId && (!checkCreate || (earlyGuard?.status === 'unknown'
|
|
658
|
+
&& earlyGuard.reasons.length === 1 && earlyGuard.reasons[0]?.code === 'inventory-unknown'));
|
|
659
|
+
if (candidateCardId && earlyGuard?.status !== 'allow' && !earlyInventoryUnknown)
|
|
660
|
+
return { ok: false, reason: 'guard', detail: 'candidate card inventory unmeasured before push' };
|
|
661
|
+
if (earlyInventoryUnknown) debug.log('pr-tool.open-guard', 'candidate-inventory-unmeasured', {
|
|
662
|
+
branch: input.branch, cardId: candidateCardId, stage: 'before-push',
|
|
663
|
+
reason: earlyGuard?.reasons[0]?.detail ?? 'create guard unavailable',
|
|
664
|
+
});
|
|
665
|
+
if (candidateCardId) {
|
|
666
|
+
const branchPr = findPrForBranchOutcome(input.branch, cwd);
|
|
667
|
+
if (branchPr.status === 'FAILED' || branchPr.url)
|
|
668
|
+
return { ok: false, reason: 'guard', detail: 'candidate run branch PR already exists or is unmeasured before push' };
|
|
669
|
+
}
|
|
492
670
|
// force-push — 재구현이 이전 구현을 교체(기존 브랜치 갱신 or 신규). 안정 브랜치명이라 기존 PR 이
|
|
493
671
|
// 있으면 GitHub 이 그 PR 을 자동 업데이트(닫고 새로 안 만듦). elanous 자체 SE 브랜치라 force 안전.
|
|
494
672
|
// 일시 원격 실패(5xx·연결 끊김 등)만 최대 3회. 영구 거부는 한 번에 끝낸다.
|
|
495
673
|
const waitForPushRetry = input.waitForPushRetry ?? defaultWaitForPushRetry;
|
|
496
|
-
const pushArgs =
|
|
674
|
+
const pushArgs = candidateCardId
|
|
675
|
+
? ['-C', cwd, 'push', '-u', 'origin', input.branch]
|
|
676
|
+
: ['-C', cwd, 'push', '--force', '-u', 'origin', input.branch];
|
|
497
677
|
let pushR = runGitWrite(pushArgs);
|
|
498
678
|
let pushAttempts = 1;
|
|
499
679
|
while (!pushR.ok && pushAttempts < MAX_PUSH_ATTEMPTS && isTransientPushFailure(detailOf(pushR))) {
|
|
@@ -509,46 +689,22 @@ export function makePrManager(
|
|
|
509
689
|
}
|
|
510
690
|
const existing = findPrForBranchOutcome(input.branch, cwd);
|
|
511
691
|
if (existing.url) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
// - draft: 현재 상태를 조회해 실제 전이가 필요할 때만 수행(멱등) — 이미 요청 상태면 no-op.
|
|
516
|
-
// draft=false && 현재 draft → gh pr ready · draft=true && 현재 ready → gh pr ready --undo.
|
|
517
|
-
const editArgs = ['pr', 'edit', existing.url, '--title', input.title, '--body', input.body];
|
|
518
|
-
// ⚠️ 재사용 경로는 **명시 base 만** 넘긴다(리뷰 must-fix 2026-07-26). 추론한 base 를 넘기면
|
|
519
|
-
// `release/*` 등 비기본 브랜치를 대상으로 열려 있던 기존 PR 을 **main 으로 재타기팅**하는
|
|
520
|
-
// 회귀가 된다(요청자는 base 를 지정하지도 않았는데). 미지정 = "base 는 건드리지 마라".
|
|
521
|
-
// 신규 생성은 base 가 반드시 필요하므로 그쪽만 추론값을 쓴다.
|
|
522
|
-
// 트림은 신규 경로(resolveDeliverableBase)와 동일하게 — 공백 전용 base 는 미지정으로 본다(리뷰 should-fix).
|
|
523
|
-
const explicitBase = input.base?.trim();
|
|
524
|
-
if (explicitBase && !isBranchSelfRef(explicitBase, input.branch)) editArgs.push('--base', prBaseFromComparison(explicitBase));
|
|
525
|
-
for (const label of new Set((input.labels ?? []).map(label => label.trim()).filter(Boolean))) editArgs.push('--add-label', label);
|
|
526
|
-
let edited = run('gh', editArgs, opts);
|
|
527
|
-
if (!edited.ok) return { ok: false, reason: 'gh', detail: detailOf(edited) || 'gh pr edit 실패' };
|
|
528
|
-
if (input.draft !== undefined) {
|
|
529
|
-
// 현재 draft 상태 조회 — 조회 실패/비정상 출력은 fail-closed(요청 draft 를 적용 못했는데
|
|
530
|
-
// 성공 반환하면 openPr 계약 위반). 정상 조회 시에만 실제 전이가 필요할 때 수행(멱등).
|
|
531
|
-
const stateR = run('gh', ['pr', 'view', existing.url, '--json', 'isDraft', '-q', '.isDraft'], opts);
|
|
532
|
-
const raw = stateR.out.trim();
|
|
533
|
-
if (!stateR.ok || (raw !== 'true' && raw !== 'false')) {
|
|
534
|
-
return { ok: false, reason: 'gh', detail: detailOf(stateR) || `draft 상태 조회 실패(isDraft=${raw || 'empty'})` };
|
|
535
|
-
}
|
|
536
|
-
const isDraft = raw === 'true';
|
|
537
|
-
if (input.draft === false && isDraft) {
|
|
538
|
-
const ready = run('gh', ['pr', 'ready', existing.url], opts);
|
|
539
|
-
if (!ready.ok) return { ok: false, reason: 'gh', detail: detailOf(ready) || 'gh pr ready 실패' };
|
|
540
|
-
} else if (input.draft === true && !isDraft) {
|
|
541
|
-
const undo = run('gh', ['pr', 'ready', existing.url, '--undo'], opts);
|
|
542
|
-
if (!undo.ok) return { ok: false, reason: 'gh', detail: detailOf(undo) || 'gh pr ready --undo 실패' };
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
if (input.reuseComment) run('gh', ['pr', 'comment', existing.url, '--body', input.reuseComment], opts);
|
|
546
|
-
return { ok: true, url: existing.url, reused: true };
|
|
692
|
+
if (candidateCardId)
|
|
693
|
+
return { ok: false, reason: 'guard', detail: 'candidate run branch PR appeared after push; refuse edit' };
|
|
694
|
+
return editExistingPr(run, input, existing.url);
|
|
547
695
|
}
|
|
548
|
-
|
|
696
|
+
if (existing.status === 'FAILED') return { ok: false, reason: 'gh', detail: 'existing PR branch lookup failed' };
|
|
697
|
+
let guardUnmeasured = earlyInventoryUnknown;
|
|
698
|
+
let hunkOverlapWarning: { prs: readonly number[]; files: readonly string[] } | null = null;
|
|
549
699
|
if (checkCreate) {
|
|
550
700
|
const seat = input.seat ?? seatFromEnvironment();
|
|
701
|
+
// Another run may open a PR after the early inventory and before this create.
|
|
702
|
+
// Read the complete OPEN inventory again after push, immediately before create.
|
|
551
703
|
const verdict = checkCreate({ cwd, base: comparisonBase, seat, body: input.body }, run);
|
|
704
|
+
if (verdict.sameCellReuse)
|
|
705
|
+
return { ok: false, reason: 'guard', detail: 'same-cell PR appeared after run branch push; retry from fresh inventory' };
|
|
706
|
+
const hunkWarn = verdict.status === 'allow' ? verdict.warnings.find(warning => warning.code === 'hunk-overlap') : undefined;
|
|
707
|
+
if (hunkWarn) hunkOverlapWarning = { prs: hunkWarn.prs ?? [], files: hunkWarn.files ?? [] };
|
|
552
708
|
if (verdict.status === 'unknown' && verdict.reasons.length === 1 && verdict.reasons[0]?.code === 'inventory-unknown') {
|
|
553
709
|
const inPod = process.env.ELANOUS_SUBSTRATE === 'pod'
|
|
554
710
|
|| Object.keys(process.env).some(key => key.startsWith('ELANOUS_POD_'));
|
|
@@ -559,9 +715,9 @@ export function makePrManager(
|
|
|
559
715
|
} else {
|
|
560
716
|
const count = recordUnmeasured({ seat, reason: verdict.reasons[0].detail });
|
|
561
717
|
if (count.blocked) {
|
|
562
|
-
const alert = run('eln', ['msg', 'post', '--from', seat ?? 'HARNESS', '--to', 'OP', '--kind', 'alert', '--body', `PR open-guard 판정 불가 1시간 ${count.count}회 · 새 PR 차단 · ${count.reason ?? verdict.reasons[0].detail}`]);
|
|
718
|
+
const alert = run('eln', ['msg', 'post', '--from', seat ?? 'HARNESS', '--to', 'OP', '--kind', 'alert', '--body', `PR open-guard 판정 불가 1시간 ${count.count}회 · ${candidateCardId ? '카드 후보는 draft 관측' : '새 PR 차단'} · ${count.reason ?? verdict.reasons[0].detail}`]);
|
|
563
719
|
if (!alert.ok) debug.log('pr-tool.open-guard', 'op-alert-failed', { seat, reason: alert.err || alert.out || 'eln msg post 실패' });
|
|
564
|
-
return { ok: false, reason: 'guard', detail: `inventory-unknown: 1시간 ${count.count}회 · 새 PR 차단${count.reason ? ` (${count.reason})` : ''}` };
|
|
720
|
+
if (!candidateCardId) return { ok: false, reason: 'guard', detail: `inventory-unknown: 1시간 ${count.count}회 · 새 PR 차단${count.reason ? ` (${count.reason})` : ''}` };
|
|
565
721
|
}
|
|
566
722
|
}
|
|
567
723
|
guardUnmeasured = true;
|
|
@@ -571,18 +727,28 @@ export function makePrManager(
|
|
|
571
727
|
}
|
|
572
728
|
const createArgs = ['pr', 'create', '--head', input.branch, '--title', input.title, '--body', input.body];
|
|
573
729
|
if (prBase) createArgs.push('--base', prBase);
|
|
574
|
-
if (input.draft) createArgs.push('--draft');
|
|
730
|
+
if (input.draft || guardUnmeasured) createArgs.push('--draft');
|
|
575
731
|
const seat = input.seat ?? seatFromEnvironment();
|
|
576
732
|
const requiredLabels = [...(seat ? [`seat:${seat}`] : []), ...(guardUnmeasured ? ['pr-guard:unmeasured'] : [])];
|
|
577
|
-
|
|
733
|
+
// PR-GUARD-HUNK-WARN: 줄 겹침 경고 라벨은 «최선» — 만들기 실패해도 아래 재시도가 빼고 PR 을 연다.
|
|
734
|
+
const guardLabels = hunkOverlapWarning ? ['pr-guard:hunk-overlap'] : [];
|
|
735
|
+
const creatableLabels = [...requiredLabels, ...guardLabels];
|
|
736
|
+
const requestedLabels = [...new Set([...(input.labels ?? []), ...creatableLabels].map((label) => label.trim()).filter(Boolean))];
|
|
578
737
|
const labeledArgs = [...createArgs];
|
|
579
738
|
for (const label of requestedLabels) labeledArgs.push('--label', label);
|
|
580
739
|
let created = run('gh', labeledArgs, opts);
|
|
581
|
-
if (!created.ok &&
|
|
582
|
-
for (const label of
|
|
740
|
+
if (!created.ok && creatableLabels.length && isLabelNotFoundFailure(created, creatableLabels)) {
|
|
741
|
+
for (const label of creatableLabels) run('gh', ['label', 'create', label, '--color', 'BFDADC'], opts);
|
|
583
742
|
created = run('gh', labeledArgs, opts);
|
|
584
743
|
}
|
|
744
|
+
const logHunkOverlapWarn = (url: string): void => {
|
|
745
|
+
if (hunkOverlapWarning) debug.log('pr-tool.guard', 'hunk-overlap-warn', { pr: extractPrNumber(url), files: hunkOverlapWarning.files, against: hunkOverlapWarning.prs });
|
|
746
|
+
};
|
|
585
747
|
if (created.ok && created.out) {
|
|
748
|
+
if (guardUnmeasured) debug.log('pr-tool.open-guard', 'candidate-draft-unmeasured', {
|
|
749
|
+
branch: input.branch, cardId: candidateCardId ?? null, url: created.out,
|
|
750
|
+
});
|
|
751
|
+
logHunkOverlapWarn(created.out);
|
|
586
752
|
return {
|
|
587
753
|
ok: true,
|
|
588
754
|
url: created.out,
|
|
@@ -595,6 +761,7 @@ export function makePrManager(
|
|
|
595
761
|
for (const label of requiredLabels) retryArgs.push('--label', label);
|
|
596
762
|
const retry = run('gh', retryArgs, opts);
|
|
597
763
|
if (retry.ok && retry.out) {
|
|
764
|
+
logHunkOverlapWarn(retry.out);
|
|
598
765
|
debug.log('autopilot.pr-manager', 'create.labels-omitted', {
|
|
599
766
|
branch: input.branch,
|
|
600
767
|
labels: requestedLabels,
|
|
@@ -276,3 +276,42 @@ export const AGENT_MISSION_STATE_RULES: readonly StateRule[] = [
|
|
|
276
276
|
match: { kind: 'lineRegex', re: /^\s*[❯›](\s|$)|▌/ },
|
|
277
277
|
},
|
|
278
278
|
];
|
|
279
|
+
|
|
280
|
+
// ── 자기보고 턴 ⊕ 화면 추정 정합 (H10 조각 1 · TUI-H10-HEALTH-REPORT) ──
|
|
281
|
+
//
|
|
282
|
+
// 🩸 10-16 실측: 같은 `eln pty state opt` 가 `state=working`(화면 추정 — 스크롤백에 남은 «· Streaming… (5s · esc 중단)»
|
|
283
|
+
// 줄을 `elanous-tui-turn-in-progress` 가 물었다)과 `turn=idle`(TUI 가 스스로 적은 값)을 «동시에» 냈다(#55 이원 판정).
|
|
284
|
+
// OP·TF 는 둘 중 무엇을 믿을지 몰라 herdr 화면을 긁었다.
|
|
285
|
+
// ⇒ 원천은 하나다: TUI 가 스스로 적은 턴(`tui-run-state` → manifest)이 있으면 그것이 «바쁜가/한가한가»를 정한다.
|
|
286
|
+
// 화면 추정은 턴 값이 «모를 때»와, 턴과 모순되지 않는 «더 구체적인» 상태(승인 대기 blocked·waiting·done)일 때만 쓴다.
|
|
287
|
+
// ⛔ 화면 추정은 버리지 않는다 — `screenState` 로 같이 내서 둘이 갈린 순간이 관측에 남게 한다.
|
|
288
|
+
|
|
289
|
+
/** TUI 가 스스로 적은 턴(manifest `turnState`). 'unknown' = 기록 없음·죽은 행. */
|
|
290
|
+
export type SelfReportedTurn = 'busy' | 'idle' | 'unknown';
|
|
291
|
+
|
|
292
|
+
export interface ReconciledFrameState {
|
|
293
|
+
/** 바깥에 내는 하나의 상태. */
|
|
294
|
+
readonly state: FrameState;
|
|
295
|
+
/** 'turn' = 자기보고 턴이 정했다(화면과 같았던 경우 포함) · 'screen' = 화면 추정을 그대로 썼다. */
|
|
296
|
+
readonly source: 'turn' | 'screen';
|
|
297
|
+
/** 화면 분류 원값(화면을 못 읽었으면 'unknown'). */
|
|
298
|
+
readonly screenState: FrameState;
|
|
299
|
+
/** 화면 추정이 턴과 «모순»돼 턴이 덮어썼나 — 관측 이벤트를 남길 자리. */
|
|
300
|
+
readonly overridden: boolean;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 화면 추정과 자기보고 턴을 하나로 접는다(순수).
|
|
305
|
+
* - turn=busy: 화면 blocked·waiting 은 «턴 안의 더 구체적인 상태»라 유지, 그 밖(idle·unknown·done·working)은 working.
|
|
306
|
+
* - turn=idle: 화면 blocked·waiting·done 은 유지(한가할 때 뜨는 선택 UI 등), working·unknown 은 idle.
|
|
307
|
+
* - turn=unknown: 화면 추정 그대로.
|
|
308
|
+
*/
|
|
309
|
+
export function reconcileFrameStateWithTurn(screenState: FrameState, turn: SelfReportedTurn): ReconciledFrameState {
|
|
310
|
+
if (turn === 'unknown') return { state: screenState, source: 'screen', screenState, overridden: false };
|
|
311
|
+
if (turn === 'busy') {
|
|
312
|
+
if (screenState === 'blocked' || screenState === 'waiting') return { state: screenState, source: 'screen', screenState, overridden: false };
|
|
313
|
+
return { state: 'working', source: 'turn', screenState, overridden: screenState !== 'working' && screenState !== 'unknown' };
|
|
314
|
+
}
|
|
315
|
+
if (screenState === 'blocked' || screenState === 'waiting' || screenState === 'done') return { state: screenState, source: 'screen', screenState, overridden: false };
|
|
316
|
+
return { state: 'idle', source: 'turn', screenState, overridden: screenState === 'working' };
|
|
317
|
+
}
|
|
@@ -39,10 +39,11 @@ import { createTuiScreenMirror } from './tui-screen-mirror.js';
|
|
|
39
39
|
import { getChannelBus } from '../terminal-matrix/index.js';
|
|
40
40
|
import { publishSelfReportFrame } from './self-report-frame.js';
|
|
41
41
|
import {
|
|
42
|
-
upsertPtyManifest, updatePtyManifestFrame, touchLivePtyManifest, markPtyManifestClosed, removePtyManifest,
|
|
42
|
+
upsertPtyManifest, updatePtyManifestFrame, touchLivePtyManifest, markPtyManifestClosed, removePtyManifest, getPtyManifest,
|
|
43
|
+
updatePtyManifestBuild,
|
|
43
44
|
} from '../pty-shell/pty-manifest.js';
|
|
44
45
|
import { writeHarnessScreen } from '../harness/harness-screen.js';
|
|
45
|
-
import { startTuiRunStateRecorder } from '../pty-shell/tui-run-state.js';
|
|
46
|
+
import { runningBuild, startTuiRunStateRecorder } from '../pty-shell/tui-run-state.js';
|
|
46
47
|
import { debug } from '../debug/log.js';
|
|
47
48
|
import { routeExternalInput, type ExternalInputRoute } from '../input/external-input-queue.js';
|
|
48
49
|
|
|
@@ -187,6 +188,46 @@ export interface TuiSelfReportDeps {
|
|
|
187
188
|
startRunState?: (surfaceId: string) => (() => void);
|
|
188
189
|
/** 미룬 우편 깨움 폴러(TUI-H4)를 연다 — 반환 = 정리. 기본은 실 행 등록과 짝일 때만 늦게 불러온 `startPendingWakePoller`. */
|
|
189
190
|
startWakePoller?: (surfaceId: string) => (() => void);
|
|
191
|
+
/** 박동마다 자기 행을 본다 — 없으면 null · ⛔ 조회 실패는 «던진다»(없다로 읽지 않는다). 기본 = `getPtyManifest(id, { strict })`. */
|
|
192
|
+
lookupRow?: (surfaceId: string) => TuiOwnRowView | null;
|
|
193
|
+
/** 재등록 뒤 실행 판(build) 칸을 다시 적는다 — 기본 = 기동 때 판(`runningBuild`). */
|
|
194
|
+
restoreBuild?: (surfaceId: string) => void;
|
|
195
|
+
/** 박동 스케줄러 — 기본 setInterval(unref). 시험이 박동을 손으로 돌린다. */
|
|
196
|
+
driveHeartbeat?: (tick: () => void, ms: number) => (() => void);
|
|
197
|
+
/** SIGCONT 수신 훅(행 상실 단서) — 반환 = 해제. 기본 = process.on('SIGCONT'). */
|
|
198
|
+
onSigcont?: (fn: () => void) => (() => void);
|
|
199
|
+
/** 행 상실 관측 — 기본 = debug.log('tui.self-report', 'row-missing', data). */
|
|
200
|
+
logRowMissing?: (data: TuiRowMissingEvent) => void;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** 박동이 보는 자기 행 — `PtyManifestRow` 의 부분(재등록 뒤 frame·build 복원 확인에도 쓴다). */
|
|
204
|
+
export interface TuiOwnRowView {
|
|
205
|
+
readonly alive: boolean;
|
|
206
|
+
readonly frameAt?: number;
|
|
207
|
+
readonly build?: unknown;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** `tui.self-report` · `row-missing` 한 줄 — 살아 있는 TUI 의 manifest 행이 사라졌을 때(재등록 시도 결과 ⊕ 원인 단서). */
|
|
211
|
+
export interface TuiRowMissingEvent {
|
|
212
|
+
readonly surfaceId: string;
|
|
213
|
+
readonly pid: number;
|
|
214
|
+
/** 'absent' = 행이 없다 · 'closed' = 행은 있는데 alive=0 · 'lookup-failed' = 조회 자체가 실패(재등록 안 함). */
|
|
215
|
+
readonly state: 'absent' | 'closed' | 'lookup-failed';
|
|
216
|
+
/** 마지막으로 자기 행을 «본» 시각(등록·재등록 포함). */
|
|
217
|
+
readonly lastSeenAt: number;
|
|
218
|
+
readonly sinceMs: number;
|
|
219
|
+
/** 직전 박동과의 간격 — 박동 주기보다 훨씬 크면 그 사이 프로세스가 멈췄다(SIGSTOP·SIGTTIN·이벤트 루프 정체). */
|
|
220
|
+
readonly gapMs: number;
|
|
221
|
+
readonly heartbeatMs: number;
|
|
222
|
+
/** 마지막 SIGCONT 시각(없으면 null) — `lastSeenAt` 뒤면 «정지 → 재개» 사이에 걷혔다는 단서. */
|
|
223
|
+
readonly sigcontAt: number | null;
|
|
224
|
+
readonly sigcontSinceLastSeen: boolean;
|
|
225
|
+
readonly reRegistered: boolean;
|
|
226
|
+
/** 재등록이 비운 frame 칸에 마지막 화면을 다시 적었나(`pty snapshot` 이 바로 닿는다). */
|
|
227
|
+
readonly frameRestored: boolean;
|
|
228
|
+
/** 재등록이 비운 실행 판(build) 칸을 다시 적었나(다시 읽어 확인). */
|
|
229
|
+
readonly buildRestored: boolean;
|
|
230
|
+
readonly error?: string;
|
|
190
231
|
}
|
|
191
232
|
|
|
192
233
|
export type TuiControlInitStage = 'create-target' | 'register-target' | 'start-poller' | 'publish-manifest';
|
|
@@ -292,8 +333,11 @@ export function startTuiSelfReport(deps: TuiSelfReportDeps = {}): () => void {
|
|
|
292
333
|
// The manifest row is published only after both input capabilities are
|
|
293
334
|
// live. A listed TUI therefore always has a registered target and poller.
|
|
294
335
|
|
|
336
|
+
// 마지막으로 내보낸 화면 — 재등록이 frame 칸을 비우면 다시 적는다(거울은 바뀐 화면만 내보내 idle 이면 영영 빈 칸).
|
|
337
|
+
let lastEmittedText: string | null = null;
|
|
295
338
|
const emitText = (text: string, cols: number, rows: number): void => {
|
|
296
339
|
const at = now();
|
|
340
|
+
lastEmittedText = text;
|
|
297
341
|
const frame: SelfReportFrame = { surfaceId, instance, kind: 'tui', mode: 'self-report', text, cols, rows, at, ...(runId ? { runId } : {}) };
|
|
298
342
|
try { publishFrame(frame); } catch { /* fail-soft */ }
|
|
299
343
|
// `at` is shared with the manifest write → its internal throttle keys
|
|
@@ -340,16 +384,100 @@ export function startTuiSelfReport(deps: TuiSelfReportDeps = {}): () => void {
|
|
|
340
384
|
}
|
|
341
385
|
|
|
342
386
|
// Heartbeat so a live-but-idle TUI isn't culled by reapStale.
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
387
|
+
// ⭐ 박동마다 자기 행을 본다 — 남이 걷어 간 행(정지 중 stale 수거 등)을 같은 박동에서 다시 세운다.
|
|
388
|
+
// 행이 없으면 pty text/key/snapshot·우편 깨움이 이 TUI 에 영영 안 닿는다(#75 · #84).
|
|
389
|
+
// 행 등록을 갈아 끼운 호출자(시험)는 실 manifest 를 안 읽는다 — 기본 조회는 기본 행 등록과 짝일 때만.
|
|
390
|
+
const lookupRow: (id: string) => TuiOwnRowView | null = deps.lookupRow
|
|
391
|
+
?? (deps.registerRow ? () => ({ alive: true }) : (id: string) => getPtyManifest(id, { strict: true }));
|
|
392
|
+
const restoreBuild = deps.restoreBuild ?? (deps.registerRow ? () => {} : (id: string) => { updatePtyManifestBuild(id, runningBuild()); });
|
|
393
|
+
const logRowMissing = deps.logRowMissing ?? ((data: TuiRowMissingEvent) => debug.log('tui.self-report', 'row-missing', data));
|
|
394
|
+
const rowNickname = deps.nickname?.trim() || undefined;
|
|
395
|
+
let lastSeenAt = now();
|
|
396
|
+
let lastBeatAt = lastSeenAt;
|
|
397
|
+
let sigcontAt: number | null = null;
|
|
398
|
+
let stopSigcont: () => void = () => {};
|
|
399
|
+
try {
|
|
400
|
+
stopSigcont = (deps.onSigcont ?? ((fn) => {
|
|
401
|
+
process.on('SIGCONT', fn);
|
|
402
|
+
return () => { process.off('SIGCONT', fn); };
|
|
403
|
+
}))(() => { sigcontAt = now(); });
|
|
404
|
+
} catch { /* fail-soft — 단서일 뿐 */ }
|
|
346
405
|
let stopped = false;
|
|
406
|
+
const beat = (): void => {
|
|
407
|
+
if (stopped) return;
|
|
408
|
+
const at = now();
|
|
409
|
+
const prevSeenAt = lastSeenAt;
|
|
410
|
+
const gapMs = at - lastBeatAt;
|
|
411
|
+
lastBeatAt = at;
|
|
412
|
+
let state: TuiRowMissingEvent['state'] | null = null;
|
|
413
|
+
let error: string | undefined;
|
|
414
|
+
try {
|
|
415
|
+
const row = lookupRow(surfaceId);
|
|
416
|
+
if (!row) state = 'absent';
|
|
417
|
+
else if (!row.alive) state = 'closed';
|
|
418
|
+
} catch (e) {
|
|
419
|
+
state = 'lookup-failed';
|
|
420
|
+
error = e instanceof Error ? e.message : String(e);
|
|
421
|
+
}
|
|
422
|
+
if (state === null) {
|
|
423
|
+
lastSeenAt = at;
|
|
424
|
+
try { heartbeat(surfaceId, at); } catch { /* fail-soft */ }
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
let reRegistered = false;
|
|
428
|
+
let frameRestored = false;
|
|
429
|
+
let buildRestored = false;
|
|
430
|
+
if (state === 'lookup-failed') {
|
|
431
|
+
// ⛔ 실패를 «없다»로 읽지 않는다 — 재등록 없이 평소 박동만.
|
|
432
|
+
try { heartbeat(surfaceId, at); } catch { /* fail-soft */ }
|
|
433
|
+
} else {
|
|
434
|
+
try {
|
|
435
|
+
registerRow(surfaceId, at, rowNickname);
|
|
436
|
+
// 기본 행 등록은 fail-soft(조용히 삼킨다) — «다시 세웠다» 는 다시 읽어서만 말한다.
|
|
437
|
+
reRegistered = lookupRow(surfaceId)?.alive === true;
|
|
438
|
+
if (!reRegistered) throw new Error('row-still-missing-after-register');
|
|
439
|
+
lastSeenAt = at;
|
|
440
|
+
// 재등록은 실행 판·턴 칸을 비운다 — 판은 기동 때 값으로 다시 적는다. 턴은 비운 채(unknown) 둔다:
|
|
441
|
+
// 녹음기를 다시 열면 «idle» 을 적는데, 턴 도중이면 거짓 idle 이 깨움을 끼어들게 한다. 다음 턴 변화가 채운다.
|
|
442
|
+
const restoreErrors: string[] = [];
|
|
443
|
+
try { restoreBuild(surfaceId); } catch (e) { restoreErrors.push(`build: ${e instanceof Error ? e.message : String(e)}`); }
|
|
444
|
+
if (lastEmittedText !== null) {
|
|
445
|
+
try { writeFrame(surfaceId, lastEmittedText, at); } catch (e) { restoreErrors.push(`frame: ${e instanceof Error ? e.message : String(e)}`); }
|
|
446
|
+
}
|
|
447
|
+
// 기본 쓰기도 fail-soft — «복원했다» 는 다시 읽어서만 말한다.
|
|
448
|
+
try {
|
|
449
|
+
const after = lookupRow(surfaceId);
|
|
450
|
+
frameRestored = lastEmittedText !== null && (after?.frameAt ?? 0) >= at;
|
|
451
|
+
buildRestored = after?.build != null;
|
|
452
|
+
} catch (e) { restoreErrors.push(`verify: ${e instanceof Error ? e.message : String(e)}`); }
|
|
453
|
+
if (restoreErrors.length) error = restoreErrors.join('; ');
|
|
454
|
+
} catch (e) {
|
|
455
|
+
error = e instanceof Error ? e.message : String(e);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
try {
|
|
459
|
+
logRowMissing({
|
|
460
|
+
surfaceId, pid: process.pid, state, lastSeenAt: prevSeenAt, sinceMs: at - prevSeenAt, gapMs, heartbeatMs,
|
|
461
|
+
sigcontAt, sigcontSinceLastSeen: sigcontAt !== null && sigcontAt >= prevSeenAt,
|
|
462
|
+
reRegistered, frameRestored, buildRestored, ...(error ? { error } : {}),
|
|
463
|
+
});
|
|
464
|
+
} catch { /* fail-soft diagnostic */ }
|
|
465
|
+
};
|
|
466
|
+
const stopHeartbeat = (deps.driveHeartbeat ?? ((tick, ms) => {
|
|
467
|
+
// setImmediate 로 한 칸 미룬다 — 정지(SIGSTOP·SIGTTIN)에서 풀리면 밀린 타이머가 SIGCONT 처리기보다 «먼저» 돈다
|
|
468
|
+
// (WSL bun 실측). 미뤄야 같은 박동의 row-missing 이 sigcontAt 을 본다.
|
|
469
|
+
const t = setInterval(() => { setImmediate(tick); }, ms);
|
|
470
|
+
(t as { unref?: () => void }).unref?.();
|
|
471
|
+
return () => clearInterval(t);
|
|
472
|
+
}))(beat, heartbeatMs);
|
|
473
|
+
|
|
347
474
|
const stop = (): void => {
|
|
348
475
|
if (stopped) return;
|
|
349
476
|
stopped = true;
|
|
350
477
|
try { stopSource(); } catch { /* fail-soft — unregisters observer / clears tick timer */ }
|
|
351
478
|
try { mirror?.stop(); } catch { /* fail-soft — restores stdout.write */ }
|
|
352
|
-
|
|
479
|
+
try { stopHeartbeat(); } catch { /* fail-soft */ }
|
|
480
|
+
try { stopSigcont(); } catch { /* fail-soft */ }
|
|
353
481
|
try { stopRunState(); } catch { /* fail-soft */ }
|
|
354
482
|
wakePollerStopped = true;
|
|
355
483
|
try { stopWakePoller(); } catch { /* fail-soft */ }
|