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
|
@@ -10,7 +10,7 @@ import { lastJsonObject, runGraph, verifyReleaseCommandRoot, type GraphRunState
|
|
|
10
10
|
import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
|
|
11
11
|
import { releaseRunUniverse } from './release-universe.js';
|
|
12
12
|
import { isReleaseVersion } from './release-version.js';
|
|
13
|
-
import { changedFilesBetween, clearPartialPlan, planPartialRegate, writePartialPlan } from './gate-partial.js';
|
|
13
|
+
import { changedFilesBetween, clearPartialPlan, planPartialRegate, planStalledShardRecheck, writePartialPlan, writeRecheckPlan } from './gate-partial.js';
|
|
14
14
|
import { gitClosureTree, testsReachingChanged, TRACEABLE_RELEASE_JSON, type ClosureTree } from './gate-closure.js';
|
|
15
15
|
import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeGatePodPool, releaseResumeWaiver, type AcceptedRegression } from './resume.js';
|
|
16
16
|
import { reserveReleaseResumeAttempt } from './resume-cap.js';
|
|
@@ -173,13 +173,50 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
|
|
|
173
173
|
const reachesGate = (opts.from === 'gate' || opts.from === 'export-check') && fromIndex >= 0 && gateIndex >= fromIndex;
|
|
174
174
|
// The default applies only where it can help: a gate re-run on a tip that moved. An unchanged tip re-uses its own
|
|
175
175
|
// shard results by commit already.
|
|
176
|
-
if (opts.partial === false || (auto && (!reachesGate || !tip.changed))) return { requested: false };
|
|
176
|
+
if (opts.partial === false || (auto && (!reachesGate || (!tip.changed && opts.from !== 'gate')))) return { requested: false };
|
|
177
177
|
const fallback = (reason: string): PartialOutcome => {
|
|
178
|
-
debug.log('release-loop.resume', 'partial-fallback', { version: tip.version, reason, auto
|
|
178
|
+
debug.log('release-loop.resume', 'partial-fallback', { version: tip.version, reason, auto,
|
|
179
|
+
planKind: 'full', remeasureFileCount: 0, preservedShardCount: 0, fallbackReason: reason });
|
|
179
180
|
return { requested: true, applied: false, reason, ...(auto ? { auto: true as const } : {}) };
|
|
180
181
|
};
|
|
181
182
|
if (!reachesGate) return fallback('--partial requires a restart that reaches gate');
|
|
182
|
-
if (!tip.changed)
|
|
183
|
+
if (!tip.changed) {
|
|
184
|
+
if (opts.from !== 'gate') return fallback('same-commit stalled-shard recheck requires --from gate');
|
|
185
|
+
const saved = JSON.parse(readFileSync(tip.statePath, 'utf8')) as GraphRunState;
|
|
186
|
+
const gateRecord = saved.nodes.find((node) => node.nodeId === 'gate');
|
|
187
|
+
const previousGate = gateRecord ? lastJsonObject(gateRecord.output) as Record<string, unknown> | undefined : undefined;
|
|
188
|
+
const stalled = previousGate?.stalledShards;
|
|
189
|
+
const summary = previousGate?.partialSummary as { pass?: unknown; fail?: unknown; errors?: unknown; ran?: unknown; files?: unknown } | undefined;
|
|
190
|
+
const measured = previousGate?.partialFailures as { failures?: unknown; errors?: unknown } | undefined;
|
|
191
|
+
if (previousGate?.outcome !== 'error' || previousGate.commit !== tip.to || !Array.isArray(stalled) || !stalled.length || !summary || !measured
|
|
192
|
+
|| !['pass', 'fail', 'errors', 'ran', 'files'].every((key) => Number.isSafeInteger(summary[key as keyof typeof summary]) && Number(summary[key as keyof typeof summary]) >= 0)
|
|
193
|
+
|| !Array.isArray(measured.failures) || !measured.failures.every((id) => typeof id === 'string')
|
|
194
|
+
|| !Array.isArray(measured.errors) || !measured.errors.every((id) => typeof id === 'string')
|
|
195
|
+
|| measured.failures.length !== Number(summary.fail) || measured.errors.length !== Number(summary.errors))
|
|
196
|
+
return fallback('same-commit gate has no complete stalled-shard measurement record');
|
|
197
|
+
const stalledFiles: string[] = [];
|
|
198
|
+
for (const item of stalled) {
|
|
199
|
+
if (!item || typeof item !== 'object' || !Array.isArray((item as { files?: unknown }).files)
|
|
200
|
+
|| !(item as { files: unknown[] }).files.every((file) => typeof file === 'string')
|
|
201
|
+
|| !['incomplete', 'no-output', 'job-failed', 'exit-code', 'unattributed', 'timeout'].includes(String((item as { reason?: unknown }).reason)))
|
|
202
|
+
return fallback('stalled-shard record is malformed');
|
|
203
|
+
stalledFiles.push(...(item as { files: string[] }).files);
|
|
204
|
+
}
|
|
205
|
+
const closure = (deps.closureTree ?? ((commit: string) => gitClosureTree(deps.repo ?? process.cwd(), commit)))(tip.to);
|
|
206
|
+
const tracked = new Set(closure.files);
|
|
207
|
+
const preservedShardCount = Number.isSafeInteger(previousGate?.preservedShardCount)
|
|
208
|
+
&& Number(previousGate?.preservedShardCount) >= 0 ? Number(previousGate?.preservedShardCount) : undefined;
|
|
209
|
+
const planned = planStalledShardRecheck({ version: tip.version, measuredCommit: tip.to, forCommit: tip.to,
|
|
210
|
+
failures: measured.failures as string[], errors: measured.errors as string[], stalledFiles,
|
|
211
|
+
...(preservedShardCount === undefined ? {} : { preservedShardCount }),
|
|
212
|
+
existsAtCommit: (file) => tracked.has(file) });
|
|
213
|
+
if (!planned.ok) return fallback(planned.reason);
|
|
214
|
+
const path = writeRecheckPlan(root, planned.plan);
|
|
215
|
+
debug.log('release-loop.resume', 'stalled-recheck-planned', { version: tip.version, commit: tip.to,
|
|
216
|
+
planKind: planned.plan.kind, remeasureFileCount: planned.plan.files.length,
|
|
217
|
+
preservedShardCount: planned.plan.preservedShardCount ?? 0, fallbackReason: null, path });
|
|
218
|
+
return { requested: true, applied: true, files: planned.plan.files.length, priorCommit: tip.to, ...(auto ? { auto: true as const } : {}) };
|
|
219
|
+
}
|
|
183
220
|
let prior: { commit?: unknown; failures?: unknown; errors?: unknown } | undefined;
|
|
184
221
|
for (const location of [...new Set([deps.ledgerRoot ?? releaseLedgerRoot(), root])]) {
|
|
185
222
|
const path = join(location, 'release', tip.version, 'gate-failures.json');
|
|
@@ -39,6 +39,8 @@ export interface ReleaseLoopConfig {
|
|
|
39
39
|
gatePodCpu?: number | string | { request?: number | string; limit?: number | string };
|
|
40
40
|
gateRemote?: string;
|
|
41
41
|
gateRemoteMirror?: string;
|
|
42
|
+
/** RELEASE-PWA-NODE-RESILIENCE ① — SSH host the `pwa` node runs its scenario suite on (e.g. `node-b`); absent = this machine. No fallback. */
|
|
43
|
+
pwaRemote?: string;
|
|
42
44
|
opsHosts?: string[];
|
|
43
45
|
internalDist?: string;
|
|
44
46
|
opsRestart?: boolean;
|
package/scripts/test-diet/lib.ts
CHANGED
|
@@ -93,7 +93,12 @@ export type Verdict = 'keep' | 'failing' | 'review';
|
|
|
93
93
|
export type Proposal = 'delete' | 'shrink' | 'rewrite-cheap' | 'move-out-of-gate' | 'investigate';
|
|
94
94
|
export interface Td1Disposition { disposition: string; alternative: string; guards: string; why_slow: string }
|
|
95
95
|
export interface Judged extends Measurement { caught90: number; flags: string[]; verdict: Verdict; effectiveness?: Effectiveness; proposal?: Proposal | null; basis?: string | null }
|
|
96
|
-
export interface LedgerLine {
|
|
96
|
+
export interface LedgerLine {
|
|
97
|
+
at: string; range: string; start: number; end: number; next: number; total: number; commit: string; budgetSecs: number; results: Judged[];
|
|
98
|
+
/** Exact non-contiguous selection; `range` encodes these indices in selection order. */
|
|
99
|
+
selectedFiles?: string[]; selectedIndices?: number[];
|
|
100
|
+
sweepVisited?: number; sweepCostSecs?: number; sweepSlices?: number;
|
|
101
|
+
}
|
|
97
102
|
|
|
98
103
|
/** `file\tsecs\t…` (TD1 whole-gate TSV) → seconds per file. */
|
|
99
104
|
export function costTable(tsv: string): Map<string, number> {
|
|
@@ -7,12 +7,13 @@ import { appendFileSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSyn
|
|
|
7
7
|
import { tmpdir } from 'node:os';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { debug } from '../../src/debug/log.js';
|
|
10
|
-
import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
10
|
+
import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
|
|
11
11
|
import { CardStore } from '../../src/task-cards/card-store.js';
|
|
12
12
|
import { GATE_NIGHTLY_AUDITS } from '../release-loop/gate-node.js';
|
|
13
13
|
import { isCredentialKey } from '../lib/deterministic-env.js';
|
|
14
14
|
import { appendLedger, costTable, judge, lastLedgerLine, ledgerPath, mainFailureFiles, nightlyAuditLedgerPath, pickRange, propose, td1Dispositions, writeCardDraft, writeMainFailureDay, type LedgerLine, type MainFailureResult, type Measurement, type Td1Disposition } from './lib.js';
|
|
15
15
|
import { fixedCountAssertions, flakeVerdict, sweepSlice, unreachableImports, type Mutation, type TestRun } from './effectiveness.js';
|
|
16
|
+
import { gateHistory, type GateHistoryRow } from '../release-loop/gate-history.js';
|
|
16
17
|
|
|
17
18
|
type Context = { graphId?: string; input: Record<string, unknown>; outputs: Record<string, Record<string, unknown> | null> };
|
|
18
19
|
function context(): Context {
|
|
@@ -27,6 +28,129 @@ function emit(result: Record<string, unknown> & { outcome: 'ok' | 'fail' | 'erro
|
|
|
27
28
|
}
|
|
28
29
|
const git = (args: string[]) => spawnSync('git', args, { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 }).stdout ?? '';
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
* GATE-FAIL-HISTORY → per-file failure likelihood (boundary ①): a file the landed gate already failed on is picked
|
|
33
|
+
* before one it never failed on, and preexisting/knownEnv repeat offenders outrank one-off introduced/load-flaky hits.
|
|
34
|
+
*/
|
|
35
|
+
const GATE_FAIL_WEIGHT = { preexisting: 4, knownEnv: 3, flaky: 3, introduced: 2 } as const;
|
|
36
|
+
|
|
37
|
+
/** Only the buckets the pick order and the prescription both read — no write-only fields. */
|
|
38
|
+
export type GateFailWeight = { file: string; weight: number; preexisting: number; knownEnv: number; flaky: number };
|
|
39
|
+
|
|
40
|
+
export function gateFailWeights(rows: readonly GateHistoryRow[]): Map<string, GateFailWeight> {
|
|
41
|
+
const weights = new Map<string, GateFailWeight>();
|
|
42
|
+
for (const row of rows) {
|
|
43
|
+
const weight = row.preexisting * GATE_FAIL_WEIGHT.preexisting + row.env * GATE_FAIL_WEIGHT.knownEnv
|
|
44
|
+
+ row.flaky * GATE_FAIL_WEIGHT.flaky + row.introduced * GATE_FAIL_WEIGHT.introduced;
|
|
45
|
+
if (weight <= 0) continue;
|
|
46
|
+
const file = String(row.file);
|
|
47
|
+
weights.set(file, { file, weight, preexisting: row.preexisting, knownEnv: row.env, flaky: row.flaky });
|
|
48
|
+
}
|
|
49
|
+
return weights;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Reads the gate's own failure ledger; an unreadable ledger is an empty history, never a failed pick. */
|
|
53
|
+
export function loadGateFailWeights(deps: {
|
|
54
|
+
instanceRoots?: readonly string[]; ledgerRoots?: readonly string[]; rows?: readonly GateHistoryRow[];
|
|
55
|
+
} = {}): Map<string, GateFailWeight> {
|
|
56
|
+
if (deps.rows) return gateFailWeights(deps.rows);
|
|
57
|
+
try {
|
|
58
|
+
const report = gateHistory({
|
|
59
|
+
instanceRoots: deps.instanceRoots ?? [effectiveInstanceRoot()],
|
|
60
|
+
ledgerRoots: deps.ledgerRoots ?? [releaseLedgerRoot()],
|
|
61
|
+
}, { mergedPrs: () => [] });
|
|
62
|
+
return gateFailWeights(report.rows);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
debug.log('test-diet', 'history-read-failed', { error: String(error) });
|
|
65
|
+
return new Map();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* `pickRange` with the history-weighted order on top: every gate-failed file that fits the budget comes first
|
|
71
|
+
* (weight desc, then cheaper), the cursor slice fills the rest. Cursor `next` only advances past cursor files the
|
|
72
|
+
* budget actually selected — an unselected cursor file stays before `next`, so no file is skipped in a daily verdict
|
|
73
|
+
* or a sweep.
|
|
74
|
+
*/
|
|
75
|
+
export function pickWithHistory(files: readonly string[], start: number, costs: ReadonlyMap<string, number>, budgetSecs: number,
|
|
76
|
+
weights: ReadonlyMap<string, GateFailWeight>): ReturnType<typeof pickRange> & {
|
|
77
|
+
historyFiles: GateFailWeight[]; selectedIndices: number[]; rangeLabel: string; cursorVisitedCount: number;
|
|
78
|
+
} {
|
|
79
|
+
const range = pickRange(files, start, costs, budgetSecs);
|
|
80
|
+
const cost = (file: string) => costs.get(file) ?? 10;
|
|
81
|
+
const historyFiles = [...weights.values()].filter((entry) => files.includes(entry.file))
|
|
82
|
+
.sort((a, b) => b.weight - a.weight || cost(a.file) - cost(b.file) || a.file.localeCompare(b.file));
|
|
83
|
+
const describeSelection = (selectedFiles: string[]) => {
|
|
84
|
+
const selectedIndices = selectedFiles.map((file) => files.indexOf(file));
|
|
85
|
+
const contiguous = selectedIndices.length > 0
|
|
86
|
+
&& selectedIndices.every((index, position) => position === 0 || index === selectedIndices[position - 1]! + 1);
|
|
87
|
+
const rangeLabel = selectedIndices.length === 0 ? '#empty'
|
|
88
|
+
: contiguous ? `#${selectedIndices[0]}~#${selectedIndices.at(-1)}`
|
|
89
|
+
: selectedIndices.map((index) => `#${index}`).join(',');
|
|
90
|
+
return { selectedIndices, rangeLabel };
|
|
91
|
+
};
|
|
92
|
+
if (historyFiles.length === 0) return { ...range, historyFiles, cursorVisitedCount: range.files.length, ...describeSelection(range.files) };
|
|
93
|
+
const ordered: string[] = [];
|
|
94
|
+
let estimatedSecs = 0;
|
|
95
|
+
for (const file of [...historyFiles.map((entry) => entry.file), ...range.files]) {
|
|
96
|
+
if (ordered.includes(file)) continue;
|
|
97
|
+
const added = cost(file);
|
|
98
|
+
if (ordered.length > 0 && estimatedSecs + added > budgetSecs) continue;
|
|
99
|
+
ordered.push(file);
|
|
100
|
+
estimatedSecs += added;
|
|
101
|
+
}
|
|
102
|
+
// 예산을 이력 파일로 채웠을 때: 커서는 실제로 선택한 커서 조각까지만 전진한다.
|
|
103
|
+
// 선택되지 않은 커서 파일을 next 너머로 건너뛰면 일일 판정·sweep에서 영구 누락된다.
|
|
104
|
+
const firstUnpicked = range.files.findIndex((file) => !ordered.includes(file));
|
|
105
|
+
const next = firstUnpicked === -1 ? range.next : (range.start + firstUnpicked) % files.length;
|
|
106
|
+
return { ...range, files: ordered, estimatedSecs, historyFiles, next,
|
|
107
|
+
cursorVisitedCount: range.files.filter((file) => ordered.includes(file)).length, ...describeSelection(ordered) };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** MANUAL-gate-regression-response-recipe §2 T1~T7, plus TA for a verdict that is only a draft for the card. */
|
|
111
|
+
export type CleanseRecipeType = 'T1' | 'T2' | 'T3' | 'T4' | 'T5' | 'T6' | 'T7' | 'TA';
|
|
112
|
+
export type CleanseRecipe = { type: CleanseRecipeType; file: string; action: string; basis: string };
|
|
113
|
+
|
|
114
|
+
const RECIPE_ACTIONS: Record<CleanseRecipeType, string> = {
|
|
115
|
+
T1: 'fixture·단언을 새 계약으로 고쳐 쓴다(제품 동작은 그대로)',
|
|
116
|
+
T2: '제품 회귀 — 제품 동작을 고친다(시험 완화 금지)',
|
|
117
|
+
T3: '규칙 문면을 규칙 원본과 맞춘다',
|
|
118
|
+
T4: '시험 문면을 지금 문안으로 맞춘다(프로토콜·기본 동작은 그대로)',
|
|
119
|
+
T5: '빈 환경 의존을 주입으로 없앤다(credential·경로·도구를 명시 주입)',
|
|
120
|
+
T6: '간섭을 격리한다(단독 실행·임시 HOME·동시성 낮춤)',
|
|
121
|
+
T7: '인프라 실패 — 재게이트하고 TA 카드로 사람에게 넘긴다',
|
|
122
|
+
TA: '결과를 TA 카드로 남긴다(지우기·이동은 사람·주인 확인)',
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export type RecipeInput = { file: string; verdict: string; reason?: string; flaky?: boolean; effectiveness?: { flake?: string };
|
|
126
|
+
history?: { preexisting: number; knownEnv: number; flaky?: number } };
|
|
127
|
+
|
|
128
|
+
/** Exactly one prescription per verdict — the draft only, never a deletion. */
|
|
129
|
+
export function recipeFor(result: RecipeInput): CleanseRecipe {
|
|
130
|
+
const reason = (result.reason ?? '').toLowerCase();
|
|
131
|
+
const flaky = result.flaky === true || result.effectiveness?.flake === 'flaky';
|
|
132
|
+
const history = result.history;
|
|
133
|
+
// The gate ledger's flaky bucket is the same «history» the pick weighs, so a repeat-flaky file that measures
|
|
134
|
+
// keep still gets the isolation prescription (T6) instead of falling through to a bare TA card.
|
|
135
|
+
const historyFlaky = history?.flaky ?? 0;
|
|
136
|
+
const type: CleanseRecipeType = result.verdict === 'failing'
|
|
137
|
+
? (/enospc|out of memory|cannot allocate|oomkilled|no space|pod .*(restart|terminat)|preempt/.test(reason) ? 'T7'
|
|
138
|
+
: flaky ? 'T6'
|
|
139
|
+
: /enoent|eacces|no llm provider|command not found|cannot find module|credential|api key|not found: |git config/.test(reason) ? 'T5'
|
|
140
|
+
: /timed out|timeout|waitfor|expected text|wording|문면/.test(reason) ? 'T4'
|
|
141
|
+
: /rules-contract|(^|\/)\.rules\//.test(result.file) ? 'T3'
|
|
142
|
+
: /typeerror|referenceerror|is not a function|is not defined|syntaxerror/.test(reason) ? 'T2'
|
|
143
|
+
: 'T1')
|
|
144
|
+
: history?.knownEnv ? 'T5'
|
|
145
|
+
: flaky || history?.preexisting || historyFlaky > 0 ? 'T6'
|
|
146
|
+
: 'TA';
|
|
147
|
+
const tail = reason.split('\n')[0]?.slice(0, 160) ?? '';
|
|
148
|
+
const historyBasis = history && (history.preexisting > 0 || history.knownEnv > 0 || historyFlaky > 0)
|
|
149
|
+
? ` · gate history preexisting ${history.preexisting} · knownEnv ${history.knownEnv}`
|
|
150
|
+
+ `${historyFlaky > 0 ? ` · flaky ${historyFlaky}` : ''}` : '';
|
|
151
|
+
return { type, file: result.file, action: RECIPE_ACTIONS[type], basis: `${result.verdict}${tail ? `: ${tail}` : ''}${historyBasis}` };
|
|
152
|
+
}
|
|
153
|
+
|
|
30
154
|
function pick(ctx: Context, sweep = false): number {
|
|
31
155
|
const files = git(['ls-files', '*.test.ts']).split('\n').filter(Boolean).sort();
|
|
32
156
|
const costs = costTable(readFileSync(join(process.cwd(), 'docs/measurements/td1-whole-gate-mechanical-2026-10-01.tsv'), 'utf8'));
|
|
@@ -35,7 +159,7 @@ function pick(ctx: Context, sweep = false): number {
|
|
|
35
159
|
const totalCostSecs = sweep ? files.reduce((sum, file) => sum + (costs.get(file) ?? 10), 0) : 0;
|
|
36
160
|
// `start` re-looks a slice on purpose; otherwise continue from the ledger cursor.
|
|
37
161
|
const startAt = typeof ctx.input.start === 'number' && ctx.input.start >= 0 ? ctx.input.start : last?.next ?? 0;
|
|
38
|
-
const continuing = ctx.input.start === undefined && last?.sweepVisited && last.sweepVisited < files.length && last.next === startAt && last.total === files.length;
|
|
162
|
+
const continuing = ctx.input.start === undefined && typeof last?.sweepVisited === 'number' && last.sweepVisited < files.length && last.next === startAt && last.total === files.length;
|
|
39
163
|
const remaining = continuing ? files.length - last.sweepVisited! : files.length;
|
|
40
164
|
const elapsed = continuing ? last.sweepSlices ?? 0 : 0;
|
|
41
165
|
const slotsLeft = Math.max(1, 28 - elapsed);
|
|
@@ -43,8 +167,13 @@ function pick(ctx: Context, sweep = false): number {
|
|
|
43
167
|
slotsLeft, minBudgetSecs: continuing ? last.budgetSecs : 0 }) : undefined;
|
|
44
168
|
const budgetSecs = sweepPlan?.budgetSecs
|
|
45
169
|
?? (typeof ctx.input.budgetSecs === 'number' && ctx.input.budgetSecs > 0 ? ctx.input.budgetSecs : 1800);
|
|
46
|
-
const
|
|
47
|
-
|
|
170
|
+
const measuredLastSlice = new Set((last?.results ?? []).map((result) => result.file));
|
|
171
|
+
const cursorParked = last?.next === startAt && last.selectedIndices?.every((index) => index !== startAt);
|
|
172
|
+
// When a prior history-only slice left the cursor parked, force the next slice onto the cursor.
|
|
173
|
+
// Suppressing only the last history winner allows two weighted files to alternate forever.
|
|
174
|
+
const availableHistory = cursorParked ? new Map() : new Map([...loadGateFailWeights()].filter(([file]) => !measuredLastSlice.has(file)));
|
|
175
|
+
const range = pickWithHistory(files, startAt, costs, budgetSecs, availableHistory);
|
|
176
|
+
return emit({ outcome: 'ok', summary: `test-diet pick ${range.rangeLabel} of ${files.length} (≈${Math.round(range.estimatedSecs)}s)`, ...range, total: files.length, budgetSecs,
|
|
48
177
|
...(sweep ? { sweep: true, totalCostSecs, slicesNeeded: sweepPlan?.slicesNeeded, sweepElapsed: elapsed } : {}) });
|
|
49
178
|
}
|
|
50
179
|
|
|
@@ -180,6 +309,23 @@ function recordNightlyAudit(ctx: Context): number {
|
|
|
180
309
|
return emit({ outcome: failing ? 'fail' : 'ok', summary: `nightly audit ${results.length} · failing ${failing}${card ? ' · card draft' : ''}`, failing, ledger: path, ...(card ? { card } : {}) });
|
|
181
310
|
}
|
|
182
311
|
|
|
312
|
+
/** The pick's own gate-history snapshot — `record` reads the files `pick` actually selected from, never a fresh
|
|
313
|
+
* ledger query, so the prescription and the ledger line keep the same basis even if the gate ledger changed
|
|
314
|
+
* between the two graph steps. */
|
|
315
|
+
function pickHistoryFiles(p: Record<string, unknown> | null): GateFailWeight[] {
|
|
316
|
+
const raw = p?.historyFiles;
|
|
317
|
+
if (!Array.isArray(raw)) return [];
|
|
318
|
+
const files: GateFailWeight[] = [];
|
|
319
|
+
for (const entry of raw) {
|
|
320
|
+
if (entry === null || typeof entry !== 'object') continue;
|
|
321
|
+
const x = entry as GateFailWeight;
|
|
322
|
+
if (typeof x.file !== 'string' || typeof x.weight !== 'number' || !Number.isFinite(x.weight)
|
|
323
|
+
|| typeof x.preexisting !== 'number' || typeof x.knownEnv !== 'number' || typeof x.flaky !== 'number') continue;
|
|
324
|
+
files.push({ file: x.file, weight: x.weight, preexisting: x.preexisting, knownEnv: x.knownEnv, flaky: x.flaky });
|
|
325
|
+
}
|
|
326
|
+
return files;
|
|
327
|
+
}
|
|
328
|
+
|
|
183
329
|
export function record(ctx: Context, deps: { createStore?: (root: string) => Pick<CardStore, 'createCard' | 'appendSection' | 'close'>; td1?: ReadonlyMap<string, Td1Disposition> } = {}): number {
|
|
184
330
|
const p = ctx.outputs.pick;
|
|
185
331
|
const m = ctx.outputs.measure;
|
|
@@ -188,27 +334,61 @@ export function record(ctx: Context, deps: { createStore?: (root: string) => Pic
|
|
|
188
334
|
const td1 = deps.td1 ?? td1Dispositions(readFileSync(join(process.cwd(), 'docs/measurements/td1-top200-content-review-2026-10-01.tsv'), 'utf8'));
|
|
189
335
|
const results = measurements.map((x) => propose(judge(x, git(['log', '--since=90.days', '--format=%s', '--', x.file]).split('\n').filter((s) => /^fix\b/i.test(s)).length), td1));
|
|
190
336
|
const previous = p.sweep === true ? lastLedgerLine(effectiveInstanceRoot()) : null;
|
|
191
|
-
const continuing = previous?.sweepVisited && previous.sweepVisited < Number(p.total)
|
|
337
|
+
const continuing = typeof previous?.sweepVisited === 'number' && previous.sweepVisited < Number(p.total)
|
|
192
338
|
&& previous.next === Number(p.start) && previous.total === Number(p.total);
|
|
193
|
-
const visited = p.sweep === true ? Math.min(Number(p.total), (continuing ? previous.sweepVisited! : 0) + results.length) : undefined;
|
|
339
|
+
const visited = p.sweep === true ? Math.min(Number(p.total), (continuing ? previous.sweepVisited! : 0) + Number(p.cursorVisitedCount ?? results.length)) : undefined;
|
|
194
340
|
const sweepCostSecs = p.sweep === true ? (continuing ? previous.sweepCostSecs ?? 0 : 0) + Number(p.estimatedSecs) : undefined;
|
|
195
341
|
const sweepSlices = p.sweep === true ? Number(p.sweepElapsed ?? (continuing ? previous.sweepSlices ?? 0 : 0)) + 1 : undefined;
|
|
342
|
+
const root = effectiveInstanceRoot();
|
|
343
|
+
const historyFiles = pickHistoryFiles(p);
|
|
344
|
+
const weights = new Map(historyFiles.map((entry) => [entry.file, entry]));
|
|
345
|
+
const historyFailures = results.map((result) => weights.get(result.file))
|
|
346
|
+
.filter((entry): entry is GateFailWeight => entry !== undefined);
|
|
347
|
+
const slicePreexisting = historyFailures.reduce((sum, entry) => sum + entry.preexisting, 0);
|
|
348
|
+
const slicePreexistingKnownEnv = historyFailures.reduce((sum, entry) => sum + entry.knownEnv, 0);
|
|
349
|
+
// Metric (boundary ③): each ledger line carries its slice's preexisting ⊕ knownEnv totals AND their delta
|
|
350
|
+
// against the previous slice line, so «판마다 이월» is readable row by row — even on a zero line.
|
|
351
|
+
const previousHistory = (lastLedgerLine(root) as { gateHistory?: { preexisting?: number; knownEnv?: number } } | null)?.gateHistory;
|
|
352
|
+
const history = {
|
|
353
|
+
preexisting: slicePreexisting,
|
|
354
|
+
knownEnv: slicePreexistingKnownEnv,
|
|
355
|
+
total: slicePreexisting + slicePreexistingKnownEnv,
|
|
356
|
+
files: historyFailures.map((entry) => entry.file),
|
|
357
|
+
deltaPreexisting: slicePreexisting - Number(previousHistory?.preexisting ?? 0),
|
|
358
|
+
deltaKnownEnv: slicePreexistingKnownEnv - Number(previousHistory?.knownEnv ?? 0),
|
|
359
|
+
};
|
|
360
|
+
const selectedFiles = Array.isArray(p.files) ? p.files.filter((file): file is string => typeof file === 'string') : results.map((result) => result.file);
|
|
361
|
+
const selectedIndices = Array.isArray(p.selectedIndices) && p.selectedIndices.every((index) => typeof index === 'number')
|
|
362
|
+
? p.selectedIndices as number[] : [];
|
|
196
363
|
const line = {
|
|
197
|
-
|
|
364
|
+
// start/end/next are cursor coordinates; range + selectedIndices describe the exact weighted selection.
|
|
365
|
+
at: new Date().toISOString(), range: typeof p.rangeLabel === 'string' ? p.rangeLabel : `#${p.start}~#${p.end}`,
|
|
366
|
+
start: Number(p.start), end: Number(p.end), next: Number(p.next), total: Number(p.total), selectedFiles, selectedIndices,
|
|
198
367
|
commit: String(m?.commit ?? '?'), budgetSecs: Number(p.budgetSecs), results, ...(visited === undefined ? {} : { sweepVisited: visited, sweepCostSecs, sweepSlices }),
|
|
368
|
+
gateHistory: { preexisting: history.preexisting, knownEnv: history.knownEnv, total: history.total,
|
|
369
|
+
deltaPreexisting: history.deltaPreexisting, deltaKnownEnv: history.deltaKnownEnv },
|
|
199
370
|
};
|
|
200
|
-
const root = effectiveInstanceRoot();
|
|
201
371
|
appendLedger(root, line);
|
|
202
372
|
const card = writeCardDraft(root, line);
|
|
373
|
+
const recipes = new Map(results.map((result) => {
|
|
374
|
+
const entry = weights.get(result.file);
|
|
375
|
+
return [result.file, recipeFor(entry ? { ...result, history: entry } : result)] as const;
|
|
376
|
+
}));
|
|
377
|
+
const recipeCounts: Record<string, number> = {};
|
|
378
|
+
for (const recipe of recipes.values()) recipeCounts[recipe.type] = (recipeCounts[recipe.type] ?? 0) + 1;
|
|
203
379
|
const proposals: Record<string, number> = {};
|
|
204
380
|
for (const result of results) {
|
|
205
|
-
if (!result.proposal) continue;
|
|
206
|
-
|
|
381
|
+
if (td1.get(result.file)?.disposition === 'keep' && result.verdict === 'keep' && !result.proposal) continue;
|
|
382
|
+
const recipe = recipes.get(result.file)!;
|
|
383
|
+
const historyEntry = weights.get(result.file);
|
|
384
|
+
// YAML이 약속한 «판정마다 처방 카드 초안 하나» — 제안·실패·이력이 없는 keep 판정도 카드를 건너뛰지 않는다.
|
|
385
|
+
const proposal = result.proposal ?? (result.verdict === 'failing' ? 'failing' : historyEntry !== undefined ? `gate-history:${recipe.type}` : `verdict:${recipe.type}`);
|
|
386
|
+
proposals[proposal] = (proposals[proposal] ?? 0) + 1;
|
|
207
387
|
let store: Pick<CardStore, 'createCard' | 'appendSection' | 'close'> | undefined;
|
|
208
388
|
try {
|
|
209
389
|
store = deps.createStore?.(root) ?? new CardStore(root);
|
|
210
|
-
const task = store.createCard({ goalId: `test-diet:${result.file}:${
|
|
211
|
-
const observation = { proposal: result.proposal, basis: result.basis, guards: td1.get(result.file)?.guards ?? '',
|
|
390
|
+
const task = store.createCard({ goalId: `test-diet:${result.file}:${proposal}`, title: `시험 다이어트 제안 — ${result.file} · ${proposal} · ${recipe.type}` });
|
|
391
|
+
const observation = { proposal: result.proposal, recipe, basis: result.basis, guards: td1.get(result.file)?.guards ?? '',
|
|
212
392
|
secs: result.secs, rssMb: result.rssMb, caught90: result.caught90, range: line.range, ...(result.effectiveness ? { effectiveness: result.effectiveness } : {}) };
|
|
213
393
|
const fingerprint = createHash('sha256').update(JSON.stringify(observation)).digest('hex');
|
|
214
394
|
const key = `test-diet:${line.commit}:${fingerprint}`;
|
|
@@ -233,8 +413,9 @@ export function record(ctx: Context, deps: { createStore?: (root: string) => Pic
|
|
|
233
413
|
}
|
|
234
414
|
debug.log('test-diet', 'proposed', { range: line.range, proposals });
|
|
235
415
|
const counts = { keep: results.filter((r) => r.verdict === 'keep').length, review: results.filter((r) => r.verdict === 'review').length, failing: results.filter((r) => r.verdict === 'failing').length };
|
|
416
|
+
debug.log('test-diet', 'prescriptions', { range: line.range, recipes: recipeCounts, preexisting: history.preexisting, knownEnv: history.knownEnv });
|
|
236
417
|
debug.log('test-diet', 'recorded', { range: line.range, ...counts, card: card !== null });
|
|
237
|
-
return emit({ outcome: 'ok', summary: `test-diet ${line.range} · keep ${counts.keep} · review ${counts.review} · failing ${counts.failing}${card ? ' · card draft' : ''}`, range: line.range, ...counts, ...(card ? { card } : {}) });
|
|
418
|
+
return emit({ outcome: 'ok', summary: `test-diet ${line.range} · keep ${counts.keep} · review ${counts.review} · failing ${counts.failing}${card ? ' · card draft' : ''}`, range: line.range, ...counts, ...(card ? { card } : {}), recipes: recipeCounts, history });
|
|
238
419
|
}
|
|
239
420
|
|
|
240
421
|
export function mainFailures(ctx: Context, deps: { root?: string; checkout?: string; runFile?: (file: string, cwd: string) => MainFailureResult; now?: Date } = {}): number {
|
package/scripts/ux-sim.ts
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
// bun scripts/ux-sim.ts --fault pod-death # 결함 주입: PARTIAL 줄을 남긴 Pod 가 SIGTERM 으로 지워짐 → 호스트 재방출 판정
|
|
18
18
|
// bun scripts/ux-sim.ts --fault pool-cap # 결함 주입: --pod-pool 에 :N 이 빠진 풀 → 승인 판정(limitedBy)
|
|
19
19
|
// bun scripts/ux-sim.ts --fault sqlite-busy # 결함 주입: 실제 SQLite 잠금 → 로그 배치 버퍼·복구
|
|
20
|
+
// bun scripts/ux-sim.ts emit child-error-long --json # 사건 주입(L0): 격리 우주 원장에 주입 줄 → 소비자 목록
|
|
20
21
|
//
|
|
21
22
|
// ⛔ 이 CLI 는 «실제 위젯 render()» 를 부른다 — 흉내 렌더러가 아니다.
|
|
22
23
|
import { simRenderLogFrame } from '../src/ux-sim/render-frame.js';
|
|
@@ -29,6 +30,44 @@ const PHASES: TurnPhase[] = [
|
|
|
29
30
|
|
|
30
31
|
const argv = process.argv.slice(2);
|
|
31
32
|
|
|
33
|
+
// ── 사건 주입 «이벤트 몽키» (SIM-EVENT-MONKEY · L0) — 자기 플래그를 가진 하위 명령 ──
|
|
34
|
+
// bun scripts/ux-sim.ts emit <kind> [--run <id>] [--variant allowed|refused] [--state-dir <dir>] [--json]
|
|
35
|
+
// bun scripts/ux-sim.ts emit --list
|
|
36
|
+
// ⛔ 운영 우주(~/.elanous)면 쓰기 전에 거부(rc 3). 격리 우주는 ELANOUS_STATE_DIR 또는 --state-dir.
|
|
37
|
+
if (argv[0] === 'emit') {
|
|
38
|
+
// 얇은 별칭 — 해석은 `eln sim emit` 과 «같은» runEventMonkeyCli 하나가 한다.
|
|
39
|
+
const rest = argv.slice(1);
|
|
40
|
+
const EMIT_FLAGS = new Set(['--run', '--variant', '--state-dir', '--json', '--list']);
|
|
41
|
+
const VALUED = new Set(['--run', '--variant', '--state-dir']);
|
|
42
|
+
const unknown = rest.filter((a) => a.startsWith('--') && !EMIT_FLAGS.has(a));
|
|
43
|
+
if (unknown.length > 0) {
|
|
44
|
+
console.error(`⛔ 모르는 인자다: ${unknown.join(' ')} — 아는 것: ${[...EMIT_FLAGS].join(' · ')}`);
|
|
45
|
+
process.exit(2);
|
|
46
|
+
}
|
|
47
|
+
const value = (flag: string): string | undefined => {
|
|
48
|
+
const i = rest.indexOf(flag);
|
|
49
|
+
if (i < 0) return undefined;
|
|
50
|
+
const v = rest[i + 1];
|
|
51
|
+
if (!v || v.startsWith('--')) { console.error(`⛔ ${flag} 에 값이 필요하다`); process.exit(2); }
|
|
52
|
+
return v;
|
|
53
|
+
};
|
|
54
|
+
const { renderEventMonkeyKinds, runEventMonkeyCli } = await import('../src/ux-sim/event-monkey.js');
|
|
55
|
+
if (rest.includes('--list')) { console.log(renderEventMonkeyKinds(rest.includes('--json')).join('\n')); process.exit(0); }
|
|
56
|
+
const positional = rest.filter((a, i) => !a.startsWith('--') && !VALUED.has(rest[i - 1] ?? ''));
|
|
57
|
+
if (positional.length > 1) {
|
|
58
|
+
console.error(`⛔ 사건은 하나만 받는다 — 남는 인자: ${positional.slice(1).join(' ')}`);
|
|
59
|
+
process.exit(2);
|
|
60
|
+
}
|
|
61
|
+
const runId = value('--run');
|
|
62
|
+
const variant = value('--variant');
|
|
63
|
+
const stateDir = value('--state-dir');
|
|
64
|
+
const out = runEventMonkeyCli({ kindName: positional[0], json: rest.includes('--json'),
|
|
65
|
+
...(runId ? { runId } : {}), ...(variant ? { variant } : {}), ...(stateDir ? { stateDir } : {}) });
|
|
66
|
+
for (const line of out.stdout) console.log(line);
|
|
67
|
+
for (const line of out.stderr) console.error(line);
|
|
68
|
+
process.exit(out.code);
|
|
69
|
+
}
|
|
70
|
+
|
|
32
71
|
// ⛔⭐ 모르는 인자를 «조용히 삼키지» 않는다 — 이름을 대고 거부한다.
|
|
33
72
|
//
|
|
34
73
|
// 🚨 2026-08-27 실측: `--trajectory-list`(오타 · 실제는 `--list-trajectories`)를 쳤더니
|
|
@@ -18,8 +18,16 @@ import { elanousSelfAmbientBaseParts } from './self-ambient.js';
|
|
|
18
18
|
|
|
19
19
|
export const SELF_AMBIENT_FRESH_MS = 30_000;
|
|
20
20
|
export const SELF_AMBIENT_STALE_MAX_MS = 10 * 60_000;
|
|
21
|
+
export const SELF_AMBIENT_KEEP_WARM_ACTIVE_MS = 25_000;
|
|
22
|
+
export const SELF_AMBIENT_KEEP_WARM_IDLE_MS = 8 * 60_000;
|
|
23
|
+
const SELF_AMBIENT_IDLE_AFTER_MS = 2 * 60_000;
|
|
21
24
|
const WORKER_TIMEOUT_MS = 60_000;
|
|
22
25
|
|
|
26
|
+
/** Keep turn context warm while active; avoid periodic ambient scans during a long idle. */
|
|
27
|
+
export function selfAmbientKeepWarmIntervalMs(idleMs: number): number {
|
|
28
|
+
return idleMs >= SELF_AMBIENT_IDLE_AFTER_MS ? SELF_AMBIENT_KEEP_WARM_IDLE_MS : SELF_AMBIENT_KEEP_WARM_ACTIVE_MS;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
interface CacheEntry { at: number; version: number; parts: string[] }
|
|
24
32
|
|
|
25
33
|
export interface SelfAmbientCacheDeps {
|
|
@@ -35,6 +35,22 @@ export interface AcpReviewerOpts {
|
|
|
35
35
|
timeoutMs?: number;
|
|
36
36
|
/** One deadline for spawn → initialize → session/new → model select (ms). A child that never answers ACP must not hang the review. Default min(timeoutMs, 60000). */
|
|
37
37
|
handshakeTimeoutMs?: number;
|
|
38
|
+
/**
|
|
39
|
+
* ACP-REVIEW-VIA-TEAMCLAUDE: how a `claude` review without an explicit `backendSpec` finds the teamclaude
|
|
40
|
+
* (cct) route. Default (production, non-injected) = `resolveTeamclaudeReviewRoute()`; an injected agent
|
|
41
|
+
* without this seam does not probe the host.
|
|
42
|
+
*/
|
|
43
|
+
resolveClaudeRoute?: () => import('../self-dev/review-provider-fallback.js').TeamclaudeReviewRoute
|
|
44
|
+
| Promise<import('../self-dev/review-provider-fallback.js').TeamclaudeReviewRoute>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** ACP claude reviews read the repo with tools and ran 228–345s in practice (OPC #25934); 300s cut them. */
|
|
48
|
+
const ACP_CLAUDE_REVIEW_TIMEOUT_SEC = 600;
|
|
49
|
+
const ACP_REVIEW_TIMEOUT_SEC = 300;
|
|
50
|
+
|
|
51
|
+
/** Default per-review deadline (seconds) when the caller gives none. */
|
|
52
|
+
export function defaultAcpReviewTimeoutSec(backend: string): number {
|
|
53
|
+
return canonicalizeBackendId(backend) === 'claude' ? ACP_CLAUDE_REVIEW_TIMEOUT_SEC : ACP_REVIEW_TIMEOUT_SEC;
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
/**
|
|
@@ -96,6 +112,26 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
|
|
|
96
112
|
// The injected seam deliberately accepts arbitrary test backends. The
|
|
97
113
|
// production path alone resolves aliases and transport through the factory.
|
|
98
114
|
const backend = canonicalizeBackendId(requestedBackend);
|
|
115
|
+
const timeoutMs = opts.timeoutMs ?? defaultAcpReviewTimeoutSec(backend) * 1000;
|
|
116
|
+
// ACP-REVIEW-VIA-TEAMCLAUDE (대표 10-21): a claude review goes through teamclaude (multi-account proxy) when it
|
|
117
|
+
// answers with a base URL — same cct spawn as the subscription lane. No answer = the prior path, recorded.
|
|
118
|
+
let backendSpec = opts.backendSpec;
|
|
119
|
+
let childEnv = opts.env;
|
|
120
|
+
const resolveClaudeRoute = backend === 'claude' && !opts.backendSpec
|
|
121
|
+
? opts.resolveClaudeRoute ?? (injected ? undefined
|
|
122
|
+
: async () => (await import('../self-dev/review-provider-fallback.js')).resolveTeamclaudeReviewRoute())
|
|
123
|
+
: undefined;
|
|
124
|
+
if (resolveClaudeRoute) {
|
|
125
|
+
let route: import('../self-dev/review-provider-fallback.js').TeamclaudeReviewRoute;
|
|
126
|
+
try { route = await resolveClaudeRoute(); } catch { route = { reason: 'teamclaude-unavailable' }; }
|
|
127
|
+
if (route.spawn) { backendSpec = route.spawn.backendSpec; childEnv = route.spawn.env; }
|
|
128
|
+
debug.log('review.acp', 'claude-route', {
|
|
129
|
+
viaTeamclaude: Boolean(route.spawn),
|
|
130
|
+
baseUrlSet: Boolean(childEnv?.ANTHROPIC_BASE_URL),
|
|
131
|
+
timeoutSec: Math.round(timeoutMs / 1000),
|
|
132
|
+
reason: route.reason,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
99
135
|
// ⛔⭐⭐⭐ 백엔드 해석은 «`try` 밖»이라 여기서 던지면 아래 `catch` 의 `acp-review/error` 가
|
|
100
136
|
// «안 걸린다**. 그래서 `--acp-backend claude-code`(미등록) 같은 오타를 주면 레지스트리가
|
|
101
137
|
// ***`Unknown ACP backend "claude-code". Known: …"`*** 라는 «완벽한» 오류를 던지는데도
|
|
@@ -105,14 +141,13 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
|
|
|
105
141
|
// ⇒ 이 한 줄만 자기 catch 로 감싼다(전체 try 를 앞당기면 `start` 관측이 그 안으로 들어간다).
|
|
106
142
|
let transport: string | null;
|
|
107
143
|
try {
|
|
108
|
-
transport = injected ? null :
|
|
144
|
+
transport = injected ? null : backendSpec?.transport ?? getAcpBackend(backend).transport ?? 'acp';
|
|
109
145
|
} catch (e) {
|
|
110
146
|
debug.log('acp-review', 'error', {
|
|
111
147
|
requestedBackend, backend, stage: 'resolve-backend', message: (e as Error).message,
|
|
112
148
|
}, { level: 'error' });
|
|
113
149
|
throw e;
|
|
114
150
|
}
|
|
115
|
-
const timeoutMs = opts.timeoutMs ?? 300_000;
|
|
116
151
|
debug.log('acp-review', 'start', {
|
|
117
152
|
requestedBackend,
|
|
118
153
|
backend,
|
|
@@ -130,7 +165,7 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
|
|
|
130
165
|
let capabilitiesObserved = false;
|
|
131
166
|
const agentOpts: Omit<AcpAgentOpts, 'backendId'> = {
|
|
132
167
|
cwd: opts.cwd,
|
|
133
|
-
...(
|
|
168
|
+
...(backendSpec ? { backendSpec, env: childEnv } : {}),
|
|
134
169
|
log: (message) => debug.log('acp-review', 'agent-log', { backend, message }),
|
|
135
170
|
onCapabilities: (capabilities) => {
|
|
136
171
|
capabilitiesObserved = true;
|
|
@@ -159,7 +194,7 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
|
|
|
159
194
|
// chat agents, whose callbacks and lifecycle must not be mutated here.
|
|
160
195
|
// Grok's start can hang before the manager registers the subprocess;
|
|
161
196
|
// own it directly so the handshake timeout can stop that child.
|
|
162
|
-
const directAgent = injected || Boolean(
|
|
197
|
+
const directAgent = injected || Boolean(backendSpec) || backend === 'grok';
|
|
163
198
|
const reviewManager = directAgent ? undefined : new AcpAgentManager();
|
|
164
199
|
let agent: AcpAgent | undefined;
|
|
165
200
|
let text = '';
|
|
@@ -684,7 +684,21 @@ const LONG_BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*(?:[-—–]
|
|
|
684
684
|
const KNOWN_NO_FINDING_REMARKS = new Set([
|
|
685
685
|
// #27349 저장 JSON의 실제 무소견 문구.
|
|
686
686
|
'문서 전용 변경이고 의도된 산출물이 실제로 존재하며 배선 누락·죽은 코드·Goodhart 해당 없음',
|
|
687
|
+
// #29974 ACP 실측: 단독 (없음) 뒤에 차단 결함 부재와 통과 근거를 적은 닫힌 문장.
|
|
688
|
+
'막는 결함은 찾지 못했다. ref → 전체 SHA 고정, 이미지 SHA12 태그, Job 쪽 `imageCommit==source.sha`·`image==shelfImage` 가드까지 한 줄로 이어진다.',
|
|
687
689
|
]);
|
|
690
|
+
// #30028 ACP 저장 리뷰의 긍정 수용 서술. 광범위한 의미 추정보다 원문을 고정한다.
|
|
691
|
+
const KNOWN_POSITIVE_FINDINGS = new Set([
|
|
692
|
+
'없음. 수용 기준은 코드와 시험 기준으로 충족한다.',
|
|
693
|
+
'프로토타입 키(`constructor`·`__proto__`)를 Map 으로 바르게 센다.',
|
|
694
|
+
'분모는 `task-agent/entrance-denominator` 별도 이벤트로만 나간다. `task-agent/action` 은 그대로다.',
|
|
695
|
+
'retro 사실과 tasks cover 집계는 분모 줄이 있든 없든 같다. 시험(`retro-cli.test.ts`)이 이를 고정하고, 임시 폴더는 `finally` 의 `rmSync` 로 지운다.',
|
|
696
|
+
// 이 후속 PR 자체의 ACP r2: 닫힌 무소견 문장.
|
|
697
|
+
'없음 — 막는 결함은 찾지 못했다.',
|
|
698
|
+
]);
|
|
699
|
+
function isPositiveNoFinding(text: string): boolean {
|
|
700
|
+
return KNOWN_POSITIVE_FINDINGS.has(text);
|
|
701
|
+
}
|
|
688
702
|
/** 괄호 안 `없음` 뒤 설명이 닫힌 무소견 문법에 정확히 들어가는가. */
|
|
689
703
|
function isLongNoFindingBracket(text: string): boolean {
|
|
690
704
|
const m = LONG_BRACKETED_SENTINEL.exec(text.trim());
|
|
@@ -699,8 +713,11 @@ function isLongNoFindingBracket(text: string): boolean {
|
|
|
699
713
|
export function isNoneSentinelFinding(finding: string): boolean {
|
|
700
714
|
const text = finding.trim();
|
|
701
715
|
if (!text || isBracketedPlaceholder(text)) return true;
|
|
716
|
+
if (isPositiveNoFinding(text)) return true;
|
|
702
717
|
if (/^[-—–]+$/.test(text)) return true;
|
|
703
718
|
const markerText = text.replace(/^[—–-]+\s*|\s*[—–-]+$/g, '').trim();
|
|
719
|
+
const leadingNone = /^[((]\s*(?:없음|none)\s*[))]\s+(.+)$/i.exec(markerText);
|
|
720
|
+
if (leadingNone && KNOWN_NO_FINDING_REMARKS.has(leadingNone[1]!.trim())) return true;
|
|
704
721
|
if (markerText && (BARE_SENTINEL.test(markerText) || DASH_ONLY_SENTINEL.test(markerText) || DASH_WRAPPED_BRACKETED_SENTINEL.test(markerText))) return true;
|
|
705
722
|
const bracketed = BRACKETED_SENTINEL.exec(markerText);
|
|
706
723
|
if (bracketed) {
|