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/ux-sim/fake-bin.ts
CHANGED
|
@@ -15,15 +15,28 @@
|
|
|
15
15
|
// tests that run where the tool exists.
|
|
16
16
|
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
17
17
|
import { tmpdir } from 'node:os';
|
|
18
|
-
import { delimiter, join } from 'node:path';
|
|
18
|
+
import { delimiter, isAbsolute, join } from 'node:path';
|
|
19
19
|
|
|
20
20
|
export interface FakeBinSpec {
|
|
21
21
|
readonly stdout?: string;
|
|
22
22
|
readonly stderr?: string;
|
|
23
23
|
/** Exit code (default 0). */
|
|
24
24
|
readonly exitCode?: number;
|
|
25
|
-
/** Stay alive this long before exiting — for long-running daemons a test kills
|
|
25
|
+
/** Stay alive this long before exiting — for long-running daemons a test kills, or a fractional
|
|
26
|
+
* per-call latency (e.g. 0.2) for a test that measures fan-out. */
|
|
26
27
|
readonly sleepSeconds?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Fake only the calls whose argv starts with these words (e.g. `['worktree', 'add']`);
|
|
30
|
+
* every other call `exec`s `otherwise` with the same argv. Needs `otherwise`.
|
|
31
|
+
*/
|
|
32
|
+
readonly whenArgsStartWith?: readonly string[];
|
|
33
|
+
/** Absolute path of the real executable that serves the calls `whenArgsStartWith` does not match. */
|
|
34
|
+
readonly otherwise?: string;
|
|
35
|
+
/**
|
|
36
|
+
* After stdout/stderr (and any sleep), the fake kills itself with this signal instead of exiting —
|
|
37
|
+
* a «died without a word» failure (`status` null · `signal` set). `exitCode` is then never reached.
|
|
38
|
+
*/
|
|
39
|
+
readonly killSignal?: 'KILL' | 'TERM' | 'INT' | 'HUP' | 'ABRT' | 'SEGV';
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
export interface FakeBinCall {
|
|
@@ -48,6 +61,7 @@ export interface FakeBins {
|
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
const NAME = /^[A-Za-z0-9._+-]+$/;
|
|
64
|
+
const KILL_SIGNALS: ReadonlySet<string> = new Set(['KILL', 'TERM', 'INT', 'HUP', 'ABRT', 'SEGV']);
|
|
51
65
|
|
|
52
66
|
function shellQuote(value: string): string {
|
|
53
67
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -57,25 +71,37 @@ function script(name: string, spec: FakeBinSpec, dataDir: string, logPath: strin
|
|
|
57
71
|
const lines = ['#!/bin/sh'];
|
|
58
72
|
// One record per call: name and each argv entry NUL-terminated (one printf), then an ASCII record
|
|
59
73
|
// separator \x1e (a second printf). `calls()` drops the unterminated tail, so a reader never sees half a record.
|
|
60
|
-
|
|
74
|
+
// The record is staged in its own file and appended by one `cat` (one write), so concurrent calls never interleave.
|
|
75
|
+
// The fake PATH may itself contain mktemp, cat, or rm. Use the shell's default utility path
|
|
76
|
+
// for recorder and payload reads so a fake of one of those names cannot recursively call itself.
|
|
77
|
+
lines.push(`rec=$(command -p mktemp ${shellQuote(join(dataDir, 'rec.XXXXXX'))})`);
|
|
78
|
+
lines.push(`{ printf '%s\\0' ${shellQuote(name)} "$@"; printf '\\036'; } > "$rec"; command -p cat "$rec" >> ${shellQuote(logPath)}; command -p rm -f "$rec"`);
|
|
79
|
+
if (spec.whenArgsStartWith !== undefined && spec.otherwise !== undefined) {
|
|
80
|
+
const words = spec.whenArgsStartWith;
|
|
81
|
+
const tests = [`[ "$#" -ge ${words.length} ]`, ...words.map((word, index) => `[ "$${index + 1}" = ${shellQuote(word)} ]`)];
|
|
82
|
+
lines.push(`if ${tests.join(' && ')}; then :; else exec ${shellQuote(spec.otherwise)} "$@"; fi`);
|
|
83
|
+
}
|
|
61
84
|
if (spec.stdout !== undefined) {
|
|
62
85
|
const file = join(dataDir, `${name}.stdout`);
|
|
63
86
|
writeFileSync(file, spec.stdout);
|
|
64
|
-
lines.push(`cat ${shellQuote(file)}`);
|
|
87
|
+
lines.push(`command -p cat ${shellQuote(file)}`);
|
|
65
88
|
}
|
|
66
89
|
if (spec.stderr !== undefined) {
|
|
67
90
|
const file = join(dataDir, `${name}.stderr`);
|
|
68
91
|
writeFileSync(file, spec.stderr);
|
|
69
|
-
lines.push(`cat ${shellQuote(file)} >&2`);
|
|
92
|
+
lines.push(`command -p cat ${shellQuote(file)} >&2`);
|
|
70
93
|
}
|
|
71
94
|
const exitCode = spec.exitCode ?? 0;
|
|
72
95
|
if (spec.sleepSeconds !== undefined && spec.sleepSeconds > 0) {
|
|
73
|
-
|
|
96
|
+
// Whole seconds stay as they were; a fraction keeps millisecond precision (`sleep 0.2` — BSD · GNU · busybox).
|
|
97
|
+
const seconds = Number.isInteger(spec.sleepSeconds) ? spec.sleepSeconds : Math.ceil(spec.sleepSeconds * 1000) / 1000;
|
|
74
98
|
// exit 0: `exec` so killing the fake kills the sleep itself. Any other code needs the shell to
|
|
75
99
|
// outlive the sleep; a fake killed mid-sleep then leaves `sleep` until `sleepSeconds` ends.
|
|
76
|
-
|
|
100
|
+
// killSignal must outlive the sleep too, or `exec` would replace the shell before the kill line.
|
|
101
|
+
if (exitCode === 0 && spec.killSignal === undefined) lines.push(`exec sleep ${seconds}`);
|
|
77
102
|
else lines.push(`sleep ${seconds}`);
|
|
78
103
|
}
|
|
104
|
+
if (spec.killSignal !== undefined) lines.push(`kill -s ${spec.killSignal} $$`);
|
|
79
105
|
lines.push(`exit ${exitCode}`);
|
|
80
106
|
return `${lines.join('\n')}\n`;
|
|
81
107
|
}
|
|
@@ -83,6 +109,15 @@ function script(name: string, spec: FakeBinSpec, dataDir: string, logPath: strin
|
|
|
83
109
|
export function createFakeBins(specs: Readonly<Record<string, FakeBinSpec>>): FakeBins {
|
|
84
110
|
for (const name of Object.keys(specs)) {
|
|
85
111
|
if (!NAME.test(name) || name === '.' || name === '..') throw new Error(`fake-bin: invalid executable name ${JSON.stringify(name)}`);
|
|
112
|
+
const spec = specs[name]!;
|
|
113
|
+
if (spec.killSignal !== undefined && !KILL_SIGNALS.has(spec.killSignal)) throw new Error(`fake-bin: ${name}: killSignal must be one of ${[...KILL_SIGNALS].join(', ')}`);
|
|
114
|
+
if (spec.whenArgsStartWith !== undefined) {
|
|
115
|
+
if (spec.whenArgsStartWith.length === 0) throw new Error(`fake-bin: ${name}: whenArgsStartWith needs at least one word`);
|
|
116
|
+
if (spec.otherwise === undefined) throw new Error(`fake-bin: ${name}: whenArgsStartWith needs otherwise (the real executable)`);
|
|
117
|
+
if (!isAbsolute(spec.otherwise)) throw new Error(`fake-bin: ${name}: otherwise must be an absolute path, got ${JSON.stringify(spec.otherwise)}`);
|
|
118
|
+
} else if (spec.otherwise !== undefined) {
|
|
119
|
+
throw new Error(`fake-bin: ${name}: otherwise is only used with whenArgsStartWith`);
|
|
120
|
+
}
|
|
86
121
|
}
|
|
87
122
|
const root = mkdtempSync(join(tmpdir(), 'ux-sim-fake-bin-'));
|
|
88
123
|
const dir = join(root, 'bin');
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// ── 결함 주입 심 — «next-move→dispatch 간선 ⊕ push 확인 지연 unconfirmed» ─────────
|
|
2
|
+
//
|
|
3
|
+
// 🚨 왜 이것이 있나 (NEXTMOVE-HARDEN · 2026-10-21)
|
|
4
|
+
// 운영 로그에는 merge→next-move 1건만 있고 next-move→dispatch 0건이라 E4 가 실물로
|
|
5
|
+
// 증명되지 않았다. 운영 코드는 건드리면 안 되므로, 이미 있는 생산 함수를 그대로 돌려
|
|
6
|
+
// 같은 PR 수리 한 바퀴에서 나와야 할 두 사건을 «기다리지 않고 일으킨다».
|
|
7
|
+
// ① next-move→dispatch graph-edge-taken 1건 — runRepairCycle 이 repairNextMove 판정 뒤
|
|
8
|
+
// recordJourneyEdge(judged.route, 'dispatch') 로 남기는 관측.
|
|
9
|
+
// ② push 확인 지연 → unconfirmed 1건 — applyRepairBundle 이 exact-head push 에 성공한 뒤
|
|
10
|
+
// PR 머리 확인(CONFIRM_DELAYS_MS)이 가짜 gh 의 늙은 머리를 못 따라잡아 내는 전이.
|
|
11
|
+
//
|
|
12
|
+
// ⛔ 흉내 내지 않는다(FAULT-SCOPE-ESCAPE-LIFT 규율): 운영이 부르는 «같은» 함수를 그대로 부른다 —
|
|
13
|
+
// ① runRepairCycle(src/task-agent/repair-cycle.ts) — 발사 틱 ⊕ 결과 회수(CAS) 틱
|
|
14
|
+
// ② repairNextMove ⊕ judgeNextMove(src/task-agent/repair-next-move.ts · judge.ts)
|
|
15
|
+
// ③ applyRepairBundle(src/task-agent/repair-branch-cas.ts) — exact-head CAS ⊕ --force-with-lease push
|
|
16
|
+
// git 은 진짜 git 을 임시 bare 원격(temp-git-remote.ts)에, gh 는 공유 PATH 심(fake-bin.ts)을 쓴다.
|
|
17
|
+
// kubectl·Pod·GitHub API·네트워크는 없다. 카드 상태는 임시 디렉터리 하나에만 쓰고 끝에 지운다.
|
|
18
|
+
//
|
|
19
|
+
// 영수증 = 명령 ⊕ injectionId ⊕ 결과(receipt). 시험 출력 문면 = renderFaultNextmoveDispatch(층 L2).
|
|
20
|
+
|
|
21
|
+
import { spawnSync } from 'node:child_process';
|
|
22
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
23
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
24
|
+
import { tmpdir } from 'node:os';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { debug } from '../debug/log.js';
|
|
27
|
+
import { createFakeBins, type FakeBins } from './fake-bin.js';
|
|
28
|
+
import { createTempGitRemote, type TempGitRemote } from './temp-git-remote.js';
|
|
29
|
+
import { runRepairCycle, type RepairCycleInput, type RepairLaunchRequest } from '../task-agent/repair-cycle.js';
|
|
30
|
+
import { applyRepairBundle, REPAIR_BUNDLE_REF, type RepairCasDeps } from '../task-agent/repair-branch-cas.js';
|
|
31
|
+
import { readTaskCard, writeTaskCards, type TaskCard } from '../task-agent/task-hand.js';
|
|
32
|
+
|
|
33
|
+
/** 이 심을 재는 증거 명령 — 매뉴얼 §3 과 영수증의 «명령» 칸이 같은 문자열이다. */
|
|
34
|
+
export const FAULT_NEXTMOVE_DISPATCH_COMMAND = 'bun test src/ux-sim/fault-nextmove-dispatch.test.ts';
|
|
35
|
+
|
|
36
|
+
const PR = 30404;
|
|
37
|
+
const ORIGIN_REPO = 'sim-owner/sim-repo';
|
|
38
|
+
const CARD_ID = 'ta-sim-nextmove';
|
|
39
|
+
const BRANCH = 'feature';
|
|
40
|
+
const JOB = 'si-sim-nextmove';
|
|
41
|
+
const MUST_FIX = ['fix the broken assertion'];
|
|
42
|
+
|
|
43
|
+
export interface FaultNextmoveDispatchFixture {
|
|
44
|
+
/** 임시 실물 git 원격(bare·seed·checkout) — casDeps.git 이 여기에 진짜 git 을 돌린다. */
|
|
45
|
+
readonly remote: TempGitRemote;
|
|
46
|
+
/** 가짜 gh PATH 심 — prView 가 이름 그대로 PATH 에서 찾는다. */
|
|
47
|
+
readonly fakeBins: FakeBins;
|
|
48
|
+
readonly root: string;
|
|
49
|
+
readonly statePath: string;
|
|
50
|
+
readonly artifactDir: string;
|
|
51
|
+
/** 리뷰된 PR 머리(수리 base). */
|
|
52
|
+
readonly head: string;
|
|
53
|
+
/** 수리 commit(머리의 자식). */
|
|
54
|
+
readonly commit: string;
|
|
55
|
+
readonly bundleSha256: string;
|
|
56
|
+
/** 생산 확인 루프가 요청한 지연(ms) — 심의 sleep 이 기다리지 않고 적는다. */
|
|
57
|
+
readonly confirmSleeps: number[];
|
|
58
|
+
cleanup(): void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** 같은 PR 수리 한 바퀴에 필요한 실물 상태를 임시 경로에 세운다. GitHub API·네트워크 없음. */
|
|
62
|
+
function createFaultNextmoveDispatchFixture(): FaultNextmoveDispatchFixture {
|
|
63
|
+
const remote = createTempGitRemote();
|
|
64
|
+
let root: string | undefined;
|
|
65
|
+
try {
|
|
66
|
+
root = mkdtempSync(join(tmpdir(), 'ux-sim-nextmove-'));
|
|
67
|
+
const checkout = remote.checkout;
|
|
68
|
+
const git = remote.git;
|
|
69
|
+
// clone 은 seed 의 로컬 신원을 물려받지 않는다(GIT_CONFIG_GLOBAL 이 비어 있음) — 체크아웃에 심어준다.
|
|
70
|
+
git(checkout, ['config', 'user.email', 'sim@example.test']);
|
|
71
|
+
git(checkout, ['config', 'user.name', 'ux-sim fault nextmove']);
|
|
72
|
+
// PR 가지 — 리뷰된 머리 A. 원격에도 둔다(CAS 가 임대 비교할 기준).
|
|
73
|
+
git(checkout, ['checkout', '-q', '-b', BRANCH]);
|
|
74
|
+
writeFileSync(join(checkout, 'CHANGE.md'), 'pr base\n');
|
|
75
|
+
git(checkout, ['add', 'CHANGE.md']);
|
|
76
|
+
git(checkout, ['commit', '-q', '-m', 'pr base']);
|
|
77
|
+
const head = git(checkout, ['rev-parse', 'HEAD']);
|
|
78
|
+
git(checkout, ['push', '-q', 'origin', `HEAD:refs/heads/${BRANCH}`]);
|
|
79
|
+
// 수리 commit B — 머리의 자식. 원격은 아직 A 에 있다.
|
|
80
|
+
writeFileSync(join(checkout, 'CHANGE.md'), 'pr base\nfixed\n');
|
|
81
|
+
git(checkout, ['add', 'CHANGE.md']);
|
|
82
|
+
git(checkout, ['commit', '-q', '-m', 'repair fix']);
|
|
83
|
+
const commit = git(checkout, ['rev-parse', 'HEAD']);
|
|
84
|
+
// 수리 bundle — 생산 REPAIR_BUNDLE_REF 그대로.
|
|
85
|
+
git(checkout, ['update-ref', REPAIR_BUNDLE_REF, commit]);
|
|
86
|
+
const artifactDir = join(root, 'pod-artifacts', JOB, 'repair');
|
|
87
|
+
mkdirSync(artifactDir, { recursive: true });
|
|
88
|
+
const bundlePath = join(artifactDir, 'commit.bundle');
|
|
89
|
+
git(checkout, ['bundle', 'create', bundlePath, REPAIR_BUNDLE_REF]);
|
|
90
|
+
const bundleSha256 = createHash('sha256').update(readFileSync(bundlePath)).digest('hex');
|
|
91
|
+
// 가짜 gh — 운영 prView 의 --json 인자 그대로. 머리는 «늙은» A 로 고정(확인 지연을 내는 장치).
|
|
92
|
+
const ghView = JSON.stringify({
|
|
93
|
+
state: 'OPEN', headRefOid: head, headRefName: BRANCH,
|
|
94
|
+
isCrossRepository: false, headRepository: { nameWithOwner: ORIGIN_REPO },
|
|
95
|
+
});
|
|
96
|
+
const fakeBins = createFakeBins({ gh: { stdout: `${ghView}\n` } });
|
|
97
|
+
// TA 카드 — 수리 틱이 읽는 상태 파일.
|
|
98
|
+
const statePath = join(root, 'task-agent-actions.json');
|
|
99
|
+
const card: TaskCard = {
|
|
100
|
+
id: CARD_ID, text: 'fix the PR', seat: 'TC',
|
|
101
|
+
createdAt: '2026-10-21T08:00:00.000Z', status: 'launched', history: [],
|
|
102
|
+
pr: { number: PR, url: `https://github.com/${ORIGIN_REPO}/pull/${PR}` },
|
|
103
|
+
childLlm: { provider: 'openai-codex', model: 'gpt-6-sol' },
|
|
104
|
+
};
|
|
105
|
+
writeTaskCards(statePath, [card]);
|
|
106
|
+
let cleaned = false;
|
|
107
|
+
return {
|
|
108
|
+
remote, fakeBins, root, statePath, artifactDir, head, commit, bundleSha256, confirmSleeps: [],
|
|
109
|
+
cleanup(): void {
|
|
110
|
+
if (cleaned) return;
|
|
111
|
+
cleaned = true;
|
|
112
|
+
fakeBins.cleanup();
|
|
113
|
+
remote.cleanup();
|
|
114
|
+
if (root !== undefined) rmSync(root, { recursive: true, force: true });
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
} catch (error) {
|
|
118
|
+
remote.cleanup();
|
|
119
|
+
if (root !== undefined) rmSync(root, { recursive: true, force: true });
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 생산 applyRepairBundle 에 줄 CAS deps — ⛔ 판정 로직(CAS·push·확인 지연 루프)은 여기 하나도 없다.
|
|
126
|
+
* `RepairCasDeps` 는 생산이 주입 자리로 열어 둔 I/O 어댑터 셋뿐이고, 셋 다 바깥 세계만 바꾼다:
|
|
127
|
+
* · git — 진짜 git 을 그대로 spawn 한다. 바꾸는 것은 env(임시 원격의 GIT_CONFIG_GLOBAL 등) 하나.
|
|
128
|
+
* · prView — 진짜 `gh pr view <pr> --json …` 를 PATH 의 가짜 gh 심에 spawn 하고 JSON 꼴만 옮긴다.
|
|
129
|
+
* 생산 어댑터의 필드 검증은 복사하지 않는다(가짜 gh 가 늘 같은 꼴을 내 판정에 안 든다).
|
|
130
|
+
* · originRepo — 임시 원격은 file:// 라 github 신원이 없다. 신원 한 줄만 심이 준다.
|
|
131
|
+
*/
|
|
132
|
+
function casDeps(fixture: FaultNextmoveDispatchFixture): RepairCasDeps {
|
|
133
|
+
const ghEnv = { ...process.env, PATH: fixture.fakeBins.path() };
|
|
134
|
+
return {
|
|
135
|
+
git(cwd, args) {
|
|
136
|
+
const r = spawnSync('git', args, { cwd, encoding: 'utf8', timeout: 120_000, env: { ...process.env, ...fixture.remote.gitEnv } });
|
|
137
|
+
return { status: r.status, stdout: String(r.stdout ?? ''), stderr: String(r.stderr ?? '') };
|
|
138
|
+
},
|
|
139
|
+
prView(cwd, pr) {
|
|
140
|
+
const r = spawnSync('gh', ['pr', 'view', String(pr), '--json', 'state,headRefOid,headRefName,isCrossRepository,headRepository'],
|
|
141
|
+
{ cwd, encoding: 'utf8', timeout: 30_000, env: ghEnv });
|
|
142
|
+
if (r.status !== 0) return null;
|
|
143
|
+
const v = JSON.parse(String(r.stdout)) as {
|
|
144
|
+
state: string; headRefOid: string; headRefName: string; isCrossRepository: boolean; headRepository: { nameWithOwner: string };
|
|
145
|
+
};
|
|
146
|
+
return { state: v.state, head: v.headRefOid, branch: v.headRefName, crossRepository: v.isCrossRepository, headRepo: v.headRepository.nameWithOwner };
|
|
147
|
+
},
|
|
148
|
+
originRepo: () => ORIGIN_REPO,
|
|
149
|
+
// 확인 지연 루프(CONFIRM_DELAYS_MS)는 생산 그대로 돈다 — 실제로 기다리지만 않는다(Atomics.wait 블로킹 제거).
|
|
150
|
+
sleep: (ms) => { fixture.confirmSleeps.push(ms); },
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface FaultNextmoveDispatchObservation {
|
|
155
|
+
/** 이번 주입의 식별자 — 영수증 칸. */
|
|
156
|
+
readonly injectionId: string;
|
|
157
|
+
/** ① next-move→dispatch graph-edge-taken 관측(debug sink 원문). */
|
|
158
|
+
readonly edge: { readonly count: number; readonly record: Record<string, unknown> | undefined; readonly decision: string };
|
|
159
|
+
/** ② push 확인 지연 → unconfirmed 전이. */
|
|
160
|
+
readonly unconfirmed: { readonly decision: string; readonly status: string | undefined; readonly reason: string };
|
|
161
|
+
/** 회수 틱 뒤 임시 원격의 PR 가지 머리 — 수리 commit 이면 exact-head push 가 실제로 됐다. */
|
|
162
|
+
readonly remoteHead: string;
|
|
163
|
+
/** 장치가 세운 수리 commit — remoteHead 와 대조한다. */
|
|
164
|
+
readonly repairCommit: string;
|
|
165
|
+
/** 가짜 gh PATH 심이 실제로 불린 횟수. */
|
|
166
|
+
readonly ghCalls: number;
|
|
167
|
+
/** 생산 확인 루프가 요청한 지연(ms) — 확인 지연이 «생산 루프를 다 돈 뒤» unconfirmed 가 됐다는 증거. */
|
|
168
|
+
readonly confirmSleeps: readonly number[];
|
|
169
|
+
/** 두 틱이 낸 알림(심이 받아 적음 · 운영 우편함 0). */
|
|
170
|
+
readonly notified: readonly { seat: string; body: string }[];
|
|
171
|
+
/** 영수증 = 명령 ⊕ injectionId ⊕ 결과. */
|
|
172
|
+
readonly receipt: { readonly command: string; readonly injectionId: string; readonly result: string };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** 같은 PR 수리 한 바퀴를 생산 함수로 돌려 두 사건을 낸다. 발사·회수 두 틱이다. */
|
|
176
|
+
export async function simFaultNextmoveDispatch(): Promise<FaultNextmoveDispatchObservation> {
|
|
177
|
+
const fixture = createFaultNextmoveDispatchFixture();
|
|
178
|
+
const injectionId = `fnd-${randomBytes(6).toString('hex')}`;
|
|
179
|
+
const firstTick = new Date('2026-10-21T08:00:00.000Z');
|
|
180
|
+
const secondTick = new Date('2026-10-21T08:01:00.000Z');
|
|
181
|
+
const edges: Record<string, unknown>[] = [];
|
|
182
|
+
const off = debug.registerSink({
|
|
183
|
+
name: `ux-sim-fault-nextmove-dispatch-${injectionId}`,
|
|
184
|
+
emit: (record) => {
|
|
185
|
+
if (record.category === 'self-implement' && record.event === 'graph-edge-taken') edges.push(record.data as Record<string, unknown>);
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
// ⛔ 생산 기본 notify(`msg post`)·request(detached elanous spawn)에 «절대» 닿지 않게 두 틱 모두 기록용 심을 준다.
|
|
189
|
+
// 상태 전이가 바뀌어 기본값으로 떨어지면 운영 우편함·실제 발사가 된다(리뷰 r1).
|
|
190
|
+
const notified: { seat: string; body: string }[] = [];
|
|
191
|
+
const notify = (seat: string, body: string): void => { notified.push({ seat, body }); };
|
|
192
|
+
try {
|
|
193
|
+
const base = (now: Date): RepairCycleInput => ({
|
|
194
|
+
// 매 틱 직전의 카드 원문 — 틱 ① 이 repairs 를 적은 뒤 틱 ② 는 그걸 다시 읽어야 회수 경로로 간다.
|
|
195
|
+
card: readTaskCard(CARD_ID, fixture.statePath)!, statePath: fixture.statePath, repo: fixture.remote.checkout,
|
|
196
|
+
pr: PR, head: fixture.head, branch: BRANCH, mustFix: MUST_FIX,
|
|
197
|
+
liveMoves: new Set(['narrow-relaunch']), now, notify,
|
|
198
|
+
modelAvailability: { codexSubscription: false, grokSubscription: false },
|
|
199
|
+
});
|
|
200
|
+
const deps = casDeps(fixture);
|
|
201
|
+
// 틱 ① — 발사. runRepairCycle 이 repairNextMove 판정 뒤 recordJourneyEdge('dispatch') 를 남긴다.
|
|
202
|
+
const launched: RepairLaunchRequest[] = [];
|
|
203
|
+
const first = await runRepairCycle({ ...base(firstTick), request: async (request: RepairLaunchRequest) => { launched.push(request); } });
|
|
204
|
+
const launch = launched[0];
|
|
205
|
+
if (launched.length !== 1 || launch === undefined) {
|
|
206
|
+
throw new Error(`fault-nextmove-dispatch: 발사 틱이 수리 요청을 ${launched.length}건 냈다(기대 1) · decision=${first.decision} · reason=${first.reason}`);
|
|
207
|
+
}
|
|
208
|
+
// 수리 worker 가 끝 JSON ⊕ artifact 를 남겼다(생산 회수 경로가 읽는 꼴 그대로).
|
|
209
|
+
const result = { pr: PR, baseHead: fixture.head, runId: launch.runId, commit: fixture.commit, bundleSha256: fixture.bundleSha256 };
|
|
210
|
+
writeFileSync(join(fixture.artifactDir, 'result.json'), JSON.stringify(result));
|
|
211
|
+
writeFileSync(launch.resultPath, JSON.stringify({
|
|
212
|
+
pr: PR, head: fixture.head, runId: launch.runId, ok: true, job: JOB,
|
|
213
|
+
artifactDir: fixture.artifactDir, result,
|
|
214
|
+
}));
|
|
215
|
+
// 틱 ② — 결과 회수. 생산 applyRepairBundle 이 exact-head CAS push 에 성공하고
|
|
216
|
+
// PR 머리 확인이 늙은 가짜 gh 머리를 못 따라잡아 unconfirmed 로 돌아온다.
|
|
217
|
+
const relaunched: RepairLaunchRequest[] = [];
|
|
218
|
+
const second = await runRepairCycle({
|
|
219
|
+
...base(secondTick),
|
|
220
|
+
request: async (request: RepairLaunchRequest) => { relaunched.push(request); },
|
|
221
|
+
apply: (request) => applyRepairBundle(request, deps),
|
|
222
|
+
});
|
|
223
|
+
if (relaunched.length !== 0) throw new Error(`fault-nextmove-dispatch: 회수 틱이 다시 발사했다(${relaunched.length}건) · decision=${second.decision}`);
|
|
224
|
+
const stored = readTaskCard(CARD_ID, fixture.statePath);
|
|
225
|
+
const unconfirmed = {
|
|
226
|
+
decision: second.decision,
|
|
227
|
+
status: stored?.repairs?.[0]?.status,
|
|
228
|
+
reason: second.reason,
|
|
229
|
+
};
|
|
230
|
+
const edgeCount = edges.filter((edge) => edge.from === 'next-move' && edge.to === 'dispatch').length;
|
|
231
|
+
const remoteHead = fixture.remote.git(fixture.remote.checkout, ['ls-remote', 'origin', `refs/heads/${BRANCH}`]).split('\t')[0] ?? '';
|
|
232
|
+
const ghCalls = fixture.fakeBins.calls().filter((call) => call.name === 'gh').length;
|
|
233
|
+
const receipt = {
|
|
234
|
+
command: FAULT_NEXTMOVE_DISPATCH_COMMAND,
|
|
235
|
+
injectionId,
|
|
236
|
+
result: `graph-edge-taken(next-move→dispatch)=${edgeCount} · unconfirmed=${unconfirmed.status === 'unconfirmed' ? 1 : 0}`,
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
injectionId,
|
|
240
|
+
edge: { count: edgeCount, record: edges.find((edge) => edge.from === 'next-move' && edge.to === 'dispatch'), decision: first.decision },
|
|
241
|
+
unconfirmed,
|
|
242
|
+
remoteHead,
|
|
243
|
+
repairCommit: fixture.commit,
|
|
244
|
+
ghCalls,
|
|
245
|
+
confirmSleeps: [...fixture.confirmSleeps],
|
|
246
|
+
notified,
|
|
247
|
+
receipt,
|
|
248
|
+
};
|
|
249
|
+
} finally {
|
|
250
|
+
off();
|
|
251
|
+
fixture.cleanup();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** CLI·시험 출력 한 화면 — 영수증(명령 ⊕ injectionId ⊕ 결과)과 두 사건 원문(층 L2). */
|
|
256
|
+
export function renderFaultNextmoveDispatch(observation: FaultNextmoveDispatchObservation): string[] {
|
|
257
|
+
return [
|
|
258
|
+
'fault-nextmove-dispatch · 층 L2 · 생산 runRepairCycle/repairNextMove/applyRepairBundle 직접 호출(GitHub API·네트워크 0)',
|
|
259
|
+
` receipt: command=${observation.receipt.command} ⊕ injectionId=${observation.receipt.injectionId} ⊕ result=${observation.receipt.result}`,
|
|
260
|
+
` ① graph-edge-taken: ${JSON.stringify(observation.edge.record ?? {})}`,
|
|
261
|
+
` ② unconfirmed: decision=${observation.unconfirmed.decision} · status=${observation.unconfirmed.status ?? '-'} · reason=${observation.unconfirmed.reason}`,
|
|
262
|
+
` 원격 PR 가지 머리: ${observation.remoteHead.slice(0, 12)} · 수리 commit ${observation.repairCommit.slice(0, 12)} · push ${observation.remoteHead === observation.repairCommit ? '됨' : '안 됨'}`,
|
|
263
|
+
` 확인 지연 루프 요청(ms): ${observation.confirmSleeps.join(',') || '-'} · 알림 ${observation.notified.length}건(심이 받음)`,
|
|
264
|
+
` 가짜 gh 심 호출: ${observation.ghCalls}회 · 발사 틱 판정: ${observation.edge.decision}`,
|
|
265
|
+
];
|
|
266
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// 결함 주입 심 «Pod 자식 공급자 폴백» ── codex 응답 503(server_is_overloaded) 이 생산 폴백 사다리(FALLBACK_STEPS)를
|
|
2
|
+
// 타고 승인된 zai(glm) 로 이어가고, 503 이 아닌 오류는 폴백 없이 끝나는지를 프로세스 안(S1)에서 재현한다.
|
|
3
|
+
//
|
|
4
|
+
// 🚨 왜 이것이 있나 (POD-CHILD-PROVIDER-FALLBACK · 2026-10-21)
|
|
5
|
+
// 폴백 코드 #29340(e9553897) 은 main 에 착지했지만 E4 증거(10-19 격리 node-b Pod · fake HTTP 503 → GLM)는
|
|
6
|
+
// scratch 장치라 새 초록 규칙의 장치 조건 ①(main 착지 · 자기 시험)을 못 채웠다. 이 심이 그 완료 경계를
|
|
7
|
+
// 상주 시험으로 만든다 — 503 이면(한 번) zai 로 이어감 · 503 아닌 오류 → 폴백 안 함, 두 경우를 가른다.
|
|
8
|
+
//
|
|
9
|
+
// ⛔ 흉내 내지 않는다 — 진짜 `streamLLMWithTools`(Pod 자식이 도는 도구 경로) ⊕ 진짜 재시도 정책
|
|
10
|
+
// (`fetchApiWithRetry` 의 503 streak → `OverloadFailoverError` 전환) ⊕ 진짜 `FALLBACK_STEPS` 사다리를 그대로
|
|
11
|
+
// 부른다. 폴백 대상도 진짜다 — 생산 `PROVIDERS.glm`(zaiCodingPlanAvailable → makeZaiCodingPlanProvider →
|
|
12
|
+
// OpenAI 호환 HTTP)을 바꾸지 않고, Pod 자식이 받는 zai 자격 env(ZAI_POD_SECRET_KEY) 하나만 가짜 값으로 둔다.
|
|
13
|
+
// 주입은 HTTP 경계 하나뿐: codex 쪽은 스크립트된 503/401 · zai 코딩 엔드포인트는 정상 SSE(kubectl·네트워크·Pod 없음).
|
|
14
|
+
// 심이 주는 Pod 사실 하나: codex 자식 Pod 엔 grok 자격이 없다(호스트 grok auth.json 이 섞이지 않게).
|
|
15
|
+
// 관측 = 결과 provider · llm.retry 관측 · llm.router 이벤트 · 영수증(명령 ⊕ injectionId ⊕ 결과) · 층 L1.
|
|
16
|
+
|
|
17
|
+
import { randomUUID } from 'node:crypto';
|
|
18
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
19
|
+
import { tmpdir } from 'node:os';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { _resetKeyCacheForTests } from '../config.js';
|
|
22
|
+
import { debug } from '../debug/log.js';
|
|
23
|
+
import { PROVIDERS, streamLLMWithTools } from '../llm.js';
|
|
24
|
+
import { ZAI_CODING_PLAN_URL } from '../llm/zai-coding-plan.js';
|
|
25
|
+
import { FALLBACK_STEPS, type FallbackStep } from '../oauth/fallback-chain.js';
|
|
26
|
+
import { ZAI_POD_SECRET_KEY } from '../task-orchestrator/surfaces/pod-zai-child.js';
|
|
27
|
+
import { setUserConfigOverlay } from '../user-config.js';
|
|
28
|
+
|
|
29
|
+
/** zai 코딩 엔드포인트(HTTP 경계)가 돌려주는 답 — 폴백이 실제로 zai 응답을 흘렸는지 대조한다. */
|
|
30
|
+
export const POD_CODEX_503_ZAI_ANSWER = '[pod-codex-503] zai OK';
|
|
31
|
+
|
|
32
|
+
/** 이 심의 사다리 층 — event-monkey(L0)가 원장·logs.db 에 줄을 싣는 데 대해, 이 심은 진짜 LLM 폴백 경로를 프로세스 안에서 돈다. */
|
|
33
|
+
export const POD_CODEX_503_LEVEL = 'L1' as const;
|
|
34
|
+
|
|
35
|
+
/** 격리 시험 환경에서 지우는 자격 키 — 폴백 사다리의 다른 칸이 우연히 «사용 가능»해지지 않게 한다(zai 칸만 심이 채운다). */
|
|
36
|
+
const ISOLATED_LLM_ENV_KEYS = [
|
|
37
|
+
'OPENAI_API_KEY', 'XAI_API_KEY', 'GROK_API_KEY', 'GROK_CODE_XAI_API_KEY', 'ANTHROPIC_API_KEY',
|
|
38
|
+
'GEMINI_API_KEY', 'GOOGLE_API_KEY', 'LOCAL_LLM_URL', 'OPENROUTER_API_KEY', 'OPENGATEWAY_API_KEY', 'ZAI_API_KEY',
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
/** 주입할 codex 결함 — 503 server_is_overloaded(폴백 사다리를 탄다) · 401(폴백 자격 없음 → 폴백 없음). */
|
|
42
|
+
export type PodCodex503Fault = 'overload-503' | 'auth-401';
|
|
43
|
+
|
|
44
|
+
export const POD_CODEX_503_FAULT_RESPONSES: Readonly<Record<PodCodex503Fault, { status: number; body: string }>> = {
|
|
45
|
+
'overload-503': { status: 503, body: '{"error":{"message":"server_is_overloaded"}}' },
|
|
46
|
+
'auth-401': { status: 401, body: '{"error":{"message":"invalid_api_key"}}' },
|
|
47
|
+
} as const;
|
|
48
|
+
|
|
49
|
+
export interface PodCodex503Scenario {
|
|
50
|
+
/** 주입할 결함(기본 'overload-503' — 칸의 결함). */
|
|
51
|
+
readonly fault: PodCodex503Fault;
|
|
52
|
+
/** 주입 식별자 — 영수증에 실린다(기본 `inj-<uuid>`). */
|
|
53
|
+
readonly injectionId?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function podCodex503Scenario(overrides: Partial<PodCodex503Scenario> = {}): Required<PodCodex503Scenario> {
|
|
57
|
+
return { fault: 'overload-503', injectionId: `inj-${randomUUID()}`, ...overrides };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** 관측 행 — debug.log 를 가로챈 원본(category ⊕ event ⊕ data). */
|
|
61
|
+
export interface PodCodex503ObservedRow {
|
|
62
|
+
readonly category: string;
|
|
63
|
+
readonly event: string;
|
|
64
|
+
readonly data: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface PodCodex503Observation {
|
|
68
|
+
readonly level: typeof POD_CODEX_503_LEVEL;
|
|
69
|
+
readonly injectionId: string;
|
|
70
|
+
readonly fault: PodCodex503Fault;
|
|
71
|
+
readonly faultStatus: number;
|
|
72
|
+
/** 생산 폴백 사다리 — `FALLBACK_STEPS` 정본 칸들(Pod 자식이 받는 체인과 같은 어휘). */
|
|
73
|
+
readonly chain: readonly FallbackStep[];
|
|
74
|
+
/** 완료 경계 판정 — 503 → 'zai-fallback' · 503 아닌 오류 → 'no-fallback'. */
|
|
75
|
+
readonly result: 'zai-fallback' | 'no-fallback';
|
|
76
|
+
readonly resultProvider: string | null;
|
|
77
|
+
readonly answer: string | null;
|
|
78
|
+
readonly error: string | null;
|
|
79
|
+
readonly glmCalls: number;
|
|
80
|
+
readonly scriptedResponses: number;
|
|
81
|
+
/** llm.retry 관측 — 재시도·전환 판정 원본(retry · switch-provider · abort). */
|
|
82
|
+
readonly retryRows: readonly PodCodex503ObservedRow[];
|
|
83
|
+
/** llm.router 이벤트 — overload-failover · 후보 스캔. */
|
|
84
|
+
readonly events: readonly PodCodex503ObservedRow[];
|
|
85
|
+
/** zai.coding-plan 관측 — 생산 glm(zai 코딩 플랜) 공급자가 실제로 요청을 냈다는 원본. */
|
|
86
|
+
readonly zaiRows: readonly PodCodex503ObservedRow[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** 완료 경계 증거 명령 — 칸 문면이 지정한 이 장치의 재는 명령. */
|
|
90
|
+
export const POD_CODEX_503_EVIDENCE_COMMAND = 'bun test src/ux-sim/fault-pod-codex-503.test.ts';
|
|
91
|
+
|
|
92
|
+
/** 영수증 = 명령 ⊕ injectionId ⊕ 결과. */
|
|
93
|
+
export function podCodex503Receipt(observation: Pick<PodCodex503Observation, 'injectionId' | 'result'>): string {
|
|
94
|
+
return `영수증: ${POD_CODEX_503_EVIDENCE_COMMAND} ⊕ ${observation.injectionId} ⊕ ${observation.result}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** 한 화면 — 층 · injectionId · 결과 · 사다리 · 관측 · 영수증. */
|
|
98
|
+
export function renderPodCodex503(observation: PodCodex503Observation): string[] {
|
|
99
|
+
const outcome = observation.answer !== null
|
|
100
|
+
? ` 결과 provider: ${observation.resultProvider ?? '-'} · 답: ${observation.answer}`
|
|
101
|
+
: ` 결과 provider: ${observation.resultProvider ?? '-'} · 오류: ${observation.error ?? '-'}`;
|
|
102
|
+
return [
|
|
103
|
+
`pod-codex-503 · 층 ${observation.level} · 주입 ${observation.injectionId} · 결함 ${observation.fault} · 결과 ${observation.result}`,
|
|
104
|
+
` 사다리(FALLBACK_STEPS): ${observation.chain.join(' → ')}`,
|
|
105
|
+
` 주입 응답 ${observation.faultStatus} × ${observation.scriptedResponses}회 · glm 호출 ${observation.glmCalls}회`,
|
|
106
|
+
outcome,
|
|
107
|
+
...observation.retryRows.map((row) => ` llm.retry ${row.event} ${JSON.stringify(row.data)}`),
|
|
108
|
+
...observation.events.map((row) => ` llm.router ${row.event} ${JSON.stringify(row.data)}`),
|
|
109
|
+
...observation.zaiRows.map((row) => ` zai.coding-plan ${row.event} ${JSON.stringify(row.data)}`),
|
|
110
|
+
podCodex503Receipt(observation),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** 결함 주입 본체 — 생산 `streamLLMWithTools`(도구 경로 · Pod 자식이 도는 그 경로)를 그대로 부른다. */
|
|
115
|
+
export async function simPodCodex503(scenario: PodCodex503Scenario = podCodex503Scenario()): Promise<PodCodex503Observation> {
|
|
116
|
+
const injectionId = scenario.injectionId ?? `inj-${randomUUID()}`;
|
|
117
|
+
const fault: PodCodex503Fault = scenario.fault;
|
|
118
|
+
const scripted = POD_CODEX_503_FAULT_RESPONSES[fault];
|
|
119
|
+
const chain: readonly FallbackStep[] = [...FALLBACK_STEPS];
|
|
120
|
+
const savedEnv = { ...process.env };
|
|
121
|
+
const savedGrok = PROVIDERS.grok;
|
|
122
|
+
const savedFetch = globalThis.fetch;
|
|
123
|
+
const savedLog = debug.log;
|
|
124
|
+
const home = mkdtempSync(join(tmpdir(), 'fault-pod-codex-503-'));
|
|
125
|
+
const rows: PodCodex503ObservedRow[] = [];
|
|
126
|
+
let glmCalls = 0;
|
|
127
|
+
let scriptedResponses = 0;
|
|
128
|
+
try {
|
|
129
|
+
process.env.HOME = home;
|
|
130
|
+
process.env.XDG_CONFIG_HOME = join(home, '.config');
|
|
131
|
+
process.env.CODEX_HOME = join(home, '.codex');
|
|
132
|
+
// zai 한도 원장·quota 신호(quotaSignalDir)가 운영 ~/.elanous/budget 이 아니라 임시 뿌리로 간다.
|
|
133
|
+
process.env.ELANOUS_STATE_DIR = join(home, 'state');
|
|
134
|
+
for (const key of ISOLATED_LLM_ENV_KEYS) delete process.env[key];
|
|
135
|
+
// 키 캐시 파일(os.homedir() 기준 · HOME 을 안 따른다)을 끄고 이미 기억된 값도 비운다 —
|
|
136
|
+
// 그래야 호스트의 진짜 키가 이 심에 섞이지 않는다.
|
|
137
|
+
process.env.ELANOUS_KEEP_ENV_KEYS = '1';
|
|
138
|
+
_resetKeyCacheForTests();
|
|
139
|
+
// Pod 자식의 zai 자격 = Job 이 Secret 에서 내려 주는 env 하나(zaiPodEnv · ZAI_POD_SECRET_KEY) — 그 꼴 그대로 둔다.
|
|
140
|
+
// 생산 `PROVIDERS.glm`(zaiCodingPlanAvailable → makeZaiCodingPlanProvider → OpenAI 호환 HTTP)은 바꾸지 않는다.
|
|
141
|
+
process.env[ZAI_POD_SECRET_KEY] = 'fake-zai-test-only';
|
|
142
|
+
// codex 자식 Pod 에는 grok 자격이 실리지 않는다(podJobManifest 는 grok 자식에만 grokCredential 을 깐다).
|
|
143
|
+
// grok 자격은 os.homedir() 의 auth.json 이라 HOME 격리로는 못 지운다 — 그 Pod 사실 하나만 심이 준다.
|
|
144
|
+
PROVIDERS.grok = { ...savedGrok!, available: () => false };
|
|
145
|
+
setUserConfigOverlay((config) => ({
|
|
146
|
+
...config,
|
|
147
|
+
llm: { ...config.llm, provider: 'openai-codex', apiKey: 'fake-codex-test-only', fallbackChain: [...FALLBACK_STEPS] },
|
|
148
|
+
}));
|
|
149
|
+
// 주입 = HTTP 경계 하나. codex(그 밖 전부)는 스크립트된 결함, zai 코딩 엔드포인트는 정상 SSE 한 줄.
|
|
150
|
+
globalThis.fetch = Object.assign(
|
|
151
|
+
async (input: string | URL | Request): Promise<Response> => {
|
|
152
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
153
|
+
if (url === ZAI_CODING_PLAN_URL) {
|
|
154
|
+
glmCalls += 1;
|
|
155
|
+
const sse = `data: ${JSON.stringify({ choices: [{ delta: { content: POD_CODEX_503_ZAI_ANSWER } }] })}\n\n`
|
|
156
|
+
+ 'data: {"choices":[],"usage":{"prompt_tokens":3,"completion_tokens":1}}\n\ndata: [DONE]\n\n';
|
|
157
|
+
return new Response(sse, { status: 200, headers: { 'content-type': 'text/event-stream' } });
|
|
158
|
+
}
|
|
159
|
+
scriptedResponses += 1;
|
|
160
|
+
return new Response(scripted.body, { status: scripted.status });
|
|
161
|
+
},
|
|
162
|
+
{ preconnect: (savedFetch as unknown as { preconnect?: unknown }).preconnect },
|
|
163
|
+
) as typeof fetch;
|
|
164
|
+
debug.log = ((category: string, event: string, data: Record<string, unknown>): void => {
|
|
165
|
+
rows.push({ category, event, data });
|
|
166
|
+
}) as typeof debug.log;
|
|
167
|
+
let answer: string | null = null;
|
|
168
|
+
let error: string | null = null;
|
|
169
|
+
try {
|
|
170
|
+
answer = await streamLLMWithTools(
|
|
171
|
+
[{ role: 'user', content: `pod-codex-503 ${injectionId}: go` }],
|
|
172
|
+
{ onText: () => {}, dispatchTool: async () => ({ ok: true }) },
|
|
173
|
+
{ tools: [{ name: 'pod_codex_503_probe', description: 'pod-codex-503 probe', parameters: {} }], maxTurns: 1 },
|
|
174
|
+
);
|
|
175
|
+
} catch (caught) {
|
|
176
|
+
error = caught instanceof Error ? caught.message : String(caught);
|
|
177
|
+
}
|
|
178
|
+
const retryRows = rows.filter((row) => row.category === 'llm.retry');
|
|
179
|
+
const events = rows.filter((row) => row.category === 'llm.router');
|
|
180
|
+
const zaiRows = rows.filter((row) => row.category === 'zai.coding-plan');
|
|
181
|
+
const failover = events.find((row) => row.event === 'overload-failover' && (row.data as { fallbackProvider?: unknown }).fallbackProvider === 'glm');
|
|
182
|
+
const fellBack = failover !== undefined && answer === POD_CODEX_503_ZAI_ANSWER && glmCalls === 1;
|
|
183
|
+
return {
|
|
184
|
+
level: POD_CODEX_503_LEVEL,
|
|
185
|
+
injectionId,
|
|
186
|
+
fault,
|
|
187
|
+
faultStatus: scripted.status,
|
|
188
|
+
chain,
|
|
189
|
+
result: fellBack ? 'zai-fallback' : 'no-fallback',
|
|
190
|
+
resultProvider: fellBack ? 'glm' : null,
|
|
191
|
+
answer: fellBack ? answer : null,
|
|
192
|
+
error: fellBack ? null : error,
|
|
193
|
+
glmCalls,
|
|
194
|
+
scriptedResponses,
|
|
195
|
+
retryRows,
|
|
196
|
+
events,
|
|
197
|
+
zaiRows,
|
|
198
|
+
};
|
|
199
|
+
} finally {
|
|
200
|
+
debug.log = savedLog;
|
|
201
|
+
globalThis.fetch = savedFetch;
|
|
202
|
+
PROVIDERS.grok = savedGrok!;
|
|
203
|
+
setUserConfigOverlay(null);
|
|
204
|
+
for (const key of Object.keys(process.env)) {
|
|
205
|
+
if (!(key in savedEnv)) delete process.env[key];
|
|
206
|
+
}
|
|
207
|
+
Object.assign(process.env, savedEnv);
|
|
208
|
+
_resetKeyCacheForTests();
|
|
209
|
+
rmSync(home, { recursive: true, force: true });
|
|
210
|
+
}
|
|
211
|
+
}
|