elanous 0.2.34 → 0.2.35
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/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{5014f970-22bef0b5210f7d60.js → 0368f25d-ad84af92fefee68f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
- package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{2124.ed5bf480cea7f85b.js → 1530.0e612369b6fd7ea0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
- package/apps/pwa/out/_next/static/chunks/1674.2a65fd5668e1cc5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
- package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
- package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1993-c0007b7ad0c0ef41.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.js → 2018.a741297bce759490.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2625.5d870aa999f33db1.js +34 -0
- package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
- package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
- package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
- package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1644.35dd25240ae24e4b.js → 3408.21d1570602f4b6c0.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3121.779fafe3e44612c5.js → 3589.5444a06bcf6e775c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9131-fce7256c4180c4a5.js → 3677-4215f826f6aa68e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
- package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4346.8601952e73bf5803.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6053-d893974de92e6198.js → 4441-875b97f5821ed58a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{1895-60ed0e341c658bd4.js → 4705-194e64e47ca0fbdb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.js → 4718-17d2af636796a330.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7431.3051e9b8a4372d2d.js → 5101.e32282718f99ed6f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{2987-30cf9c2eb7b8bdd5.js → 5483-dd5d7697f6bdb106.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/56d372f2.681ab4ec4c998fae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7386.5d8e7e42e818dfb6.js → 5852.db1f7449f4f74612.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
- package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3110.0a7065f25c841818.js → 6236.e18cced2d5ba6afb.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
- package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
- package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6b89c8bd.24df687a820500b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
- package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{7005.1623d2aea78eb85f.js → 7385.50a308a477bdfc21.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.js → 7644.17e37ba6f1d4226e.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8219.baa715d1deee80e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7193-cf355cca5ba6c5d5.js → 8437-8d5492094b166cfa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2554.3b5e200f5f5cfcd6.js → 8444.4c26b379ca2b9596.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
- package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
- package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2547.dd27303624cb4da8.js → 8637.47f5b35afcae5e6b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9550.d5f76828f972058c.js → 9214.63a510d39178e997.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
- package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8548.036c344973968847.js → 938.66ad1ef0e5abae1c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3414.172ad4ca2d9b08e8.js → 9512.5a76207a730e0491.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/967-2aa39b2d04b4c690.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6740.43de73fc427c9fe2.js → 9952.5daf5f94063a2b3e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-406b47745b53f269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-d7bff0f0905a662c.js → page-26e6c18a1a750cf6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-47c5d4db587266bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-df3445b207ceceab.js → page-dc0a532f5b9196ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9a8cb466.cc9fc9e6e46038aa.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4fa33ebd.21c1bd5b294496e6.js → cbe38a15.5a032598e39970c6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{abb4b98b.163e0f56e84ae35d.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.js → da5176c6.6773b6c5994e1d99.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/bin/elanous.mjs +3 -2
- package/catalog/providers/opengateway.yaml +25 -0
- package/docs/goal-context/01-goal-authoring-checks.md +8 -0
- package/docs/goal-context/03-verification-menu.md +24 -0
- package/docs/goal-context/04-mock-scenarios.md +100 -0
- package/docs/goal-context/README.md +4 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/default-loop.yaml +57 -3
- package/graphs/document-loop.yaml +51 -3
- package/graphs/implement-loop.yaml +53 -4
- package/graphs/journey/ta-journey.yaml +11 -1
- package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
- package/graphs/journey/units/author-dialogue/observe.ts +96 -0
- package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
- package/graphs/operate-loop.yaml +51 -3
- package/graphs/research-loop.yaml +137 -3
- package/graphs/test-diet/test-diet.yaml +3 -0
- package/package.json +1 -1
- package/scripts/coord-role-pack.ts +19 -6
- package/scripts/hq/standby-snapshot.ts +17 -12
- package/scripts/release-loop/docs-land-node.ts +21 -5
- package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
- package/scripts/release-loop/gate-node.ts +181 -22
- package/scripts/release-loop/gate-partial.ts +65 -11
- package/scripts/release-loop/gate-radius-live.ts +177 -0
- package/scripts/release-loop/gate-radius-shadow.ts +1 -1
- package/scripts/release-loop/node-verdict.ts +12 -1
- package/scripts/release-loop/npm-publish-node.ts +66 -12
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
- package/scripts/release-loop/pwa-remote.ts +166 -0
- package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
- package/scripts/release-loop/resume-release.ts +41 -4
- package/scripts/release-loop/unattended-release.ts +2 -0
- package/scripts/test-diet/lib.ts +6 -1
- package/scripts/test-diet/node.ts +194 -13
- package/scripts/ux-sim.ts +39 -0
- package/src/agent/self-ambient-cache.ts +8 -0
- package/src/agent-substrate/acp-reviewer.ts +39 -4
- package/src/agent-substrate/pr-reviewer.ts +17 -0
- package/src/agent-substrate/self-review-cli.ts +62 -13
- package/src/autopilot/pr-manager.ts +215 -36
- package/src/budget/run-usage-rollup.ts +1 -0
- package/src/chat/index.ts +0 -2
- package/src/chat/pickers/modal-runtime.ts +10 -27
- package/src/cli/agent-cli.ts +13 -2
- package/src/cli/doctor-cli.ts +4 -1
- package/src/cli/light-entry-route.ts +46 -6
- package/src/cli/pod-cli.ts +77 -3
- package/src/cli/pr-cli.ts +5 -2
- package/src/cli/pr-land-pod-shadow-job.ts +3 -0
- package/src/cli/release-checklist-read-cli.ts +79 -0
- package/src/cli/release-cli.ts +72 -102
- package/src/cli/remote-resolve.ts +1 -1
- package/src/cli/root-tui-entry.ts +48 -0
- package/src/cli/sim-cli.ts +22 -0
- package/src/cli/tasks-cli.ts +540 -31
- package/src/cli/usage-cli.ts +13 -11
- package/src/clipboard/history.ts +179 -13
- package/src/config.ts +8 -1
- package/src/dashboard/chat/acp-chat.ts +8 -0
- package/src/dashboard/index.ts +78 -10
- package/src/dashboard/render/theme-resolver.ts +33 -4
- package/src/domains/schedule-registry.ts +16 -2
- package/src/git-fs/idle-refresh.ts +76 -0
- package/src/git-fs/index.ts +18 -7
- package/src/git-fs/worktree.ts +42 -4
- package/src/graph-kinds/registry.ts +2 -2
- package/src/graph-runner/runner.ts +153 -10
- package/src/grok/credential.ts +10 -3
- package/src/harness/harness-cli-command.ts +112 -28
- package/src/harness/harness-incidents.ts +33 -0
- package/src/harness/launch-utterance-ledger.ts +208 -0
- package/src/impl-discipline/detector.ts +16 -4
- package/src/impl-discipline/system-prompt.ts +11 -0
- package/src/impl-discipline/types.ts +2 -2
- package/src/index.ts +496 -143
- package/src/intake-plane/already-built-hint.ts +4 -2
- package/src/intake-plane/requirement-funnel.ts +29 -1
- package/src/light-cli.ts +27 -11
- package/src/llm/opengateway-models.ts +11 -0
- package/src/llm/provider-credentials.ts +14 -0
- package/src/llm/provider-detect.ts +8 -1
- package/src/llm/runtime-model-family.ts +2 -1
- package/src/llm.ts +213 -56
- package/src/model-tier/llm-tier-map.ts +15 -1
- package/src/native-tool-catalog.ts +15 -1
- package/src/nexus/api/loop-resources.ts +13 -1
- package/src/oauth/codex.ts +7 -0
- package/src/ops/overview-collect.ts +18 -3
- package/src/ops/overview.ts +20 -7
- package/src/pr-tool/census.ts +261 -27
- package/src/pty-shell/pty-manifest.ts +7 -0
- package/src/release-loop/checklist.ts +24 -0
- package/src/release-loop/landed-but-yellow.ts +129 -5
- package/src/release-loop/light-rc.ts +1 -0
- package/src/release-loop/rehearsal.ts +2 -2
- package/src/repl/index.ts +174 -17
- package/src/repl/ops-msg-bridge.ts +32 -0
- package/src/self-dev/ask-launch-flow.ts +44 -5
- package/src/self-dev/cli-help-text.ts +17 -0
- package/src/self-dev/dev-cli.ts +11 -9
- package/src/self-dev/draft-residue.ts +37 -1
- package/src/self-dev/draft-sweep.ts +137 -11
- package/src/self-dev/draft-triage-rules.ts +107 -0
- package/src/self-dev/fleet-reduce.ts +3 -2
- package/src/self-dev/graph-front-nodes.ts +112 -0
- package/src/self-dev/graph-journey-nodes.ts +1 -0
- package/src/self-dev/harness-run-cli.ts +3 -15
- package/src/self-dev/orchestrate-cli-text.ts +10 -0
- package/src/self-dev/review-provider-fallback.ts +35 -1
- package/src/self-dev/self-orchestrate-runtime.ts +1 -11
- package/src/self-dev/shard-aggregate.ts +42 -5
- package/src/self-dev/shard-run.ts +8 -1
- package/src/self-implement/blocked-draft-policy.ts +20 -0
- package/src/self-implement/classify-shadow.ts +3 -7
- package/src/self-implement/doctor-visit.ts +18 -1
- package/src/self-implement/gate-baseline.ts +56 -17
- package/src/self-implement/gate-cli.ts +1 -0
- package/src/self-implement/gate-remote.ts +31 -20
- package/src/self-implement/goal-author-decompose.ts +275 -47
- package/src/self-implement/goal-author.ts +250 -0
- package/src/self-implement/goal-elaborate.ts +295 -0
- package/src/self-implement/goal-refine.ts +270 -0
- package/src/self-implement/graph-overlay-yaml.ts +14 -3
- package/src/self-implement/orchestrator.ts +152 -45
- package/src/self-implement/rework-budget-judgment.ts +5 -8
- package/src/self-implement/run-stop.ts +10 -1
- package/src/self-implement/running-runs.ts +29 -1
- package/src/self-implement/scope-adjacency.ts +113 -0
- package/src/self-implement/seams.ts +127 -24
- package/src/self-implement/stop-autoheal.ts +87 -1
- package/src/session-runtime/index.ts +1 -1
- package/src/setup/llm-env-detect.ts +5 -0
- package/src/skills/tools/agent.ts +140 -14
- package/src/skills/tools/msg-ask.ts +100 -0
- package/src/skills/tools/ops-ledger.ts +2 -1
- package/src/steward/hold-hygiene.ts +24 -6
- package/src/steward/triage-budget.ts +194 -0
- package/src/steward/triage.ts +20 -3
- package/src/task-agent/actions.ts +69 -1
- package/src/task-agent/green-sweep.ts +4 -0
- package/src/task-agent/live-moves.ts +160 -4
- package/src/task-agent/parent-host.ts +123 -3
- package/src/task-agent/shadow.ts +7 -1
- package/src/task-agent/task-hand.ts +54 -41
- package/src/task-agent/tier-split.ts +127 -0
- package/src/task-agent/work-order-build.ts +2 -0
- package/src/task-agent/work-order.ts +3 -2
- package/src/task-orchestrator/generator-prompt.ts +60 -11
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +33 -0
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-command-job.ts +45 -7
- package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
- package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
- package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
- package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +37 -5
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +368 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +23 -0
- package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
- package/src/tui/README.md +2 -0
- package/src/tui/chat/background-job-status.ts +54 -0
- package/src/tui/chat/log-view.ts +80 -0
- package/src/tui/entry.ts +406 -0
- package/src/tui/input/composer.ts +144 -0
- package/src/tui/seat-mail-boot.ts +59 -0
- package/src/tui/slash/compact.ts +100 -0
- package/src/tui/slash/new-session.ts +35 -0
- package/src/tui-client/local-chat-turn.ts +239 -0
- package/src/tui-client/local-harness-command.ts +63 -0
- package/src/tui-client/local-provider-command.ts +184 -0
- package/src/user-config.ts +4 -2
- package/src/ux-sim/event-monkey.ts +378 -0
- package/src/ux-sim/fake-bin.ts +42 -7
- package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
- package/src/ux-sim/fault-pod-codex-503.ts +211 -0
- package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
- package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
- package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
- package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
- package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
- package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +0 -34
- package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3498.cf2a15a8a9e5b926.js +0 -226
- package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +0 -32
- package/apps/pwa/out/_next/static/chunks/3837.722e053fb9f321ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
- package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
- package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
- package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
- package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5446.edf141cff9ef647d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
- package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
- package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
- package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +0 -41
- package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
- package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
- package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
- package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
- package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
- package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ffdc3a04.b9c23c1b28dd4a96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
- /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
package/src/oauth/codex.ts
CHANGED
|
@@ -458,6 +458,10 @@ export async function loadFreshCodexAuthState(
|
|
|
458
458
|
});
|
|
459
459
|
return state;
|
|
460
460
|
}
|
|
461
|
+
if (process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY === '1') {
|
|
462
|
+
observeCodexAuth('no-credential', { storeKey: account.storeKey, mirrorPath: mirrorPath ?? null, reason: 'access-only-expiring' });
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
461
465
|
observeCodexAuth('refresh-start', {
|
|
462
466
|
storeKey: account.storeKey, remainingSeconds: remainingSeconds(state),
|
|
463
467
|
mirrorPath: mirrorPath ?? null, bufferMs: CODEX_REFRESH_BUFFER_MS,
|
|
@@ -602,6 +606,9 @@ export async function refreshCodexAccountHome(
|
|
|
602
606
|
now?: () => number;
|
|
603
607
|
} = {},
|
|
604
608
|
): Promise<CodexAccountRefreshResult> {
|
|
609
|
+
if (process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY === '1') {
|
|
610
|
+
return { ok: false, kind: 'no-tokens', message: '원격 access 미러는 refresh 권한이 없다' };
|
|
611
|
+
}
|
|
605
612
|
// ⛔ The CEO's default account (~/.codex) is shared with the official CLI — refreshing it here
|
|
606
613
|
// rotates the refresh token out from under that CLI. Named accounts only.
|
|
607
614
|
if (name === DEFAULT_CODEX_ACCOUNT) {
|
|
@@ -13,7 +13,7 @@ import type { ResourceView } from '../control-plane/ledger.js';
|
|
|
13
13
|
import { cardPrNumber, type TaskCard } from '../task-agent/task-hand.js';
|
|
14
14
|
import { measureLandingThroughput, type LandingThroughput } from '../task-agent/cover.js';
|
|
15
15
|
import {
|
|
16
|
-
okCell, unmeasured, type Cell, type CapacityInfo, type ChecklistCounts, type LaunchableInfo, type LoopRow, type MachineRow,
|
|
16
|
+
okCell, unmeasured, type Cell, type CapacityInfo, type ChecklistCounts, type IoPressure, type LaunchableInfo, type LoopRow, type MachineRow,
|
|
17
17
|
type OverviewSnapshot, type OwnerTaskRow, type ParentsInfo, type PodMemberRow, type ReleaseRunInfo, type ScheduleInfo,
|
|
18
18
|
type SchedulerMetrics,
|
|
19
19
|
} from './overview.js';
|
|
@@ -161,6 +161,20 @@ function collectRelease(root: string, version: string | null, schedules: Release
|
|
|
161
161
|
return { version: versionCell, run, schedule, checklist };
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* 하트비트가 실어 온 I/O 압박(diskIo.io · PSI 10초 평균)을 꺼낸다.
|
|
166
|
+
* 못 잼(맥 · /proc/pressure/io 없음 · 항목 빠짐)은 null — «0%» 로 굳히지 않는다.
|
|
167
|
+
*/
|
|
168
|
+
function ioPressureOf(diskIo: unknown): IoPressure | null {
|
|
169
|
+
const cell = (diskIo as { io?: { status?: unknown; value?: { someAvg10?: unknown; fullAvg10?: unknown } } } | null | undefined)?.io;
|
|
170
|
+
if (!cell || cell.status !== 'ok') return null;
|
|
171
|
+
const someAvg10 = cell.value?.someAvg10;
|
|
172
|
+
const fullAvg10 = cell.value?.fullAvg10;
|
|
173
|
+
if (typeof someAvg10 !== 'number' || !Number.isFinite(someAvg10)) return null;
|
|
174
|
+
if (typeof fullAvg10 !== 'number' || !Number.isFinite(fullAvg10)) return null;
|
|
175
|
+
return { someAvg10, fullAvg10 };
|
|
176
|
+
}
|
|
177
|
+
|
|
164
178
|
function collectMachines(root: string, ledgerRows: ResourceView[] | Error, poolSpec: string | null, psOut: string | Error, now: number): OverviewSnapshot['machines'] {
|
|
165
179
|
const expected = new Set<string>();
|
|
166
180
|
const pods: PodMemberRow[] = [];
|
|
@@ -181,7 +195,7 @@ function collectMachines(root: string, ledgerRows: ResourceView[] | Error, poolS
|
|
|
181
195
|
for (const r of machines) expected.add(r.machine);
|
|
182
196
|
for (const name of [...expected].sort()) {
|
|
183
197
|
const row = machines.find((r) => r.machine === name);
|
|
184
|
-
const load = (row?.attrs as { load?: { loadAvg?: number[]; cpuCount?: number; freeMem?: number; totalMem?: number; observedAt?: number } } | undefined)?.load;
|
|
198
|
+
const load = (row?.attrs as { load?: { loadAvg?: number[]; cpuCount?: number; freeMem?: number; totalMem?: number; observedAt?: number; diskIo?: unknown } } | undefined)?.load;
|
|
185
199
|
if (!row || !load || !Array.isArray(load.loadAvg)) { hosts.push({ name, load: unmeasured('control ledger heartbeat', '하트비트 없음') }); continue; }
|
|
186
200
|
const observed = typeof load.observedAt === 'number' ? load.observedAt : row.observedAt;
|
|
187
201
|
const [l1, l5, l15] = load.loadAvg;
|
|
@@ -192,7 +206,8 @@ function collectMachines(root: string, ledgerRows: ResourceView[] | Error, poolS
|
|
|
192
206
|
}
|
|
193
207
|
const age = Math.max(0, Math.round((now - observed) / 1000));
|
|
194
208
|
const value = { load1: l1, load5: l5, load15: l15, cpuCount: load.cpuCount,
|
|
195
|
-
freeGb: load.freeMem / GB, totalGb: load.totalMem / GB, ageSeconds: age
|
|
209
|
+
freeGb: load.freeMem / GB, totalGb: load.totalMem / GB, ageSeconds: age,
|
|
210
|
+
ioPressure: ioPressureOf(load.diskIo) };
|
|
196
211
|
hosts.push({ name, load: age > HEARTBEAT_STALE_S
|
|
197
212
|
? unmeasured('control ledger heartbeat', `낡음(${age}초)`, iso(observed))
|
|
198
213
|
: okCell(value, 'control ledger heartbeat', iso(observed)) });
|
package/src/ops/overview.ts
CHANGED
|
@@ -51,7 +51,14 @@ export interface LaunchableInfo {
|
|
|
51
51
|
interim: true;
|
|
52
52
|
}
|
|
53
53
|
export interface CapacityInfo { podUsed: number; podTarget: number; localUsed: number; localMax: number; free: number }
|
|
54
|
-
|
|
54
|
+
/** 리눅스 PSI(/proc/pressure/io · 10초 평균) — 적어도 한 작업이 I/O 를 기다린 시간 비율(%). 100 이면 늘 막혀 있었다. */
|
|
55
|
+
export interface IoPressure { someAvg10: number; fullAvg10: number }
|
|
56
|
+
|
|
57
|
+
export interface MachineLoad {
|
|
58
|
+
load1: number; load5: number; load15: number; cpuCount: number; freeGb: number; totalGb: number; ageSeconds: number;
|
|
59
|
+
/** 하트비트가 실어 온 I/O 압박. 못 잼(맥·/proc/pressure/io 없음)은 null — 축에서 빼지 «넉넉»으로 읽지 않는다. */
|
|
60
|
+
ioPressure?: IoPressure | null;
|
|
61
|
+
}
|
|
55
62
|
export interface MachineRow { name: string; load: Cell<MachineLoad> }
|
|
56
63
|
export interface PodMemberRow { context: string; capacity: number; occupied: Cell<number> }
|
|
57
64
|
export interface ParentsInfo { count: number; staleOver6h: number; oldestHours: number | null }
|
|
@@ -100,10 +107,10 @@ export interface OverviewSnapshot {
|
|
|
100
107
|
|
|
101
108
|
export interface VerdictResult { verdict: Verdict; reasons: string[]; nextActions: string[] }
|
|
102
109
|
|
|
103
|
-
/** 부하/코어가 이 값을 넘으면 «기계 압박»(흐름 저하의 사유).
|
|
110
|
+
/** 부하/코어가 이 값을 넘으면 «기계 압박»(흐름 저하의 사유). */
|
|
104
111
|
export const LOAD_PER_CORE_PRESSURE = 3;
|
|
105
112
|
|
|
106
|
-
/** 자원 지도의 축 어휘(닫힌 집합 · RES-FLOOR-BINDING).
|
|
113
|
+
/** 자원 지도의 축 어휘(닫힌 집합 · RES-FLOOR-BINDING). 게이트 예약은 이 칸에 원천이 없어 늘 제외다. */
|
|
107
114
|
export type ResourceKind = 'memory' | 'cpu' | 'io' | 'slots' | 'gate';
|
|
108
115
|
|
|
109
116
|
/** 구속 조건 — 남은 비율이 최소인 축. 남은 비율 = 남은 양/전체 양(CPU 는 압박선 LOAD_PER_CORE_PRESSURE×코어를 전체로 본다). */
|
|
@@ -111,7 +118,7 @@ export interface ResourceBinding {
|
|
|
111
118
|
kind: ResourceKind;
|
|
112
119
|
label: string;
|
|
113
120
|
remainingRatio: number;
|
|
114
|
-
/** 남은 양/전체 양의 사람 표기 — `5/64GB` · `0/54코어(압박선 3/코어)` · `0/46자리`. */
|
|
121
|
+
/** 남은 양/전체 양의 사람 표기 — `5/64GB` · `0/54코어(압박선 3/코어)` · `4/100(압박 96% · full 61% · 10초 평균)` · `0/46자리`. */
|
|
115
122
|
remainingText: string;
|
|
116
123
|
}
|
|
117
124
|
|
|
@@ -125,8 +132,9 @@ function remainingAmount(n: number): string {
|
|
|
125
132
|
|
|
126
133
|
/**
|
|
127
134
|
* 구속 조건 규칙(RES-FLOOR-BINDING) — 메모리·CPU·I/O·슬롯·게이트 예약 중 «남은 비율 최소»인 축이 흐름을 묶는다.
|
|
128
|
-
* 못 잰 축(하트비트 없는 호스트 · 용량 못 잼 ·
|
|
129
|
-
*
|
|
135
|
+
* 못 잰 축(하트비트 없는 호스트 · 용량 못 잼 · 하트비트에 PSI 가 없는 I/O · 원천이 없는 게이트 예약)은 후보에서 뺀다
|
|
136
|
+
* — «넉넉»으로도 «바닥»으로도 읽지 않는다.
|
|
137
|
+
* 측정 축이 하나도 없으면 null. 동율은 정해진 순서(호스트 순 메모리→CPU→I/O, 그 다음 슬롯)의 첫 축이 이긴다.
|
|
130
138
|
*/
|
|
131
139
|
export function bindingResource(s: OverviewSnapshot): ResourceBinding | null {
|
|
132
140
|
const candidates: ResourceBinding[] = [];
|
|
@@ -142,6 +150,11 @@ export function bindingResource(s: OverviewSnapshot): ResourceBinding | null {
|
|
|
142
150
|
const remaining = Math.max(0, cpuCap - l.load5);
|
|
143
151
|
candidates.push({ kind: 'cpu', label: `${host.name} CPU`, remainingRatio: ratio01(remaining / cpuCap), remainingText: `${remainingAmount(remaining)}/${cpuCap.toFixed(0)}코어(압박선 ${LOAD_PER_CORE_PRESSURE}/코어)` });
|
|
144
152
|
}
|
|
153
|
+
const io = l.ioPressure;
|
|
154
|
+
if (io) {
|
|
155
|
+
const remaining = Math.max(0, 100 - io.someAvg10);
|
|
156
|
+
candidates.push({ kind: 'io', label: `${host.name} I/O`, remainingRatio: ratio01(remaining / 100), remainingText: `${remainingAmount(remaining)}/100(압박 ${remainingAmount(io.someAvg10)}% · full ${remainingAmount(io.fullAvg10)}% · 10초 평균)` });
|
|
157
|
+
}
|
|
145
158
|
}
|
|
146
159
|
const capacity = s.tasks.capacity.value;
|
|
147
160
|
if (capacity && capacity.podTarget + capacity.localMax > 0) {
|
|
@@ -280,7 +293,7 @@ export function renderOverview(s: OverviewSnapshot, v: VerdictResult, meta: { el
|
|
|
280
293
|
lines.push(`일꾼 ${owners} · 끝 ${show(s.tasks.done, String)}`);
|
|
281
294
|
lines.push(` 발사 가능 ${show(s.tasks.launchable, (l) => `${l.count}${l.interim ? '(임시 술어)' : ''} · 대상 경로 없음 ${l.skipped.noTargetPath} · 선행 미완 ${l.skipped.predecessorOpen} · 이미 넘김 ${l.skipped.alreadyHanded}`)}`);
|
|
282
295
|
lines.push(` 빈 자리 ${show(s.tasks.capacity, (c) => `${c.free} (Pod ${c.podUsed}/${c.podTarget} · 로컬 ${c.localUsed}/${c.localMax})`)} [${s.tasks.capacity.source}]`);
|
|
283
|
-
const hosts = s.machines.hosts.map((h) => `${h.name} ${show(h.load, (l) => `${l.load1.toFixed(0)}/${l.cpuCount}코어 여유 ${l.freeGb.toFixed(0)}/${l.totalGb.toFixed(0)}GB (${l.ageSeconds}s 전)`)}`);
|
|
296
|
+
const hosts = s.machines.hosts.map((h) => `${h.name} ${show(h.load, (l) => `${l.load1.toFixed(0)}/${l.cpuCount}코어 여유 ${l.freeGb.toFixed(0)}/${l.totalGb.toFixed(0)}GB${l.ioPressure ? ` · I/O 압박 ${l.ioPressure.someAvg10}% · full ${l.ioPressure.fullAvg10}%` : ''} (${l.ageSeconds}s 전)`)}`);
|
|
284
297
|
lines.push(`기계 ${hosts.join(' · ') || '못 잼(하트비트 원장 비어 있음)'}`);
|
|
285
298
|
lines.push(` Pod ${s.machines.pods.map((p) => `${p.context} ${show(p.occupied, String)}/${p.capacity}`).join(' · ') || '못 잼(풀 설정 없음)'}`);
|
|
286
299
|
lines.push(` 하니스 부모(이 기계) ${show(s.machines.parents, (p) => `${p.count} · 6h 넘음 ${p.staleOver6h}${p.oldestHours !== null ? ` · 최고 ${p.oldestHours}h` : ''}`)}`);
|
package/src/pr-tool/census.ts
CHANGED
|
@@ -5,9 +5,13 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
6
6
|
import { withFileLockSync } from '../storage/file-lock.js';
|
|
7
7
|
import { resolveHostId } from '../platform/host-id.js';
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
8
9
|
|
|
9
10
|
export interface PrToolCommandResult { ok: boolean; out: string; err?: string }
|
|
10
11
|
export type PrToolCommand = (command: string, args: readonly string[], opts?: { cwd?: string }) => PrToolCommandResult;
|
|
12
|
+
export interface PrToolCall { command: string; args: readonly string[]; opts?: { cwd?: string } }
|
|
13
|
+
/** PR-CENSUS-PARALLEL: run every call with at most `concurrency` in flight; results stay in input order. */
|
|
14
|
+
export type PrToolParallelCommand = (calls: readonly PrToolCall[], concurrency: number) => PrToolCommandResult[];
|
|
11
15
|
export type Seat = 'OP' | 'TC' | 'MK' | 'UX';
|
|
12
16
|
export interface OpenPr {
|
|
13
17
|
number: number;
|
|
@@ -23,6 +27,8 @@ export interface OpenPr {
|
|
|
23
27
|
cellId: string | null;
|
|
24
28
|
cardId?: string | null;
|
|
25
29
|
cardMarkerPresent?: boolean;
|
|
30
|
+
/** «조각 i/N — 부모 <칸>» 표지가 있으면 그 조각 번호(없으면 null) — sibling-slice 판정용. */
|
|
31
|
+
slice?: { slice: number; total: number } | null;
|
|
26
32
|
hunks?: readonly DiffHunk[];
|
|
27
33
|
}
|
|
28
34
|
export type Inventory = { status: 'checked'; prs: readonly OpenPr[] } | { status: 'unknown'; reason: string };
|
|
@@ -35,6 +41,7 @@ export interface GuardReason { code: GuardCode; detail: string; prs?: readonly n
|
|
|
35
41
|
/** PR-GUARD-HUNK-WARN (대표 10-17): 줄 겹침은 기본 경고 — 착지 쪽 스마트 머지가 푼다. 'refuse' = 옛 거부 동작. */
|
|
36
42
|
export type HunkOverlapMode = 'refuse' | 'warn';
|
|
37
43
|
export interface GuardVerdict { status: 'allow' | 'refuse' | 'unknown'; reasons: readonly GuardReason[]; warnings: readonly GuardReason[];
|
|
44
|
+
sameCellConflicts?: readonly { pr: number; cardId: string | null; slice?: { slice: number; total: number } | null }[];
|
|
38
45
|
sameCellReuse?: { number: number; branch: string; headSha: string; cellId: string; cardId: string; legacyBound?: true } }
|
|
39
46
|
|
|
40
47
|
const SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
|
|
@@ -45,6 +52,126 @@ const MAX_FILES = 3000; // GitHub does not expose more than 3000 PR files.
|
|
|
45
52
|
const UNMEASURED_WINDOW_MS = 60 * 60 * 1000;
|
|
46
53
|
const UNMEASURED_ALLOW_COUNT = 3;
|
|
47
54
|
|
|
55
|
+
export const DEFAULT_DIFF_CONCURRENCY = 6;
|
|
56
|
+
const DIFF_CACHE_MAX = 2000;
|
|
57
|
+
const DIFF_CACHE_MAX_BYTES = 64 * 1024 * 1024;
|
|
58
|
+
const DIFF_CACHE_ENTRY_MAX_BYTES = 4 * 1024 * 1024;
|
|
59
|
+
const PARALLEL_CALL_TIMEOUT_MS = 120_000;
|
|
60
|
+
/** Whole pool ceiling, independent of the call count — a stuck pool fails (inventory unknown) instead of hanging the guard. */
|
|
61
|
+
const PARALLEL_POOL_TIMEOUT_MS = 10 * 60 * 1000;
|
|
62
|
+
const PARALLEL_MAX_BUFFER = 256 * 1024 * 1024;
|
|
63
|
+
|
|
64
|
+
/** `gh pr diff` patches keyed by PR number ⊕ head sha. A head sha fixes the diff, so a retry or a second guard
|
|
65
|
+
* call in the same process never refetches it. Bounded by entry count and total bytes (the oldest entry leaves
|
|
66
|
+
* first); a single patch above the per-entry limit is not cached at all. */
|
|
67
|
+
export class CensusDiffCache {
|
|
68
|
+
private readonly entries = new Map<string, { patch: string; bytes: number }>();
|
|
69
|
+
private totalBytes = 0;
|
|
70
|
+
constructor(private readonly max = DIFF_CACHE_MAX, private readonly maxBytes = DIFF_CACHE_MAX_BYTES,
|
|
71
|
+
private readonly entryMaxBytes = DIFF_CACHE_ENTRY_MAX_BYTES) {}
|
|
72
|
+
private key(number: number, headSha: string): string { return `${number}@${headSha}`; }
|
|
73
|
+
private drop(key: string): void {
|
|
74
|
+
const entry = this.entries.get(key);
|
|
75
|
+
if (!entry) return;
|
|
76
|
+
this.totalBytes -= entry.bytes;
|
|
77
|
+
this.entries.delete(key);
|
|
78
|
+
}
|
|
79
|
+
get(number: number, headSha: string): string | undefined { return this.entries.get(this.key(number, headSha))?.patch; }
|
|
80
|
+
set(number: number, headSha: string, patch: string): void {
|
|
81
|
+
const key = this.key(number, headSha);
|
|
82
|
+
this.drop(key);
|
|
83
|
+
const bytes = Buffer.byteLength(patch, 'utf8');
|
|
84
|
+
if (bytes > this.entryMaxBytes || bytes > this.maxBytes) return;
|
|
85
|
+
while (this.entries.size > 0 && (this.entries.size >= this.max || this.totalBytes + bytes > this.maxBytes)) {
|
|
86
|
+
const oldest = this.entries.keys().next().value;
|
|
87
|
+
if (oldest === undefined) break;
|
|
88
|
+
this.drop(oldest);
|
|
89
|
+
}
|
|
90
|
+
this.entries.set(key, { patch, bytes });
|
|
91
|
+
this.totalBytes += bytes;
|
|
92
|
+
}
|
|
93
|
+
get size(): number { return this.entries.size; }
|
|
94
|
+
get bytes(): number { return this.totalBytes; }
|
|
95
|
+
clear(): void { this.entries.clear(); this.totalBytes = 0; }
|
|
96
|
+
}
|
|
97
|
+
/** Process-lifetime cache for production callers (PR creation guard · `pr open-guard`). Tests pass their own. */
|
|
98
|
+
export const sharedCensusDiffCache = new CensusDiffCache();
|
|
99
|
+
export function resetCensusDiffCache(): void { sharedCensusDiffCache.clear(); }
|
|
100
|
+
|
|
101
|
+
// Runs inside a child `bun`/`node` so the synchronous inventory API can still fan out. stdin: { calls, concurrency,
|
|
102
|
+
// timeoutMs } · stdout: one result per call, input order. Each call runs in its own process group (detached) so a
|
|
103
|
+
// per-call timeout, or this pool ending on SIGTERM/SIGINT/SIGHUP from the outer ceiling, kills the whole group —
|
|
104
|
+
// no `gh` (or its children) outlives the pool.
|
|
105
|
+
const PARALLEL_SCRIPT = `
|
|
106
|
+
const { spawn } = require('node:child_process');
|
|
107
|
+
const live = new Set();
|
|
108
|
+
const killGroup = pid => { try { process.kill(-pid, 'SIGKILL'); } catch { try { process.kill(pid, 'SIGKILL'); } catch {} } };
|
|
109
|
+
const killAll = () => { for (const pid of live) killGroup(pid); live.clear(); };
|
|
110
|
+
for (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP']) process.on(signal, () => { killAll(); process.exit(124); });
|
|
111
|
+
process.on('exit', killAll);
|
|
112
|
+
let input = '';
|
|
113
|
+
process.stdin.setEncoding('utf8');
|
|
114
|
+
process.stdin.on('data', chunk => { input += chunk; });
|
|
115
|
+
process.stdin.on('end', () => {
|
|
116
|
+
const { calls, concurrency, timeoutMs } = JSON.parse(input);
|
|
117
|
+
const results = new Array(calls.length);
|
|
118
|
+
let next = 0;
|
|
119
|
+
const one = index => new Promise(resolve => {
|
|
120
|
+
const call = calls[index];
|
|
121
|
+
const out = []; const err = [];
|
|
122
|
+
let settled = false; let timedOut = false; let timer;
|
|
123
|
+
let child;
|
|
124
|
+
const finish = result => {
|
|
125
|
+
if (settled) return; settled = true; clearTimeout(timer);
|
|
126
|
+
if (child && child.pid) { killGroup(child.pid); live.delete(child.pid); }
|
|
127
|
+
results[index] = result; resolve();
|
|
128
|
+
};
|
|
129
|
+
try { child = spawn(call.command, call.args, { cwd: call.cwd || undefined, stdio: ['ignore', 'pipe', 'pipe'], detached: true }); }
|
|
130
|
+
catch (error) { results[index] = { ok: false, out: '', err: String(error && error.message || error) }; resolve(); return; }
|
|
131
|
+
if (child.pid) live.add(child.pid);
|
|
132
|
+
timer = setTimeout(() => { timedOut = true; if (child.pid) killGroup(child.pid); }, timeoutMs);
|
|
133
|
+
child.stdout.on('data', chunk => out.push(chunk));
|
|
134
|
+
child.stderr.on('data', chunk => err.push(chunk));
|
|
135
|
+
child.on('error', error => finish({ ok: false, out: '', err: String(error && error.message || error) }));
|
|
136
|
+
child.on('close', (code, signal) => finish({ ok: code === 0 && !signal && !timedOut, out: Buffer.concat(out).toString('utf8').trim(),
|
|
137
|
+
err: [Buffer.concat(err).toString('utf8').trim(), timedOut ? 'timed out after ' + timeoutMs + 'ms' : signal ? 'terminated by ' + signal : ''].filter(Boolean).join('\\n') }));
|
|
138
|
+
});
|
|
139
|
+
const worker = async () => { while (next < calls.length) { const index = next++; await one(index); } };
|
|
140
|
+
Promise.all(Array.from({ length: Math.max(1, Math.min(concurrency, calls.length)) }, worker))
|
|
141
|
+
.then(() => process.stdout.write(JSON.stringify(results)));
|
|
142
|
+
});
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
/** Real-spawn {@link PrToolParallelCommand}: one child runtime fans out the calls with a bounded pool. Any failure of
|
|
146
|
+
* the pool itself (including the fixed pool ceiling) returns every call as failed, so the caller's conservative
|
|
147
|
+
* unknown rule applies. `timeoutMs` = per call · `poolTimeoutMs` = whole pool (tests inject short values). */
|
|
148
|
+
export function spawnParallelCommands(calls: readonly PrToolCall[], options: { concurrency?: number; env?: NodeJS.ProcessEnv; timeoutMs?: number; poolTimeoutMs?: number } = {}): PrToolCommandResult[] {
|
|
149
|
+
if (calls.length === 0) return [];
|
|
150
|
+
const concurrency = Math.max(1, Math.floor(options.concurrency ?? DEFAULT_DIFF_CONCURRENCY));
|
|
151
|
+
const timeoutMs = options.timeoutMs ?? PARALLEL_CALL_TIMEOUT_MS;
|
|
152
|
+
const failAll = (err: string) => calls.map(() => ({ ok: false, out: '', err }));
|
|
153
|
+
try {
|
|
154
|
+
const r = spawnSync(process.execPath, ['-e', PARALLEL_SCRIPT], {
|
|
155
|
+
input: JSON.stringify({ calls: calls.map(call => ({ command: call.command, args: [...call.args], cwd: call.opts?.cwd })), concurrency, timeoutMs }),
|
|
156
|
+
encoding: 'utf-8', maxBuffer: PARALLEL_MAX_BUFFER, timeout: options.poolTimeoutMs ?? PARALLEL_POOL_TIMEOUT_MS, killSignal: 'SIGTERM',
|
|
157
|
+
...(options.env ? { env: options.env } : {}),
|
|
158
|
+
});
|
|
159
|
+
if ((r.error as NodeJS.ErrnoException | undefined)?.code === 'ENOBUFS') return failAll('parallel output exceeded 256MiB (ENOBUFS)');
|
|
160
|
+
if ((r.error as NodeJS.ErrnoException | undefined)?.code === 'ETIMEDOUT' || r.signal) return failAll(`parallel runner timed out or was killed (${r.signal ?? 'ETIMEDOUT'})`);
|
|
161
|
+
if (r.status !== 0) return failAll(`parallel runner rc=${r.status}: ${(r.stderr ?? '').trim().slice(0, 300)}`);
|
|
162
|
+
const parsed: unknown = JSON.parse(r.stdout ?? '');
|
|
163
|
+
if (!Array.isArray(parsed) || parsed.length !== calls.length) return failAll('parallel runner result shape mismatch');
|
|
164
|
+
return parsed.map(row => {
|
|
165
|
+
const value = row as { ok?: unknown; out?: unknown; err?: unknown } | null;
|
|
166
|
+
return value && typeof value.ok === 'boolean' && typeof value.out === 'string'
|
|
167
|
+
? { ok: value.ok, out: value.out, err: typeof value.err === 'string' ? value.err : '' }
|
|
168
|
+
: { ok: false, out: '', err: 'parallel runner row missing' };
|
|
169
|
+
});
|
|
170
|
+
} catch (error) {
|
|
171
|
+
return failAll(`parallel runner: ${error instanceof Error ? error.message : String(error)}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
48
175
|
function unknown(reason: string): Inventory { return { status: 'unknown', reason }; }
|
|
49
176
|
function seatValue(value: unknown): Seat | null { return SEATS.find(seat => seat === value) ?? null; }
|
|
50
177
|
function seatFromLabels(labels: readonly string[]): Seat | null {
|
|
@@ -60,6 +187,15 @@ export function cardIdFromBody(body: string): string | null {
|
|
|
60
187
|
export function hasCardMarker(body: string): boolean {
|
|
61
188
|
return /^\s*(?:[-*]\s*)?카드\s*:/m.test(body);
|
|
62
189
|
}
|
|
190
|
+
/** 골/PR 본문의 «조각 i/N — 부모 <칸>» 표지 → {slice,total}. 표지 없으면 null, 1≤i≤N 아니면 null. */
|
|
191
|
+
export function sliceMarkerFromBody(body: string): { slice: number; total: number } | null {
|
|
192
|
+
const m = /^\s*(?:[-*]\s*)?(?:«\s*)?조각\s*(\d+)\s*\/\s*(\d+)\s*(?:»)?\s*—\s*부모\s+\S[^\r\n]*$/m.exec(body);
|
|
193
|
+
if (!m) return null;
|
|
194
|
+
const slice = Number(m[1]);
|
|
195
|
+
const total = Number(m[2]);
|
|
196
|
+
return Number.isSafeInteger(slice) && Number.isSafeInteger(total) && slice >= 1 && total >= 1 && slice <= total
|
|
197
|
+
? { slice, total } : null;
|
|
198
|
+
}
|
|
63
199
|
|
|
64
200
|
export function parseDiffHunks(patch: string): DiffHunk[] {
|
|
65
201
|
const hunks: DiffHunk[] = [];
|
|
@@ -92,8 +228,8 @@ export function parseDiffHunks(patch: string): DiffHunk[] {
|
|
|
92
228
|
}
|
|
93
229
|
|
|
94
230
|
/** `gh api --paginate --slurp` must return every REST page, including the last page. */
|
|
95
|
-
function
|
|
96
|
-
|
|
231
|
+
function pagesArgs(endpoint: string): string[] { return ['api', '--paginate', '--slurp', endpoint]; }
|
|
232
|
+
function parsePages(result: PrToolCommandResult, endpoint: string): readonly unknown[] {
|
|
97
233
|
if (!result.ok) throw new Error(`gh api ${endpoint}: ${result.err || result.out || '조회 실패'}`);
|
|
98
234
|
let parsed: unknown;
|
|
99
235
|
try { parsed = JSON.parse(result.out); } catch { throw new Error(`gh api ${endpoint}: JSON 오류`); }
|
|
@@ -102,6 +238,9 @@ function pages(run: PrToolCommand, endpoint: string, cwd?: string): readonly unk
|
|
|
102
238
|
}
|
|
103
239
|
return parsed.flat();
|
|
104
240
|
}
|
|
241
|
+
function pages(run: PrToolCommand, endpoint: string, cwd?: string): readonly unknown[] {
|
|
242
|
+
return parsePages(run('gh', pagesArgs(endpoint), cwd ? { cwd } : undefined), endpoint);
|
|
243
|
+
}
|
|
105
244
|
|
|
106
245
|
function object(value: unknown): Record<string, unknown> {
|
|
107
246
|
if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error('PR 응답 행 형식 오류');
|
|
@@ -116,29 +255,59 @@ function date(value: unknown, name: string): string {
|
|
|
116
255
|
if (!Number.isFinite(Date.parse(raw))) throw new Error(`${name} 날짜 오류`);
|
|
117
256
|
return raw;
|
|
118
257
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
258
|
+
function filesEndpoint(number: number): string { return `repos/{owner}/{repo}/pulls/${number}/files?per_page=100`; }
|
|
259
|
+
function pathsFromFilesResult(result: PrToolCommandResult, number: number): string[] {
|
|
260
|
+
const rows = parsePages(result, filesEndpoint(number));
|
|
121
261
|
if (rows.length >= MAX_FILES) throw new Error(`PR #${number}: 파일 ${MAX_FILES}개 GitHub 상한에 닿음`);
|
|
122
262
|
return rows.map(row => text(object(row).filename, `PR #${number} 파일명`));
|
|
123
263
|
}
|
|
124
264
|
|
|
125
|
-
|
|
126
|
-
|
|
265
|
+
interface FileProjection {
|
|
266
|
+
files: Map<number, string[]>;
|
|
267
|
+
/** Set when the one-shot list produced nothing usable — every PR then takes the REST file fallback. */
|
|
268
|
+
failure?: string;
|
|
269
|
+
/** Rows the projection could not vouch for (malformed · file list shorter than changedFiles, e.g. >100 files). */
|
|
270
|
+
skipped: number;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** Fast file projection; the REST page census below remains the authority for which PRs exist. A failed or partial
|
|
274
|
+
* projection is never silent: the reason and skipped row count go to the `diff-scan` observation. */
|
|
275
|
+
function projectedFiles(run: PrToolCommand, count: number, cwd?: string): FileProjection {
|
|
127
276
|
const result = run('gh', ['pr', 'list', '--state', 'open', '--limit', String(Math.max(count, 1)), '--json', 'number,changedFiles,files'], cwd ? { cwd } : undefined);
|
|
128
|
-
if (!result.ok) return new Map();
|
|
277
|
+
if (!result.ok) return { files: new Map(), skipped: 0, failure: `gh pr list 실패: ${(result.err || result.out || 'rc≠0').trim().slice(0, 200)}` };
|
|
129
278
|
let rows: unknown;
|
|
130
|
-
try { rows = JSON.parse(result.out); } catch { return new Map(); }
|
|
131
|
-
if (!Array.isArray(rows)) return new Map();
|
|
279
|
+
try { rows = JSON.parse(result.out); } catch { return { files: new Map(), skipped: 0, failure: `gh pr list JSON 오류 (${result.out.length}자)` }; }
|
|
280
|
+
if (!Array.isArray(rows)) return { files: new Map(), skipped: 0, failure: 'gh pr list 응답이 배열 아님' };
|
|
132
281
|
const projection = new Map<number, string[]>();
|
|
282
|
+
let skipped = 0;
|
|
133
283
|
for (const value of rows) {
|
|
134
284
|
try {
|
|
135
285
|
const row = object(value);
|
|
136
|
-
if (!Number.isSafeInteger(row.number) || (row.number as number) <= 0 || !Number.isSafeInteger(row.changedFiles) || (row.changedFiles as number) < 0 || !Array.isArray(row.files)) continue;
|
|
286
|
+
if (!Number.isSafeInteger(row.number) || (row.number as number) <= 0 || !Number.isSafeInteger(row.changedFiles) || (row.changedFiles as number) < 0 || !Array.isArray(row.files)) { skipped += 1; continue; }
|
|
137
287
|
const paths = row.files.map(file => text(object(file).path, 'PR 파일명'));
|
|
138
288
|
if (paths.length === row.changedFiles && paths.length < MAX_FILES && !projection.has(row.number as number)) projection.set(row.number as number, paths);
|
|
139
|
-
|
|
289
|
+
else skipped += 1;
|
|
290
|
+
} catch { skipped += 1; /* malformed projection: REST file endpoint below decides this PR */ }
|
|
140
291
|
}
|
|
141
|
-
return projection;
|
|
292
|
+
if (rows.length > 0 && projection.size === 0) return { files: projection, skipped, failure: `gh pr list ${rows.length}행 모두 사용 불가` };
|
|
293
|
+
return { files: projection, skipped };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Run `calls` through the bounded pool when given, else one by one with the injected runner, stopping at the first
|
|
297
|
+
* failure (the historical order and call count). The result may be shorter than `calls` only in that sequential case. */
|
|
298
|
+
function runCalls(run: PrToolCommand, calls: readonly PrToolCall[], runParallel: PrToolParallelCommand | undefined, concurrency: number, what: string): PrToolCommandResult[] {
|
|
299
|
+
if (runParallel) {
|
|
300
|
+
const results = runParallel(calls, concurrency);
|
|
301
|
+
if (results.length !== calls.length) throw new Error(`${what} 결과 ${results.length}/${calls.length}건 · 판정 불가`);
|
|
302
|
+
return results;
|
|
303
|
+
}
|
|
304
|
+
const results: PrToolCommandResult[] = [];
|
|
305
|
+
for (const call of calls) {
|
|
306
|
+
const result = run(call.command, call.args, call.opts);
|
|
307
|
+
results.push(result);
|
|
308
|
+
if (!result.ok) break;
|
|
309
|
+
}
|
|
310
|
+
return results;
|
|
142
311
|
}
|
|
143
312
|
|
|
144
313
|
export function readOpenPrs(run: PrToolCommand, options: {
|
|
@@ -146,10 +315,28 @@ export function readOpenPrs(run: PrToolCommand, options: {
|
|
|
146
315
|
seatOfPr?: (pr: { number: number; headRefName: string; body: string; labels: readonly string[] }) => Seat | null;
|
|
147
316
|
includeDraftCommitDates?: boolean;
|
|
148
317
|
candidateFiles?: readonly string[];
|
|
318
|
+
/** Bounded parallel REST-file fallback and diff fetch. Absent ⇒ the injected `run`, one by one (historical order and call count). */
|
|
319
|
+
runParallel?: PrToolParallelCommand;
|
|
320
|
+
/** Operations default {@link DEFAULT_DIFF_CONCURRENCY} (6) — production callers do not pass it; for test injection. */
|
|
321
|
+
diffConcurrency?: number;
|
|
322
|
+
/** Absent ⇒ no cache. Production callers pass {@link sharedCensusDiffCache}. */
|
|
323
|
+
diffCache?: CensusDiffCache;
|
|
149
324
|
} = {}): Inventory {
|
|
325
|
+
const started = Date.now();
|
|
326
|
+
const callOpts = options.cwd ? { opts: { cwd: options.cwd } } : {};
|
|
327
|
+
const concurrency = options.runParallel ? Math.max(1, Math.floor(options.diffConcurrency ?? DEFAULT_DIFF_CONCURRENCY)) : 1;
|
|
328
|
+
const scan = { openPrs: 0, projected: 0, restFallback: 0, projectionFailed: false, projectionReason: undefined as string | undefined,
|
|
329
|
+
projectionSkipped: 0, fileOverlap: 0, patchFetched: 0, cacheHits: 0 };
|
|
330
|
+
let status: 'checked' | 'inventory-unknown' | 'files-failed' | 'diff-failed' | 'commit-date-failed' = 'inventory-unknown';
|
|
331
|
+
const logDiffScan = () => {
|
|
332
|
+
debug.log('pr-tool.census', 'diff-scan', { ...scan, concurrency, elapsedMs: Date.now() - started, status });
|
|
333
|
+
};
|
|
150
334
|
try {
|
|
151
335
|
const rows = pages(run, 'repos/{owner}/{repo}/pulls?state=open&per_page=100', options.cwd);
|
|
152
|
-
const
|
|
336
|
+
const projection = projectedFiles(run, rows.length, options.cwd);
|
|
337
|
+
scan.projectionFailed = projection.failure !== undefined;
|
|
338
|
+
scan.projectionReason = projection.failure;
|
|
339
|
+
scan.projectionSkipped = projection.skipped;
|
|
153
340
|
const prs: OpenPr[] = [];
|
|
154
341
|
const seen = new Set<number>();
|
|
155
342
|
for (const value of rows) {
|
|
@@ -166,26 +353,69 @@ export function readOpenPrs(run: PrToolCommand, options: {
|
|
|
166
353
|
const headSha = text(head.sha, `PR #${number} head sha`);
|
|
167
354
|
const body = typeof row.body === 'string' ? row.body : '';
|
|
168
355
|
const seat = seatValue(options.seatOfPr?.({ number: number as number, headRefName, body, labels: labelNames })) ?? seatFromLabels(labelNames);
|
|
169
|
-
|
|
356
|
+
prs.push({
|
|
170
357
|
number: number as number, headRefName, title: text(row.title, `PR #${number} title`), draft: row.draft,
|
|
171
358
|
updatedAt: date(row.updated_at, `PR #${number} updated_at`), headSha, labels: labelNames,
|
|
172
|
-
files:
|
|
359
|
+
files: projection.files.get(number as number) ?? [], seat,
|
|
173
360
|
cellId: cellIdFromBody(body), cardId: cardIdFromBody(body), cardMarkerPresent: hasCardMarker(body),
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
361
|
+
slice: sliceMarkerFromBody(body),
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
scan.openPrs = prs.length;
|
|
365
|
+
// Files: PRs the one-shot projection did not cover take the REST file endpoint — in the pool when given.
|
|
366
|
+
const restPrs = prs.filter(pr => !projection.files.has(pr.number));
|
|
367
|
+
scan.projected = prs.length - restPrs.length;
|
|
368
|
+
scan.restFallback = restPrs.length;
|
|
369
|
+
if (restPrs.length) {
|
|
370
|
+
status = 'files-failed';
|
|
371
|
+
const results = runCalls(run, restPrs.map(pr => ({ command: 'gh', args: pagesArgs(filesEndpoint(pr.number)), ...callOpts })), options.runParallel, concurrency, 'PR 파일 조회');
|
|
372
|
+
// The first failure in input order decides the reason; one failure keeps the whole inventory unknown.
|
|
373
|
+
// Invariant: a result is missing only after an earlier failure (sequential stop), which throws first. Still,
|
|
374
|
+
// a missing result is a failure (unknown), never an empty file list.
|
|
375
|
+
restPrs.forEach((pr, index) => {
|
|
376
|
+
const result = results[index];
|
|
377
|
+
if (!result) throw new Error(`PR #${pr.number}: 파일 조회 결과 없음 · 판정 불가`);
|
|
378
|
+
pr.files = pathsFromFilesResult(result, pr.number);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
// Diffs: only PRs sharing a candidate file; a cached (number, headSha) patch is not refetched.
|
|
382
|
+
const pendingDiffs: OpenPr[] = [];
|
|
383
|
+
for (const pr of prs) {
|
|
384
|
+
if (!options.candidateFiles?.some(file => pr.files.includes(file))) continue;
|
|
385
|
+
scan.fileOverlap += 1;
|
|
386
|
+
const cached = options.diffCache?.get(pr.number, pr.headSha);
|
|
387
|
+
if (cached !== undefined) { pr.hunks = parseDiffHunks(cached); scan.cacheHits += 1; }
|
|
388
|
+
else pendingDiffs.push(pr);
|
|
389
|
+
}
|
|
390
|
+
if (pendingDiffs.length) {
|
|
391
|
+
status = 'diff-failed';
|
|
392
|
+
const results = runCalls(run, pendingDiffs.map(pr => ({ command: 'gh', args: ['pr', 'diff', String(pr.number), '--patch'], ...callOpts })), options.runParallel, concurrency, '수정 줄 조회');
|
|
393
|
+
scan.patchFetched = results.length;
|
|
394
|
+
pendingDiffs.forEach((pr, index) => {
|
|
395
|
+
const patch = results[index];
|
|
396
|
+
if (!patch) throw new Error(`PR #${pr.number}: 수정 줄 조회 결과 없음 · 판정 불가`);
|
|
397
|
+
if (!patch.ok) throw new Error(`PR #${pr.number}: 수정 줄 조회 실패: ${patch.err || patch.out}`);
|
|
398
|
+
});
|
|
399
|
+
pendingDiffs.forEach((pr, index) => {
|
|
400
|
+
const patch = results[index]!;
|
|
178
401
|
pr.hunks = parseDiffHunks(patch.out);
|
|
402
|
+
options.diffCache?.set(pr.number, pr.headSha, patch.out);
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (options.includeDraftCommitDates) {
|
|
406
|
+
status = 'commit-date-failed';
|
|
407
|
+
for (const pr of prs) {
|
|
408
|
+
if (!pr.draft) continue;
|
|
409
|
+
const commit = run('gh', ['api', `repos/{owner}/{repo}/commits/${pr.headSha}`, '--jq', '.commit.committer.date'], options.cwd ? { cwd: options.cwd } : undefined);
|
|
410
|
+
if (!commit.ok) throw new Error(`PR #${pr.number}: 마지막 커밋 날짜 조회 실패: ${commit.err || commit.out}`);
|
|
411
|
+
pr.lastCommitAt = date(commit.out.trim(), `PR #${pr.number} 마지막 커밋`);
|
|
179
412
|
}
|
|
180
|
-
if (pr.draft && options.includeDraftCommitDates) {
|
|
181
|
-
const commit = run('gh', ['api', `repos/{owner}/{repo}/commits/${headSha}`, '--jq', '.commit.committer.date'], options.cwd ? { cwd: options.cwd } : undefined);
|
|
182
|
-
if (!commit.ok) throw new Error(`PR #${number}: 마지막 커밋 날짜 조회 실패: ${commit.err || commit.out}`);
|
|
183
|
-
pr.lastCommitAt = date(commit.out.trim(), `PR #${number} 마지막 커밋`);
|
|
184
|
-
}
|
|
185
|
-
prs.push(pr);
|
|
186
413
|
}
|
|
414
|
+
status = 'checked';
|
|
415
|
+
logDiffScan();
|
|
187
416
|
return { status: 'checked', prs };
|
|
188
417
|
} catch (error) {
|
|
418
|
+
logDiffScan();
|
|
189
419
|
return unknown(error instanceof Error ? error.message : String(error));
|
|
190
420
|
}
|
|
191
421
|
}
|
|
@@ -222,7 +452,7 @@ export function censusOpenPrs(inventory: Inventory, now = Date.now()): Census {
|
|
|
222
452
|
return result;
|
|
223
453
|
}
|
|
224
454
|
|
|
225
|
-
export function guardNewPr(input: { files: readonly string[] | null; seat?: Seat | null; seatCap?: number; cellId?: string | null; cardId?: string | null; boundPrNumber?: number; hunks?: readonly DiffHunk[]; hunkOverlap?: HunkOverlapMode }, inventory: Inventory): GuardVerdict {
|
|
455
|
+
export function guardNewPr(input: { files: readonly string[] | null; seat?: Seat | null; seatCap?: number; cellId?: string | null; cardId?: string | null; slice?: { slice: number; total: number } | null; boundPrNumber?: number; hunks?: readonly DiffHunk[]; hunkOverlap?: HunkOverlapMode }, inventory: Inventory): GuardVerdict {
|
|
226
456
|
if (!input.files || input.files.length === 0 || input.files.some(file => !file || file.startsWith('/') || file.includes('..'))) {
|
|
227
457
|
const reasons: GuardReason[] = [{ code: 'candidate-unknown', detail: '새 PR 변경 파일을 확인할 수 없음' }];
|
|
228
458
|
debug.log('pr.tool', 'guard-refuse', { status: 'unknown', reasons });
|
|
@@ -275,10 +505,14 @@ export function guardNewPr(input: { files: readonly string[] | null; seat?: Seat
|
|
|
275
505
|
&& input.boundPrNumber === sameCell[0].number;
|
|
276
506
|
const reusable = status === 'refuse' && reasons.length === 1 && reasons[0]?.code === 'same-cell'
|
|
277
507
|
&& input.cardId && sameCell.length === 1 && (sameCell[0]?.cardId === input.cardId || legacyBound)
|
|
508
|
+
&& (input.slice?.slice ?? null) === (sameCell[0]?.slice?.slice ?? null)
|
|
509
|
+
&& (input.slice?.total ?? null) === (sameCell[0]?.slice?.total ?? null)
|
|
278
510
|
&& sameCell[0].headRefName && /^[0-9a-f]{40}$/i.test(sameCell[0].headSha)
|
|
279
511
|
? { number: sameCell[0].number, branch: sameCell[0].headRefName, headSha: sameCell[0].headSha,
|
|
280
512
|
cellId: input.cellId!, cardId: input.cardId, ...(legacyBound ? { legacyBound: true as const } : {}) } : undefined;
|
|
281
|
-
return { status, reasons, warnings,
|
|
513
|
+
return { status, reasons, warnings,
|
|
514
|
+
...(sameCell.length ? { sameCellConflicts: sameCell.map(pr => ({ pr: pr.number, cardId: pr.cardId ?? null, slice: pr.slice ?? null })) } : {}),
|
|
515
|
+
...(reusable ? { sameCellReuse: reusable } : {}) };
|
|
282
516
|
}
|
|
283
517
|
|
|
284
518
|
/** Persist the unknown-read budget across harness processes sharing one instance state root. */
|
|
@@ -251,6 +251,13 @@ function recordPtyLifecycle(event: PtyLifecycleEvent, row: PtyManifestRow, now:
|
|
|
251
251
|
exitCode: row.exitCode,
|
|
252
252
|
startedAt: row.startedAt,
|
|
253
253
|
closedAt: row.closedAt,
|
|
254
|
+
// 시작·종료·오류·산출을 같은 seatId 한 흐름으로 대조할 수 있게
|
|
255
|
+
// 매니페스트 행의 자리 정체성과 산출 총량을 원장 이벤트에도 싣는다.
|
|
256
|
+
...(row.seat ? { seat: row.seat } : {}),
|
|
257
|
+
...(row.purpose ? { purpose: row.purpose } : {}),
|
|
258
|
+
outputBytesTotal: row.outputBytesTotal,
|
|
259
|
+
...(row.lastControlAt === undefined ? {} : { lastControlAt: row.lastControlAt }),
|
|
260
|
+
...(row.turnState ? { turnState: row.turnState, turnAt: row.turnAt } : {}),
|
|
254
261
|
},
|
|
255
262
|
});
|
|
256
263
|
if (seq === 0) debug.log('pty.manifest', 'ledger-write-failed', { ptyId: row.id, event });
|
|
@@ -132,6 +132,28 @@ function mentionedPaths(text: string): string[] {
|
|
|
132
132
|
return [...text.matchAll(PATH_TOKEN)].map((match) => match[1]!).filter((path) => !path.split('/').includes('..'));
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
/** `docs/goal-context/03-verification-menu.md` §선택 원칙: merge SHA·타입검사는 수용선이 아니다. */
|
|
136
|
+
export const MERGE_OR_TYPECHECK_ONLY_REAL_WARNING = '- 완료 경계 실물: merge sha·타입검사만으로는 실물이 아니다 — docs/goal-context/03-verification-menu.md 에서 동작을 재는 방법을 고른다';
|
|
137
|
+
/** 통합 이력·정적 타입 상태만 말하는 낱말(조사 뗀 꼴). 이 밖의 낱말이 하나라도 있으면 실물 주장으로 본다. */
|
|
138
|
+
const MERGE_OR_TYPECHECK_WORD = /^(?:pr|merge|merged|머지|병합|착지|landed|land|sha|merge-sha|commit|커밋|origin|main|tsc|typecheck|type-check|typecheck-changed|타입검사|타입|검사|type|check|changed|통과|pass|passed|green|clean|errors?|error|오류|에러|없음|후|뒤|완료|확인|and|및|만|됨|된다)$/i;
|
|
139
|
+
const MERGE_OR_TYPECHECK_SIGNAL = /^(?:merge|merged|머지|병합|착지|landed|land|sha|merge-sha|tsc|typecheck|type-check|타입검사)$/i;
|
|
140
|
+
const KOREAN_PARTICLE_TAIL = /(?:했다|했음|하였다|했고|함|으로|로|이|가|은|는|을|를|와|과|에|의|만|됨|된|된다)$/u;
|
|
141
|
+
|
|
142
|
+
/** 「완료 경계 실물」 값이 merge sha·PR 착지·타입검사 낱말로만 이뤄졌나(동작 관측이 하나도 없나). */
|
|
143
|
+
export function isMergeOrTypecheckOnlyEvidence(value: string): boolean {
|
|
144
|
+
const words = value.split(/[\s.!?。…~`'"·,⊕+()[\]:;/=|→-]+/u).map((word) => word.replace(/^#/, '')).filter(Boolean);
|
|
145
|
+
if (!words.length) return false;
|
|
146
|
+
let signal = false;
|
|
147
|
+
for (const raw of words) {
|
|
148
|
+
if (/^\d+$/.test(raw) || /^[0-9a-f]{7,40}$/i.test(raw)) continue;
|
|
149
|
+
let word = raw;
|
|
150
|
+
for (let strip = 0; strip < 3 && !MERGE_OR_TYPECHECK_WORD.test(word); strip++) word = word.replace(KOREAN_PARTICLE_TAIL, '');
|
|
151
|
+
if (!MERGE_OR_TYPECHECK_WORD.test(word)) return false;
|
|
152
|
+
if (MERGE_OR_TYPECHECK_SIGNAL.test(word)) signal = true;
|
|
153
|
+
}
|
|
154
|
+
return signal;
|
|
155
|
+
}
|
|
156
|
+
|
|
135
157
|
/** Shadow check at checklist authorship. Callers supply the origin/main file probe and merged-PR file reader. */
|
|
136
158
|
export function inspectChecklistTargetPaths(input: {
|
|
137
159
|
title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind;
|
|
@@ -179,6 +201,8 @@ export function inspectChecklistTargetPaths(input: {
|
|
|
179
201
|
if (!lines.some((line) => line.startsWith(`- 완료 경계 ${label}:`) && line.slice(`- 완료 경계 ${label}:`.length).trim()))
|
|
180
202
|
warnings.push(`- 완료 경계 ${label}: 줄이 없다`);
|
|
181
203
|
}
|
|
204
|
+
const real = lines.find((line) => line.startsWith('- 완료 경계 실물:'))?.slice('- 완료 경계 실물:'.length).trim();
|
|
205
|
+
if (real && isMergeOrTypecheckOnlyEvidence(real)) warnings.push(MERGE_OR_TYPECHECK_ONLY_REAL_WARNING);
|
|
182
206
|
}
|
|
183
207
|
if (!warnings.length) return { targets, warnings, candidates: [] };
|
|
184
208
|
const sources = [input.title, input.evidence ?? '', ...(input.refs ?? [])].join('\n');
|