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/cli/tasks-cli.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync } from 'node:fs';
|
|
1
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
3
|
import { execFileSync, spawnSync } from 'node:child_process';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
4
5
|
import { loadRunLedger as loadRunLedgerSync, loadRunLedgerWithMetadata, runLedgerDir, resolveFederatedRunLedgerDirectories } from '../self-implement/run-ledger.js';
|
|
5
6
|
import { goalRunDbPath, loadGoalRunQuery } from '../self-implement/goal-run-store.js';
|
|
6
7
|
import { loadGoalAskRecords } from '../self-implement/goal-ask-store.js';
|
|
@@ -14,14 +15,16 @@ import { assignedVersions, releasedVersion, validateVersion } from '../release-l
|
|
|
14
15
|
import { compareVersions } from '../directives/version-at.js';
|
|
15
16
|
import { cardsBoard, countBoardTasks, INTERNAL_PACK_PROJECT, mergeBoards, releasePackBoard, type BoardNode } from '../task-agent/board.js';
|
|
16
17
|
import type { Task } from '../task-orchestrator/types.js';
|
|
17
|
-
import { cardPrNumber, CLOSED_BY_HAND_EVENT, closeTaskCard, COMPLETION_KINDS,
|
|
18
|
+
import { boundPrTerminal, cardPrNumber, CLOSED_BY_HAND_EVENT, closeTaskCard, COMPLETION_KINDS, HAND_MOVE_HISTORY_EVENT, updateTaskCard, LIVE_MOVE_HISTORY_EVENT, LIVE_MOVE_RESULT_EVENT, nextMoveFor, resolveHandText, readTaskAgentState, readTaskCard, runTagChange, taskAgentStatePath as taskStatePathDefault, taskCardLabelContext, shellQuote, TASK_CARD_PREFIX, TASK_SEATS, type CompletionKind, type TaskCard, type TaskCardEvent, type TaskLaunchContext, type TaskLaunchReceipt, type TaskLauncher, type TaskSeat } from '../task-agent/task-hand.js';
|
|
18
19
|
import { RUN_TAG_KEYS, runIdentityFieldText, runPriorityClass } from '../task-agent/run-identity.js';
|
|
19
20
|
import { readCardSalvageBranch, recordWiringLiveVerified, refreshCardRunBinding, type CardRunEvidenceDeps } from '../task-agent/card-evidence.js';
|
|
20
21
|
import { captureReviewResults } from '../task-agent/review-result-capture.js';
|
|
21
22
|
import { replayRemoteCardMoves } from '../task-agent/shadow.js';
|
|
22
23
|
import { remoteLedgerMirrorDirs } from '../task-agent/parent-host.js';
|
|
24
|
+
import { buildWorkOrder } from '../task-agent/work-order-build.js';
|
|
23
25
|
import { ambiguousGreenSweepPrs, decideGreenSweep, greenSweepCandidates, observeGreenSweep, type GreenSweepPr } from '../task-agent/green-sweep.js';
|
|
24
26
|
import { HAND_MOVE_KINDS, recordHandMove } from '../task-agent/live-move-history.js';
|
|
27
|
+
import { handTaskWithTierSplit, type TierSizedDecompose } from '../task-agent/tier-split.js';
|
|
25
28
|
import { advanceMission, handMission, MissionAdvanceError, openMissionIds, recordPieceRef, type AdvanceMissionResult, type MissionDecompose, type PieceEvidenceReader } from '../task-agent/mission.js';
|
|
26
29
|
import { formatSevenVerbLive, formatTaskAgentCover, measureSevenVerbLive, measureTaskAgentCover, type CoverRow, type ImplementCardRunBinding, type ImplementRunMergeEvent, type SevenVerbLive, type TaskAgentCoverInput } from '../task-agent/cover.js';
|
|
27
30
|
import { LogStore, STORE_SAFETY_MAX, type LogQuery, type LogStoreRow } from '../mss/logging/log-store.js';
|
|
@@ -49,6 +52,8 @@ export interface TasksCliDeps {
|
|
|
49
52
|
registerSink?: (surface: string) => Promise<unknown>;
|
|
50
53
|
/** `task hand --mission` 의 분해기(시험 주입). 기본 = 나열형은 결정론 · 아니면 `decomposeSelfDevGoal`. */
|
|
51
54
|
missionDecompose?: MissionDecompose;
|
|
55
|
+
/** TIER-SPLIT-BEFORE-LAUNCH — `tasks hand --tier 상|특 --live` 의 분해기(시험 주입). 키가 없으면 `DEFAULT_TIER_SIZED_DECOMPOSE`. */
|
|
56
|
+
tierSizedDecompose?: TierSizedDecompose;
|
|
52
57
|
/** `task advance` 의 착지 근거 읽기(시험 주입). 기본 = `predecessorState`(gh · 런 원장). */
|
|
53
58
|
pieceEvidence?: PieceEvidenceReader;
|
|
54
59
|
/** `task board` 의 내부 팩 어댑터(시험 주입). 기본 = 현재 판(`checklistDevVersion()`)의 `releasePackBoard` — 읽기만. */
|
|
@@ -57,6 +62,8 @@ export interface TasksCliDeps {
|
|
|
57
62
|
releaseVersions?: () => string[];
|
|
58
63
|
/** Isolated checklist read for PR adoption. */
|
|
59
64
|
adoptChecklist?: typeof listChecklist;
|
|
65
|
+
/** Isolated checklist read for work-order build. */
|
|
66
|
+
workOrderChecklist?: typeof listChecklist;
|
|
60
67
|
/** `tasks adopt-pr` live PR read seam; default is gh in this repository. */
|
|
61
68
|
adoptPrView?: (number: number, cwd: string) => import('../task-agent/adopt-pr.js').AdoptPrView;
|
|
62
69
|
/** Isolated ledger proof for a launched card being adopted. */
|
|
@@ -85,6 +92,10 @@ export interface TasksCliDeps {
|
|
|
85
92
|
coverImplementRunMerges?: () => ReadonlyMap<string, ImplementRunMergeEvent> | null;
|
|
86
93
|
/** Read test-universe ledgers only when --include-test was requested. */
|
|
87
94
|
coverIncludeTest?: boolean;
|
|
95
|
+
/** `tasks outcomes` 의 «지금» — 상대 기간(`--since 24h`)을 푸는 기준(시험 주입). 기본 = `Date.now()`. */
|
|
96
|
+
outcomesNow?: () => number;
|
|
97
|
+
/** `tasks outcomes` 페이지 상한(시험 주입). 기본 = `OUTCOMES_QUERY_LIMIT`. */
|
|
98
|
+
outcomesLimit?: number;
|
|
88
99
|
/** TA-REJUDGE-ON-HEAD — `tasks rejudge` 의 판단 의존(시험 주입 · 기본 = 설정 liveMoves ⊕ 실물 gh·리뷰·재게이트·land). */
|
|
89
100
|
rejudge?: Partial<import('../task-agent/rejudge-on-head.js').RejudgeDeps>;
|
|
90
101
|
/** TA-REJUDGE-ON-HEAD — `tasks regate-run` 의 재게이트(시험 주입 · 기본 `runHostRegate`). */
|
|
@@ -163,10 +174,16 @@ export interface DefaultTaskLauncherDeps {
|
|
|
163
174
|
/** HQ 판(시험 주입). */
|
|
164
175
|
localVersion?: string;
|
|
165
176
|
/** HQ-owned, refresh-less Codex access mirror to install before a remote parent launch. */
|
|
166
|
-
codexAccessMirror?: () => Promise<{ elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number } | null>;
|
|
177
|
+
codexAccessMirror?: () => Promise<{ elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number; mirrors?: Array<{ elanousAuth: string; codexAuth: string; account: string; usedPercent?: number; thresholdPercent: number; expiresAt: number }> } | null>;
|
|
178
|
+
/** HQ-owned Grok subscription access mirror; resolved before the first remote SSH call. */
|
|
179
|
+
grokAccessMirror?: () => import('../task-agent/parent-host.js').OwnerGrokAccessMirror;
|
|
180
|
+
/** Clock used to recheck mirror freshness immediately before installation. */
|
|
181
|
+
now?: () => number;
|
|
167
182
|
/** Isolated integration seam; production still reads the HQ rotation snapshot and config directly. */
|
|
168
183
|
ownerCodexRotation?: () => ReturnType<typeof import('../oauth/codex-account-store.js').inspectCodexRotation>;
|
|
169
184
|
ownerCodexRotationConfig?: { accountOrder?: readonly string[]; thresholdPercentByAccount?: Readonly<Record<string, unknown>> };
|
|
185
|
+
/** The HQ owner fence is checked before any token refresh. */
|
|
186
|
+
ownerCodexLeaseHolder?: () => boolean;
|
|
170
187
|
/** 원격 → 로컬 되돌림 알림(시험 주입). 기본 = stderr 한 줄. */
|
|
171
188
|
notice?: (line: string) => void;
|
|
172
189
|
}
|
|
@@ -187,13 +204,17 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
187
204
|
const multi = Array.isArray(configured);
|
|
188
205
|
const targets = configured === null ? [] : parentHostModule.resolveParentHosts(configured, deps.parentHost === undefined ? process.env : { ...process.env, ELANOUS_TA_PARENT_HOST: undefined });
|
|
189
206
|
if (!targets.length) return null;
|
|
207
|
+
const providerFromArgs = args.find((arg) => arg.startsWith('--child-llm-provider='))?.slice('--child-llm-provider='.length)
|
|
208
|
+
?? (args.includes('--child-llm-provider') ? args[args.indexOf('--child-llm-provider') + 1] : undefined);
|
|
209
|
+
const effectiveChildProvider = context.effectiveChildProvider ?? providerFromArgs;
|
|
190
210
|
const notice = deps.notice ?? ((line: string) => { try { process.stderr.write(`${line}\n`); } catch { /* ignore */ } });
|
|
191
211
|
const failed = (target: typeof targets[number], gaps: string[], facts: Record<string, string> = {}): void => {
|
|
192
212
|
try { debug.log('task-agent', 'parent-host-fallback', { host: target.host, runId: context.runId, gaps, facts }); } catch { /* fail-soft */ }
|
|
193
213
|
notice(`[parent-host] ${target.host} 로 못 띄움 — ${multi ? '다음 호스트 또는 로컬 발사로 간다' : '로컬 발사로 간다'}: ${gaps.join(' · ')}`);
|
|
194
214
|
};
|
|
195
|
-
|
|
196
|
-
|
|
215
|
+
type OwnerMirror = { elanousAuth: string; codexAuth: string; account?: string; usedPercent?: number; thresholdPercent?: number; mirrors?: Array<{ elanousAuth: string; codexAuth: string; account: string; usedPercent?: number; thresholdPercent: number; expiresAt: number }> };
|
|
216
|
+
let accessMirror: OwnerMirror | null | undefined;
|
|
217
|
+
const getAccessMirror = async (): Promise<OwnerMirror | null> => {
|
|
197
218
|
if (accessMirror !== undefined) return accessMirror;
|
|
198
219
|
if (deps.codexAccessMirror) {
|
|
199
220
|
accessMirror = await deps.codexAccessMirror();
|
|
@@ -212,6 +233,10 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
212
233
|
const config = getUserConfig();
|
|
213
234
|
const ownerConfig = deps.ownerCodexRotationConfig;
|
|
214
235
|
const candidates = [...rotation.candidates];
|
|
236
|
+
// No local credential preserves the established local-launch fallback.
|
|
237
|
+
if (candidates.length === 0) { accessMirror = null; return null; }
|
|
238
|
+
const ownerLeaseHeld = deps.ownerCodexLeaseHolder?.() ?? hq.hqFenceDecision('ledger-cli').run;
|
|
239
|
+
if (!ownerLeaseHeld) throw new NoEligibleOwnerCodexAccountError('HQ Codex 토큰 주인 임대가 없어 원격 미러 발사를 거부한다');
|
|
215
240
|
const eligible = planOwnerCodexMirrorCandidates(candidates, {
|
|
216
241
|
accountOrder: ownerConfig?.accountOrder ?? config.llm?.codexAccountOrder ?? [],
|
|
217
242
|
thresholdPercentByAccount: ownerConfig?.thresholdPercentByAccount ?? config.llm?.codexAccountRotationThresholdPercentByAccount,
|
|
@@ -220,22 +245,44 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
220
245
|
const prerefreshDeps = {
|
|
221
246
|
credentials: (account: string) => pod.hostCredentials(account, authStore.authStorePath(), () => '', { requireExplicitChatgptAuthMode: true }),
|
|
222
247
|
refresh: (account: string) => codex.refreshCodexAccountHome(account),
|
|
223
|
-
isLeaseHolder: () => hq.hqFenceDecision('ledger-cli').run,
|
|
248
|
+
isLeaseHolder: () => deps.ownerCodexLeaseHolder?.() ?? hq.hqFenceDecision('ledger-cli').run,
|
|
224
249
|
};
|
|
225
|
-
|
|
226
|
-
|
|
250
|
+
const mirrors: NonNullable<OwnerMirror['mirrors']> = [];
|
|
251
|
+
for (const [index, candidate] of eligible.entries()) {
|
|
252
|
+
const usedPercent = candidate.usedPercent;
|
|
253
|
+
const thresholdPercent = podAccountThresholdPercent(candidate.name, {
|
|
254
|
+
thresholdPercentByAccount: ownerConfig?.thresholdPercentByAccount ?? config.llm?.codexAccountRotationThresholdPercentByAccount,
|
|
255
|
+
});
|
|
256
|
+
// HQ is the sole refresh owner. Send every usable account as an access-only snapshot
|
|
257
|
+
// so the remote Pod broker can rotate instead of pinning all jobs to one account.
|
|
227
258
|
let credential: Awaited<ReturnType<typeof pod.podCodexCredentialWithPrerefresh>> = null;
|
|
228
259
|
try { credential = await pod.podCodexCredentialWithPrerefresh(candidate.name, prerefreshDeps); }
|
|
229
|
-
catch {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
260
|
+
catch {
|
|
261
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-account-skipped', { account: candidate.name, reason: 'credential-error' }); } catch { /* fail-soft */ }
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (!credential) {
|
|
265
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-account-skipped', { account: candidate.name, reason: 'expiring-or-refresh-failed' }); } catch { /* fail-soft */ }
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const expiresAt = (JSON.parse(credential.elanousAuth) as { providers?: { 'openai-codex'?: { tokens?: { expiresAt?: unknown } } } }).providers?.['openai-codex']?.tokens?.expiresAt;
|
|
269
|
+
if (typeof expiresAt !== 'number' || !Number.isFinite(expiresAt) || expiresAt <= (deps.now?.() ?? Date.now()) + 3 * 60 * 60 * 1000) {
|
|
270
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-account-skipped', { account: candidate.name, reason: 'access-expiring' }); } catch { /* fail-soft */ }
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
mirrors.push({ elanousAuth: credential.elanousAuth, codexAuth: credential.codexAuth, account: candidate.name,
|
|
274
|
+
expiresAt,
|
|
275
|
+
...(usedPercent !== undefined ? { usedPercent } : {}), thresholdPercent });
|
|
276
|
+
// The receiving marker parser accepts at most 16 distinct accounts.
|
|
277
|
+
// Apply the same bound before writing credentials on the remote parent.
|
|
278
|
+
if (mirrors.length === 16) {
|
|
279
|
+
for (const skipped of eligible.slice(index + 1)) {
|
|
280
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-account-skipped', { account: skipped.name, reason: 'snapshot-limit-16' }); } catch { /* fail-soft */ }
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
237
284
|
}
|
|
238
|
-
accessMirror = null;
|
|
285
|
+
accessMirror = mirrors.length ? { ...mirrors[0]!, mirrors } : null;
|
|
239
286
|
return accessMirror;
|
|
240
287
|
};
|
|
241
288
|
if (cwd) {
|
|
@@ -248,6 +295,11 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
248
295
|
// 그 앞의 readParentHostCapacity 도 ssh). 가드를 아래로 내리면 hold 경로에서 시험이 실 ssh 를 쏜다(R7 사고 모양).
|
|
249
296
|
// hold 경로를 재는 시험은 deps.ssh 가짜 또는 parentHost:null 을 주입한다(real-launch-guard.test 가 이 순서를 문다).
|
|
250
297
|
if (!deps.ssh) (await import('../task-agent/real-launch-guard.js')).refuseRealLaunchUnderTest('remote-parent-ssh', targets.map((target) => target.host).join(','));
|
|
298
|
+
// Grok access is selected/refreshed on HQ before preflight performs any SSH call. A missing or stale
|
|
299
|
+
// subscription must fail closed without touching the remote host or falling back to a local launch.
|
|
300
|
+
const grokAccessMirror = effectiveChildProvider === 'grok'
|
|
301
|
+
? (deps.grokAccessMirror?.() ?? parentHostModule.resolveOwnerGrokAccessMirror())
|
|
302
|
+
: undefined;
|
|
251
303
|
let launchHoldActive = false;
|
|
252
304
|
try {
|
|
253
305
|
if (deps.launchHoldActive) launchHoldActive = deps.launchHoldActive();
|
|
@@ -264,6 +316,8 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
264
316
|
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT;
|
|
265
317
|
delete remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT;
|
|
266
318
|
delete remoteEnv.ELANOUS_REMOTE_CODEX_THRESHOLD_PERCENT;
|
|
319
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNTS;
|
|
320
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCESS_ONLY;
|
|
267
321
|
if (podGoal) for (const key of ['ELANOUS_POD_MEMORY_TIER', 'ELANOUS_POD_MEMORY', 'ELANOUS_POD_MEMORY_HIGH', 'ELANOUS_POD_MEMORY_LITE', 'ELANOUS_POD_GOAL_TYPE'] as const) {
|
|
268
322
|
const value = context.env[key] ?? process.env[key];
|
|
269
323
|
if (value !== undefined) remoteEnv[key] = value;
|
|
@@ -300,30 +354,63 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
300
354
|
if (preflight.warnings.length) notice(`⚠ ${target.host} 자격: ${preflight.warnings.join(' · ')}`);
|
|
301
355
|
try {
|
|
302
356
|
if (parentHostModule.shouldInstallRemoteCodexAccess(context.effectiveChildProvider)) {
|
|
303
|
-
let mirror:
|
|
357
|
+
let mirror: OwnerMirror | null = null;
|
|
304
358
|
let mirrorReason = 'credential-source-empty';
|
|
305
359
|
try { mirror = await getAccessMirror(); }
|
|
306
360
|
catch (error) {
|
|
307
361
|
if (error instanceof NoEligibleOwnerCodexAccountError) throw error;
|
|
308
362
|
mirrorReason = 'credential-source-error';
|
|
309
363
|
}
|
|
310
|
-
|
|
364
|
+
// The receiver accepts at most 16 accounts. Use this same bounded
|
|
365
|
+
// snapshot for installation, the launch marker, and the selected account,
|
|
366
|
+
// including mirrors supplied by the injected credential source.
|
|
367
|
+
const mirrors = mirror?.mirrors?.slice(0, 16);
|
|
368
|
+
const selected = mirrors?.[0] ?? mirror;
|
|
369
|
+
if (mirror) {
|
|
370
|
+
// Snapshot construction can outlive the HQ owner lease. Fresh tokens
|
|
371
|
+
// bypass prerefresh's lock, so recheck before any credential leaves HQ.
|
|
372
|
+
if (!(deps.ownerCodexLeaseHolder?.() ?? (await import('../hq/hq.js')).hqFenceDecision('ledger-cli').run)) {
|
|
373
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-owner-lease-lost', { host: target.host, runId: context.runId, reason: 'owner-lease-lost-before-install' }); } catch { /* fail-soft */ }
|
|
374
|
+
throw new NoEligibleOwnerCodexAccountError('HQ Codex 토큰 주인 임대가 설치 직전에 사라져 원격 미러 발사를 거부한다');
|
|
375
|
+
}
|
|
376
|
+
if (mirror.mirrors && mirror.mirrors.length > 16) {
|
|
377
|
+
for (const skipped of mirror.mirrors.slice(16)) {
|
|
378
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-account-skipped', { account: skipped.account, reason: 'snapshot-limit-16' }); } catch { /* fail-soft */ }
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// Each detached parent keeps its own auth store and Codex homes for
|
|
382
|
+
// its full lifetime, including the legacy single-account source.
|
|
383
|
+
const identity = createHash('sha256').update(`${context.runId}\0${context.launchId}`).digest('hex').slice(0, 20);
|
|
384
|
+
const xdgRoot = `${target.configDir ?? '$HOME/.elanous'}/remote-parent-credentials/${identity}`;
|
|
385
|
+
const mirrorDir = `${xdgRoot}/elanous`;
|
|
386
|
+
const installed = mirrors ?? [{ ...mirror, account: mirror.account ?? 'default' }];
|
|
387
|
+
parentHostModule.installRemoteCodexAccessBatch({ ...target, configDir: mirrorDir }, installed, deps.ssh);
|
|
388
|
+
remoteEnv.XDG_CONFIG_HOME = xdgRoot;
|
|
389
|
+
remoteEnv.CODEX_HOME = `${mirrorDir}/codex-default`;
|
|
390
|
+
// XDG isolation is for Codex credentials only. gh otherwise loses
|
|
391
|
+
// the remote host's existing login before a Pod can be created.
|
|
392
|
+
remoteEnv.GH_CONFIG_DIR = '$HOME/.config/gh';
|
|
393
|
+
}
|
|
311
394
|
else {
|
|
312
395
|
try { debug.log('task-agent.parent-host', 'codex-access-mirror-unavailable', { host: target.host, runId: context.runId, reason: mirrorReason }); } catch { /* fail-soft */ }
|
|
313
396
|
failed(target, ['codex-access-mirror-unavailable']);
|
|
314
397
|
return null;
|
|
315
398
|
}
|
|
316
|
-
if (
|
|
317
|
-
remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT =
|
|
318
|
-
remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT =
|
|
319
|
-
if (
|
|
399
|
+
if (selected?.account) {
|
|
400
|
+
remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT = selected.account;
|
|
401
|
+
remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT = selected.usedPercent === undefined ? 'unknown' : String(selected.usedPercent);
|
|
402
|
+
if (selected.thresholdPercent !== undefined) remoteEnv.ELANOUS_REMOTE_CODEX_THRESHOLD_PERCENT = String(selected.thresholdPercent);
|
|
320
403
|
}
|
|
404
|
+
if (mirrors) remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNTS = JSON.stringify(mirrors.map(({ account, usedPercent, thresholdPercent, expiresAt }) => ({ account, usedPercent: usedPercent ?? null, thresholdPercent, expiresAt })));
|
|
405
|
+
remoteEnv.ELANOUS_REMOTE_CODEX_ACCESS_ONLY = '1';
|
|
321
406
|
}
|
|
322
|
-
const launched = parentHostModule.launchRemoteParent(target, args, remoteEnv, deps.ssh
|
|
407
|
+
const launched = parentHostModule.launchRemoteParent(target, args, remoteEnv, deps.ssh,
|
|
408
|
+
grokAccessMirror ? () => grokAccessMirror : undefined, effectiveChildProvider, deps.now);
|
|
323
409
|
try { debug.log('task-agent', 'parent-host-launched', { host: target.host, runId: context.runId, pid: launched.pid, log: launched.log }); } catch { /* fail-soft */ }
|
|
324
410
|
return { runId: context.runId, parentHost: { host: target.host, ...(target.configDir ? { configDir: target.configDir } : {}), pid: launched.pid, log: launched.log } };
|
|
325
411
|
} catch (error) {
|
|
326
412
|
if (error instanceof parentHostModule.RemoteParentNotLaunchedError) { failed(target, [error.message]); continue; }
|
|
413
|
+
if (error instanceof NoEligibleOwnerCodexAccountError) throw error;
|
|
327
414
|
try { debug.log('task-agent', 'parent-host-launch-uncertain', { host: target.host, runId: context.runId, error: error instanceof Error ? error.message : String(error) }); } catch { /* fail-soft */ }
|
|
328
415
|
throw error;
|
|
329
416
|
}
|
|
@@ -344,6 +431,7 @@ function firstStderrLine(path: string): string {
|
|
|
344
431
|
}
|
|
345
432
|
|
|
346
433
|
export async function defaultTaskLauncher(args: string[], cwd?: string, context?: TaskLaunchContext, deps: DefaultTaskLauncherDeps = {}): Promise<void | TaskLaunchReceipt> {
|
|
434
|
+
if (context) context = (await import('../harness/launch-utterance-ledger.js')).withHandLaunchPairContext(args, context); // LAUNCH-UTTERANCE-LEDGER hand→say pair env
|
|
347
435
|
if (context) {
|
|
348
436
|
const remote = await tryRemoteParent(args, cwd, context, deps);
|
|
349
437
|
if (remote) return remote;
|
|
@@ -897,6 +985,332 @@ export function readTaskAgentCover(
|
|
|
897
985
|
limitReached: truncated.taskAgentActions || truncated.allLands || moveRead?.limitReached === true || orderRead?.limitReached === true || goalAsksTruncated || goalRunsTruncated, unreadableStores };
|
|
898
986
|
}
|
|
899
987
|
|
|
988
|
+
const OUTCOMES_QUERY_LIMIT = STORE_SAFETY_MAX;
|
|
989
|
+
|
|
990
|
+
/** «끝났다»로 읽는 카드 상태 — 이 밖(handed·launched)은 PR 종결 관측이 있어야 끝난 것으로 센다. */
|
|
991
|
+
const OUTCOME_TERMINAL_STATUSES: ReadonlySet<TaskCard['status']> = new Set(['failed', 'launch-failed', 'landed', 'landed-by-hand', 'done']);
|
|
992
|
+
|
|
993
|
+
/** 카드 원장에서 «종결»로 읽는 사건 — 이 줄의 시각만 종료 시각으로 쓴다(run-bound · launch 같은 끝나기 전 사건은 종료 시각이 아니다). */
|
|
994
|
+
const OUTCOME_TERMINAL_HISTORY_EVENTS: ReadonlySet<string> = new Set([
|
|
995
|
+
'failed', 'launch-failed', 'closed-by-hand', 'landed-via-train', 'postland-card', 'postland',
|
|
996
|
+
]);
|
|
997
|
+
const OUTCOME_SUCCESS_HISTORY_EVENTS: ReadonlySet<string> = new Set(['landed-via-train', 'postland-card', 'postland']);
|
|
998
|
+
|
|
999
|
+
/** `--since`/`--until` 의 상대 기간 — `24h` · `90m` · `3d`. */
|
|
1000
|
+
const OUTCOMES_RELATIVE_WINDOW = /^\d+(?:\.\d+)?(?:m|h|d)$/;
|
|
1001
|
+
|
|
1002
|
+
/** `--since`/`--until` — ISO 시각 또는 상대 기간. 그 밖의 모양은 창을 지어내지 않고 거부한다. */
|
|
1003
|
+
function parseOutcomeTime(value: string | undefined, flag: string, now: number): number | undefined {
|
|
1004
|
+
if (value === undefined) return undefined;
|
|
1005
|
+
const text = value.trim();
|
|
1006
|
+
if (OUTCOMES_RELATIVE_WINDOW.test(text)) {
|
|
1007
|
+
const amount = Number(text.slice(0, -1));
|
|
1008
|
+
const unit = text.slice(-1);
|
|
1009
|
+
const hours = unit === 'd' ? amount * 24 : unit === 'm' ? amount / 60 : amount;
|
|
1010
|
+
return now - hours * 3_600_000;
|
|
1011
|
+
}
|
|
1012
|
+
const time = Date.parse(text);
|
|
1013
|
+
if (!/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d\d:\d\d)$/.test(text) || !Number.isFinite(time)) {
|
|
1014
|
+
throw new Error(`${flag} 는 ISO 시각 또는 상대 기간(24h·3d)이어야 한다`);
|
|
1015
|
+
}
|
|
1016
|
+
return time;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/** `tasks outcomes` 한 줄 — 카드 하나의 결과. 모르는 칸은 null(지어내지 않는다). */
|
|
1020
|
+
export interface TaskOutcomeRow {
|
|
1021
|
+
/** 칸(체크리스트 id) — 칸 없이 넘긴 카드는 null. */
|
|
1022
|
+
cell: string | null;
|
|
1023
|
+
card: string;
|
|
1024
|
+
runId: string | null;
|
|
1025
|
+
/** 자식(구현) 런 — 카드가 직접 적은 결속만 사용한다. */
|
|
1026
|
+
childRunId: string | null;
|
|
1027
|
+
/** 부모 호스트 원격 이름 — HQ 로컬 발사면 null. */
|
|
1028
|
+
host: string | null;
|
|
1029
|
+
/** 종료 시각 = 카드 원장의 마지막 종결 사건 시각 ⊕ PR 종결 시각 중 늦은 것(ISO). */
|
|
1030
|
+
endedAt: string;
|
|
1031
|
+
/** 원시 카드 상태. board가 PR 종결로 투영한 상태와 구별한다. */
|
|
1032
|
+
cardStatus: TaskCard['status'];
|
|
1033
|
+
/** PR 결속 — 번호 ⊕ 종결 상태(종결을 못 봤으면 state null). */
|
|
1034
|
+
pr: { number: number; state: 'MERGED' | 'CLOSED' | null } | null;
|
|
1035
|
+
/** 종결 사유는 후속 조각까지 미측정. */
|
|
1036
|
+
reason: null;
|
|
1037
|
+
reasonFrom: null;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
export interface TaskOutcomeReport {
|
|
1041
|
+
since: string | null;
|
|
1042
|
+
until: string | null;
|
|
1043
|
+
rows: TaskOutcomeRow[];
|
|
1044
|
+
/** 사유별 집계 — 이 부분 조각에서는 reasons=[], missingReason=cards. */
|
|
1045
|
+
aggregate: { cards: number; reasons: Array<{ reason: string; count: number }>; missingReason: number };
|
|
1046
|
+
/** 조회 상한에 닿아 절단됐나 — 그때 집계는 «이 창 안에서 센 행»만 센다. */
|
|
1047
|
+
limitReached: boolean;
|
|
1048
|
+
/** 절단 사유 — 카드 조회 상한. */
|
|
1049
|
+
stopReason: 'page-limit' | null;
|
|
1050
|
+
/** 자식 원장 관측은 후속 조각에서 연결한다. */
|
|
1051
|
+
childLedgerObserved: false;
|
|
1052
|
+
/** 재결속 검증 전까지 카드 사유도 후속 조각에서 연결한다. */
|
|
1053
|
+
reasonObserved: false;
|
|
1054
|
+
/** 끝났는데 종료 시각을 몰라 창에 넣지 못한 카드 수. */
|
|
1055
|
+
undatedCards: number;
|
|
1056
|
+
/** 아직 끝나지 않은 카드 수(창 대상 아님). */
|
|
1057
|
+
openCards: number;
|
|
1058
|
+
warning?: string;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/** 마지막 실제 종결 사건. 후보·발사·run-bound·관측 줄은 종료 증거가 아니다. */
|
|
1062
|
+
function outcomeTerminalHistoryLine(card: TaskCard): TaskCardEvent | undefined {
|
|
1063
|
+
return (card.history ?? []).filter((item) => OUTCOME_TERMINAL_HISTORY_EVENTS.has(item.event)).at(-1);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* TA 카드·PR 종결 사실을 기간으로 센다(읽기 전용). 창은 «종료 시각»에 걸린다.
|
|
1068
|
+
* 사유는 재결속 증거를 확인할 때까지 미측정으로 드러낸다.
|
|
1069
|
+
*/
|
|
1070
|
+
export function readTaskOutcomes(
|
|
1071
|
+
window: { sinceMs?: number; untilMs?: number } = {},
|
|
1072
|
+
deps: Pick<TasksCliDeps, 'taskStatePath' | 'outcomesLimit'> = {},
|
|
1073
|
+
snapshot?: Record<string, TaskCard>,
|
|
1074
|
+
): Omit<TaskOutcomeReport, 'since' | 'until'> {
|
|
1075
|
+
const statePath = deps.taskStatePath ?? taskStatePathDefault();
|
|
1076
|
+
const cards = snapshot ?? readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {};
|
|
1077
|
+
const limit = deps.outcomesLimit ?? OUTCOMES_QUERY_LIMIT;
|
|
1078
|
+
const candidates: Array<{ card: TaskCard; terminal: TaskCard['prTerminal']; endedAt: string }> = [];
|
|
1079
|
+
let undatedCards = 0;
|
|
1080
|
+
let openCards = 0;
|
|
1081
|
+
for (const card of Object.values(cards)) {
|
|
1082
|
+
if (!card || typeof card.id !== 'string') continue;
|
|
1083
|
+
const terminal = boundPrTerminal(card);
|
|
1084
|
+
// 결과란 «끝난 카드»다 — 종결 상태이거나 PR 이 종결로 관측된 카드. 아직 도는 카드는 창 대상이 아니다(따로 센다).
|
|
1085
|
+
if (!OUTCOME_TERMINAL_STATUSES.has(card.status) && terminal === undefined) { openCards++; continue; }
|
|
1086
|
+
const terminalHistory = outcomeTerminalHistoryLine(card);
|
|
1087
|
+
const successfulStatus = card.status === 'done' || card.status === 'landed' || card.status === 'landed-by-hand';
|
|
1088
|
+
const manualClosure = (card.status === 'done' || card.status === 'landed-by-hand')
|
|
1089
|
+
&& terminalHistory?.event === CLOSED_BY_HAND_EVENT;
|
|
1090
|
+
const failedStatus = card.status === 'failed' || card.status === 'launch-failed';
|
|
1091
|
+
const history = successfulStatus
|
|
1092
|
+
? (OUTCOME_SUCCESS_HISTORY_EVENTS.has(terminalHistory?.event ?? '') || manualClosure ? terminalHistory : undefined)
|
|
1093
|
+
: failedStatus && (terminalHistory?.event === 'failed' || terminalHistory?.event === 'launch-failed')
|
|
1094
|
+
? terminalHistory : undefined;
|
|
1095
|
+
// 종료 시각은 «종결 관측»에서만 온다 — 마지막 종결 사건 줄 ⊕ PR 종결 관측 중 늦은 것.
|
|
1096
|
+
// run-bound 같은 끝나기 전 사건을 종료 시각으로 단정하지 않는다(모르면 undatedCards 로 세고 창에 넣지 않는다).
|
|
1097
|
+
const endedAt = [history?.at, terminal?.at]
|
|
1098
|
+
.filter((at): at is string => typeof at === 'string' && Number.isFinite(Date.parse(at)))
|
|
1099
|
+
.sort((a, b) => Date.parse(b) - Date.parse(a))[0];
|
|
1100
|
+
if (endedAt === undefined) { undatedCards++; continue; }
|
|
1101
|
+
const time = Date.parse(endedAt);
|
|
1102
|
+
if ((window.sinceMs !== undefined && time < window.sinceMs) || (window.untilMs !== undefined && time > window.untilMs)) continue;
|
|
1103
|
+
candidates.push({ card, terminal, endedAt });
|
|
1104
|
+
}
|
|
1105
|
+
candidates.sort((a, b) => Date.parse(b.endedAt) - Date.parse(a.endedAt) || a.card.id.localeCompare(b.card.id));
|
|
1106
|
+
const limitReached = candidates.length > limit;
|
|
1107
|
+
const selected = limitReached ? candidates.slice(0, limit) : candidates;
|
|
1108
|
+
const rows = selected.map(({ card, terminal, endedAt }): TaskOutcomeRow => {
|
|
1109
|
+
// 이 조각은 카드·PR 종결 사실만 관측한다. 재결속 검증 전까지 사유는 확정하지 않는다.
|
|
1110
|
+
const number = cardPrNumber(card);
|
|
1111
|
+
return {
|
|
1112
|
+
cell: card.checklistId ?? null,
|
|
1113
|
+
card: card.id,
|
|
1114
|
+
runId: card.runId ?? null,
|
|
1115
|
+
childRunId: card.runChildId ?? null,
|
|
1116
|
+
host: card.parentHost?.host ?? null,
|
|
1117
|
+
endedAt,
|
|
1118
|
+
cardStatus: card.status,
|
|
1119
|
+
pr: number === undefined ? null : { number, state: terminal?.state ?? null },
|
|
1120
|
+
reason: null,
|
|
1121
|
+
reasonFrom: null,
|
|
1122
|
+
};
|
|
1123
|
+
});
|
|
1124
|
+
const missingReason = rows.length;
|
|
1125
|
+
const warnings = [
|
|
1126
|
+
limitReached ? `카드 조회 상한 ${limit} 도달 — 창 안 ${candidates.length}장 중 ${rows.length}장만 셌다(집계도 이 행들만 센다)` : null,
|
|
1127
|
+
missingReason > 0 ? `종결 사유 미측정 — ${missingReason}장은 재결속 검증 전까지 사유를 모른다` : null,
|
|
1128
|
+
].filter((line): line is string => line !== null);
|
|
1129
|
+
return {
|
|
1130
|
+
rows,
|
|
1131
|
+
aggregate: { cards: rows.length, reasons: [], missingReason },
|
|
1132
|
+
limitReached,
|
|
1133
|
+
stopReason: limitReached ? 'page-limit' : null,
|
|
1134
|
+
childLedgerObserved: false,
|
|
1135
|
+
reasonObserved: false,
|
|
1136
|
+
undatedCards,
|
|
1137
|
+
openCards,
|
|
1138
|
+
...(warnings.length ? { warning: warnings.join(' · ') } : {}),
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/** MODEL-SIZE-OUTCOME-MEASURE — `tasks outcomes --by` 가 아는 집계 축. */
|
|
1143
|
+
export const TASK_OUTCOME_BY_DIMENSIONS = ['model', 'size'] as const;
|
|
1144
|
+
|
|
1145
|
+
/** 못 읽은 값의 이름 — 0 이나 빈 문자열로 지어내지 않는다. */
|
|
1146
|
+
export const TASK_OUTCOME_UNKNOWN = 'unknown';
|
|
1147
|
+
|
|
1148
|
+
/** 카드 하나의 결과 — PR 착지 · 범위 이탈 · 수렴 실패 · 결과 줄 없음. */
|
|
1149
|
+
export type TaskOutcomeModelSizeResult = 'landed' | 'scope-escape' | 'convergence-failure' | 'no-result-line';
|
|
1150
|
+
|
|
1151
|
+
/** 카드 하나의 측정 줄 — 자식 모델 · 등급 · 조각 크기(대상 경로 수 · 바꿀 동작 수) · 결과. */
|
|
1152
|
+
export interface TaskOutcomeModelSizeCard {
|
|
1153
|
+
card: string;
|
|
1154
|
+
/** `provider/model`(카드 childLlm) · 못 읽으면 `unknown`. */
|
|
1155
|
+
model: string;
|
|
1156
|
+
/** 디스패처 난이도(하|중|상|특) · 못 읽으면 `unknown`. */
|
|
1157
|
+
tier: string;
|
|
1158
|
+
size: { targetPaths: number | typeof TASK_OUTCOME_UNKNOWN; behaviors: number | typeof TASK_OUTCOME_UNKNOWN };
|
|
1159
|
+
result: TaskOutcomeModelSizeResult;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
/** 모델×크기 칸 하나 — 성공률 · 표본 수 · unknown 수. */
|
|
1163
|
+
export interface TaskOutcomeModelSizeCell {
|
|
1164
|
+
model: string;
|
|
1165
|
+
/** 크기 칸 이름(`paths=<n>·behaviors=<n>`) · 못 읽은 칸은 `unknown`. */
|
|
1166
|
+
size: string;
|
|
1167
|
+
samples: number;
|
|
1168
|
+
landed: number;
|
|
1169
|
+
/** landed / samples. */
|
|
1170
|
+
successRate: number | null;
|
|
1171
|
+
/** 이 칸에서 한 축이라도 못 읽은 카드 수. */
|
|
1172
|
+
unknown: number;
|
|
1173
|
+
results: Record<TaskOutcomeModelSizeResult, number>;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
export interface TaskOutcomeModelSizeReport {
|
|
1177
|
+
dimensions: readonly ['model', 'size'];
|
|
1178
|
+
cells: TaskOutcomeModelSizeCell[];
|
|
1179
|
+
cards: TaskOutcomeModelSizeCard[];
|
|
1180
|
+
/** 축별 «못 읽음» 수 — 카드 합계가 아니라 축마다 센다(한 카드가 둘을 못 읽을 수 있다). */
|
|
1181
|
+
unknown: { model: number; tier: number; size: number };
|
|
1182
|
+
samples: number;
|
|
1183
|
+
limitReached: boolean;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
const OUTCOME_MODEL_SIZE_RESULTS: readonly TaskOutcomeModelSizeResult[] = ['landed', 'scope-escape', 'convergence-failure', 'no-result-line'];
|
|
1187
|
+
|
|
1188
|
+
/** `--by` 인자 — 지금은 `model,size` 하나뿐이다(순서 무관 · 그 밖은 거부). */
|
|
1189
|
+
function parseOutcomeDimensions(value: string | undefined): readonly ['model', 'size'] | undefined {
|
|
1190
|
+
if (value === undefined) return undefined;
|
|
1191
|
+
const parts = [...new Set(value.split(',').map((part) => part.trim().toLowerCase()).filter(Boolean))];
|
|
1192
|
+
if (parts.length !== TASK_OUTCOME_BY_DIMENSIONS.length || !TASK_OUTCOME_BY_DIMENSIONS.every((dimension) => parts.includes(dimension))) {
|
|
1193
|
+
throw new Error(`--by 는 ${TASK_OUTCOME_BY_DIMENSIONS.join(',')} 다(모델×조각 크기): ${value}`);
|
|
1194
|
+
}
|
|
1195
|
+
return ['model', 'size'];
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/** 카드 문면의 «바꿀 동작 수» — `바꿀` 선언 줄 ⊕ 그 아래 항목. 선언이 없으면 null(0 으로 지어내지 않는다). */
|
|
1199
|
+
function declaredChangeCount(text: string): number | null {
|
|
1200
|
+
let declared = 0;
|
|
1201
|
+
let explicitlyNone = false;
|
|
1202
|
+
let insideChangeList = false;
|
|
1203
|
+
for (const line of text.split(/\r?\n/)) {
|
|
1204
|
+
const trimmed = line.trim();
|
|
1205
|
+
if (/^바꿀(?:\s|:|것|동작)/.test(trimmed)) {
|
|
1206
|
+
const at = trimmed.indexOf(':');
|
|
1207
|
+
const inline = at < 0 ? '' : trimmed.slice(at + 1).trim();
|
|
1208
|
+
if (/^바꿀\s*(?:것|동작)?\s*:?[\s]*(?:없음|없다)$/u.test(trimmed)) {
|
|
1209
|
+
explicitlyNone = true;
|
|
1210
|
+
insideChangeList = false;
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
// «바꿀 것: 하나» 처럼 한 줄에 적었으면 그 줄이 한 동작이고, 목록이 뒤따르지 않는다.
|
|
1214
|
+
// «바꿀 것: 다음» 처럼 목록을 가리키는 선언은 그 줄이 동작이 아니고, 뒤따르는 목록을 센다.
|
|
1215
|
+
insideChangeList = inline.length === 0 || /^다음[.!?]?$/.test(inline);
|
|
1216
|
+
if (!insideChangeList) declared++;
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1219
|
+
if (!insideChangeList) continue;
|
|
1220
|
+
if (/^[-*·]\s+\S/.test(trimmed)) { declared++; continue; }
|
|
1221
|
+
if (trimmed.length > 0) insideChangeList = false;
|
|
1222
|
+
}
|
|
1223
|
+
return declared > 0 ? declared : explicitlyNone ? 0 : null;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/** 조각 크기 — 대상 경로 수(카드가 적은 목록) ⊕ 바꿀 동작 수(문면의 바꿀 선언). */
|
|
1227
|
+
function outcomeCardSize(card: TaskCard | undefined): TaskOutcomeModelSizeCard['size'] {
|
|
1228
|
+
const targetPaths = Array.isArray(card?.targetPaths) ? card.targetPaths.length : TASK_OUTCOME_UNKNOWN;
|
|
1229
|
+
const behaviors = card && typeof card.text === 'string' ? declaredChangeCount(card.text) ?? TASK_OUTCOME_UNKNOWN : TASK_OUTCOME_UNKNOWN;
|
|
1230
|
+
return { targetPaths, behaviors };
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
function outcomeCardModel(card: TaskCard | undefined): string {
|
|
1234
|
+
const llm = card?.childLlm;
|
|
1235
|
+
if (!llm || typeof llm.provider !== 'string' || !llm.provider || typeof llm.model !== 'string' || !llm.model) return TASK_OUTCOME_UNKNOWN;
|
|
1236
|
+
return `${llm.provider}/${llm.model}`;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function outcomeCardTier(card: TaskCard | undefined): string {
|
|
1240
|
+
const tier = card?.tier;
|
|
1241
|
+
return tier === '하' || tier === '중' || tier === '상' || tier === '특' ? tier : TASK_OUTCOME_UNKNOWN;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* 결과 판정 — 카드 원장에 있는 사실만 쓴다(문면 추측 없음).
|
|
1246
|
+
* ① 실제 실행·성공한 손 범위 자르기 hand-move(trim-scope)가 있으면 «범위 이탈» — 실행·성공 값이
|
|
1247
|
+
* 없거나 false인 조정 · post-land partial(남은 작업)만으로는 범위 이탈이 아니다.
|
|
1248
|
+
* ② PR MERGED 종결 증거(row.pr ⊕ 원장 prTerminal) 또는 손 착지 종결 기록(closed-by-hand)이 있으면 «PR 착지» —
|
|
1249
|
+
* 카드 상태(landed·done)만으로는 착지로 단정하지 않는다.
|
|
1250
|
+
* ③ 실패 종결 줄이 있으면 «수렴 실패» ④ 그 밖은 «결과 줄 없음».
|
|
1251
|
+
*/
|
|
1252
|
+
function classifyOutcomeResult(card: TaskCard | undefined, row: TaskOutcomeRow): TaskOutcomeModelSizeResult {
|
|
1253
|
+
if ((card?.history ?? []).some((item) => item.event === HAND_MOVE_HISTORY_EVENT && item.kind === 'trim-scope'
|
|
1254
|
+
&& item.executed === true && item.ok === true)) return 'scope-escape';
|
|
1255
|
+
const terminal = card ? boundPrTerminal(card) : undefined;
|
|
1256
|
+
const landedByHand = row.cardStatus === 'landed-by-hand'
|
|
1257
|
+
&& (card?.history ?? []).some((item) => item.event === CLOSED_BY_HAND_EVENT);
|
|
1258
|
+
if (row.pr?.state === 'MERGED' || terminal?.state === 'MERGED' || landedByHand) return 'landed';
|
|
1259
|
+
const terminalLine = card ? outcomeTerminalHistoryLine(card) : undefined;
|
|
1260
|
+
if (terminalLine?.event === 'failed' || terminalLine?.event === 'launch-failed') return 'convergence-failure';
|
|
1261
|
+
if (row.cardStatus === 'failed' || row.cardStatus === 'launch-failed') return 'convergence-failure';
|
|
1262
|
+
return 'no-result-line';
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* MODEL-SIZE-OUTCOME-MEASURE — `tasks outcomes --by model,size`(읽기 전용).
|
|
1267
|
+
* 창 안에서 «끝난» 카드(readTaskOutcomes 와 같은 판정)를 모델×조각 크기 칸으로 묶어 성공률·표본 수·unknown 수를 낸다.
|
|
1268
|
+
* `report` 와 `snapshot` 을 함께 주면 같은 원장 시점으로 창·크기·결과를 센다.
|
|
1269
|
+
*/
|
|
1270
|
+
export function readTaskOutcomeModelSize(
|
|
1271
|
+
window: { sinceMs?: number; untilMs?: number } = {},
|
|
1272
|
+
deps: Pick<TasksCliDeps, 'taskStatePath' | 'outcomesLimit'> = {},
|
|
1273
|
+
report?: Omit<TaskOutcomeReport, 'since' | 'until'>,
|
|
1274
|
+
snapshot?: Record<string, TaskCard>,
|
|
1275
|
+
): TaskOutcomeModelSizeReport {
|
|
1276
|
+
const cards = snapshot ?? readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(deps.taskStatePath ?? taskStatePathDefault()).tasks ?? {};
|
|
1277
|
+
const observed = report ?? readTaskOutcomes(window, deps, cards);
|
|
1278
|
+
const unknown = { model: 0, tier: 0, size: 0 };
|
|
1279
|
+
const cells = new Map<string, TaskOutcomeModelSizeCell>();
|
|
1280
|
+
const rows = observed.rows.map((row): TaskOutcomeModelSizeCard => {
|
|
1281
|
+
const card = cards[row.card];
|
|
1282
|
+
const model = outcomeCardModel(card);
|
|
1283
|
+
const tier = outcomeCardTier(card);
|
|
1284
|
+
const size = outcomeCardSize(card);
|
|
1285
|
+
const result = classifyOutcomeResult(card, row);
|
|
1286
|
+
if (model === TASK_OUTCOME_UNKNOWN) unknown.model++;
|
|
1287
|
+
if (tier === TASK_OUTCOME_UNKNOWN) unknown.tier++;
|
|
1288
|
+
const sizeKey = size.targetPaths === TASK_OUTCOME_UNKNOWN || size.behaviors === TASK_OUTCOME_UNKNOWN
|
|
1289
|
+
? TASK_OUTCOME_UNKNOWN : `paths=${size.targetPaths}·behaviors=${size.behaviors}`;
|
|
1290
|
+
if (sizeKey === TASK_OUTCOME_UNKNOWN) unknown.size++;
|
|
1291
|
+
// Cell unknown belongs to its two grouping axes; tier is reported separately per card and in unknown.tier.
|
|
1292
|
+
const unresolved = model === TASK_OUTCOME_UNKNOWN || sizeKey === TASK_OUTCOME_UNKNOWN;
|
|
1293
|
+
const key = `${model}\u0000${sizeKey}`;
|
|
1294
|
+
const cell = cells.get(key) ?? { model, size: sizeKey, samples: 0, landed: 0, successRate: null, unknown: 0,
|
|
1295
|
+
results: Object.fromEntries(OUTCOME_MODEL_SIZE_RESULTS.map((name) => [name, 0])) as Record<TaskOutcomeModelSizeResult, number> };
|
|
1296
|
+
cell.samples++;
|
|
1297
|
+
if (result === 'landed') cell.landed++;
|
|
1298
|
+
if (unresolved) cell.unknown++;
|
|
1299
|
+
cell.results[result]++;
|
|
1300
|
+
cell.successRate = cell.landed / cell.samples;
|
|
1301
|
+
cells.set(key, cell);
|
|
1302
|
+
return { card: row.card, model, tier, size, result };
|
|
1303
|
+
});
|
|
1304
|
+
return {
|
|
1305
|
+
dimensions: ['model', 'size'],
|
|
1306
|
+
cells: [...cells.values()].sort((a, b) => a.model.localeCompare(b.model) || a.size.localeCompare(b.size)),
|
|
1307
|
+
cards: rows,
|
|
1308
|
+
unknown,
|
|
1309
|
+
samples: rows.length,
|
|
1310
|
+
limitReached: observed.limitReached,
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
|
|
900
1314
|
export function registerTasksCommands(program: Command, deps: TasksCliDeps = {}): void {
|
|
901
1315
|
let activeToken: string | undefined;
|
|
902
1316
|
const output = deps.output ?? console.log;
|
|
@@ -909,6 +1323,38 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
909
1323
|
};
|
|
910
1324
|
const tasks = program.command('tasks').alias('task').description('TOX 태스크 조회 및 승인 · TASK-AGENT 과제 넘기기(hand)');
|
|
911
1325
|
|
|
1326
|
+
tasks.command('work-order').description('TASK-AGENT 작업 지시서')
|
|
1327
|
+
.command('build')
|
|
1328
|
+
.description('체크리스트 칸으로 작업 지시서를 만들어 파일에 쓴다')
|
|
1329
|
+
.requiredOption('--checklist <cellId>', '체크리스트 칸 id')
|
|
1330
|
+
.requiredOption('--version <version>', '체크리스트 판')
|
|
1331
|
+
.requiredOption('--out <path>', '작업 지시서 출력 파일')
|
|
1332
|
+
.action((opts: { checklist: string; version: string; out: string }) => {
|
|
1333
|
+
try {
|
|
1334
|
+
validateVersion(opts.version);
|
|
1335
|
+
const item = (deps.workOrderChecklist ?? listChecklist)(opts.version).items.find((cell) => cell.id === opts.checklist);
|
|
1336
|
+
if (!item) throw new Error(`체크리스트 칸 없음: ${opts.checklist}`);
|
|
1337
|
+
const targets = /^대상 경로:[ \t]*(.*)$/.exec(item.title.split(/\r?\n/, 1)[0]!)?.[1]?.split(' · ').map((path) => path.trim()).filter(Boolean) ?? [];
|
|
1338
|
+
const missing = targets.filter((path) => !existsSync(resolve(process.cwd(), path)));
|
|
1339
|
+
const boundary = [
|
|
1340
|
+
...(targets.length ? [`대상 경로: ${targets.join(' · ')}`] : []),
|
|
1341
|
+
...(missing.length ? [`boundary.missing: ${missing.join(' · ')}`] : []),
|
|
1342
|
+
].join('\n');
|
|
1343
|
+
const order = buildWorkOrder({
|
|
1344
|
+
cellId: item.id,
|
|
1345
|
+
version: opts.version,
|
|
1346
|
+
priority: item.priority,
|
|
1347
|
+
boundary: boundary || undefined,
|
|
1348
|
+
});
|
|
1349
|
+
mkdirSync(dirname(opts.out), { recursive: true });
|
|
1350
|
+
writeFileSync(opts.out, `${JSON.stringify(order, null, 2)}\n`);
|
|
1351
|
+
out(opts.out);
|
|
1352
|
+
} catch (error) {
|
|
1353
|
+
out(error instanceof Error ? error.message : '작업 지시서 작성 실패');
|
|
1354
|
+
process.exitCode = 1;
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
|
|
912
1358
|
tasks.command('green-sweep')
|
|
913
1359
|
.description('병합된 과제 PR 과 칸 근거를 대조해 green/기록만/건너뜀을 미리 본다 (항상 dry-run)')
|
|
914
1360
|
.requiredOption('--version <version>', '조회할 체크리스트 판')
|
|
@@ -923,6 +1369,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
923
1369
|
{ cwd: process.cwd(), encoding: 'utf8', timeout: 20_000 }));
|
|
924
1370
|
const cards = Object.values(readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(deps.taskStatePath ?? taskStatePathDefault()).tasks ?? {});
|
|
925
1371
|
let holds: Set<string> | null = null;
|
|
1372
|
+
let holdDiagnostic: string | undefined;
|
|
926
1373
|
if (opts.traffic) {
|
|
927
1374
|
try {
|
|
928
1375
|
const traffic: unknown = JSON.parse(readFileSync(opts.traffic, 'utf8'));
|
|
@@ -930,8 +1377,13 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
930
1377
|
&& Array.isArray((traffic as { hold?: unknown }).hold)
|
|
931
1378
|
&& (traffic as { hold: unknown[] }).hold.every((id) => typeof id === 'string'))
|
|
932
1379
|
holds = new Set((traffic as { hold: string[] }).hold);
|
|
933
|
-
|
|
934
|
-
|
|
1380
|
+
else holdDiagnostic = `invalid-traffic-shape: ${opts.traffic} must contain hold: string[]`;
|
|
1381
|
+
} catch (error) {
|
|
1382
|
+
const code = error && typeof error === 'object' && 'code' in error && typeof error.code === 'string'
|
|
1383
|
+
? error.code : error instanceof SyntaxError ? 'invalid-json' : 'read-error';
|
|
1384
|
+
holdDiagnostic = `${code}: ${opts.traffic}`;
|
|
1385
|
+
}
|
|
1386
|
+
} else holdDiagnostic = 'traffic-path-not-provided: pass --traffic ~/elanous-hq/seat-state/OP/traffic.json';
|
|
935
1387
|
const prCache = new Map<number, GreenSweepPr | null>();
|
|
936
1388
|
const ambiguousPrs = ambiguousGreenSweepPrs(snapshot.items, opts.version, cards);
|
|
937
1389
|
const origin = run('git', ['remote', 'get-url', 'origin']);
|
|
@@ -981,7 +1433,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
981
1433
|
return check.status === 0 ? true : check.status === 1 ? false : null;
|
|
982
1434
|
})();
|
|
983
1435
|
const decision = decideGreenSweep({ item, candidate, candidateCount: candidates.length,
|
|
984
|
-
pr: landingPr ?? null, ancestor, hold: holds === null ? null : holds.has(item.id), repositoryMatches,
|
|
1436
|
+
pr: landingPr ?? null, ancestor, hold: holds === null ? null : holds.has(item.id), holdDiagnostic, repositoryMatches,
|
|
985
1437
|
ambiguousAcrossCells: ambiguousPrs.has(candidate.pr) });
|
|
986
1438
|
observeGreenSweep(decision);
|
|
987
1439
|
return decision;
|
|
@@ -993,8 +1445,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
993
1445
|
if (opts.json) out(JSON.stringify({ dryRun: true, version: opts.version, counts, decisions }));
|
|
994
1446
|
else {
|
|
995
1447
|
out(`dry-run · ${opts.version} · 후보 ${counts.candidate} · green ${counts.green} · 기록만 ${counts.recordOnly} · 건너뜀 ${counts.skipped}`);
|
|
996
|
-
for (const d of decisions) out(`${d.verdict}\t${d.cell}\t#${d.pr}\t${d.mergeSha ?? '-'}\t${d.reason}\t${d.evidence}\tbefore=${JSON.stringify(d.existingEvidence)}\tafter=${JSON.stringify(d.plannedEvidence)}`);
|
|
997
|
-
if (holds === null) out('⚠ hold 원장을 읽지 못해 green 없이 기록만 판정');
|
|
1448
|
+
for (const d of decisions) out(`${d.verdict}\t${d.cell}\t#${d.pr}\t${d.mergeSha ?? '-'}\t${d.reason}\t${d.evidence}\tbefore=${JSON.stringify(d.existingEvidence)}\tafter=${JSON.stringify(d.plannedEvidence)}\tholdDiagnostic=${d.holdDiagnostic ?? ''}`);
|
|
998
1449
|
}
|
|
999
1450
|
} catch (error) { out(`green-sweep 조회 실패: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
1000
1451
|
});
|
|
@@ -1051,6 +1502,41 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1051
1502
|
} catch (error) { out(error instanceof Error ? error.message : '커버 조회 실패'); process.exitCode = 1; }
|
|
1052
1503
|
});
|
|
1053
1504
|
|
|
1505
|
+
tasks.command('outcomes')
|
|
1506
|
+
.description('TA 카드·PR 종결 결과를 기간으로 센다 — JSON 한 건, 자식 원장 미측정(읽기 전용 · 카드 페이지 상한)')
|
|
1507
|
+
.option('--since <기간>', '시작 시각 — ISO 또는 상대 기간(24h · 3d)')
|
|
1508
|
+
.option('--until <기간>', '끝 시각 — ISO 또는 지금에서 뺀 상대 기간(24h · 3d)')
|
|
1509
|
+
.option('--by <축>', '집계 축 — model,size = 카드마다 자식 모델 · 등급 · 조각 크기(대상 경로 수·바꿀 동작 수) · 결과(PR 착지 · 범위 이탈 · 수렴 실패 · 결과 줄 없음)를 묶어 모델×크기 칸별 성공률 · 표본 수 · unknown 수를 낸다(읽기 전용)')
|
|
1510
|
+
.option('--json', 'JSON 출력(기본값)')
|
|
1511
|
+
.action((opts: { since?: string; until?: string; by?: string; json?: boolean }) => {
|
|
1512
|
+
try {
|
|
1513
|
+
const now = deps.outcomesNow?.() ?? Date.now();
|
|
1514
|
+
const sinceMs = parseOutcomeTime(opts.since, '--since', now);
|
|
1515
|
+
const untilMs = parseOutcomeTime(opts.until, '--until', now) ?? now;
|
|
1516
|
+
// 창이 뒤집혔으면 아무것도 읽지 않는다(«빈 결과»로 속이지 않는다).
|
|
1517
|
+
if (sinceMs !== undefined && untilMs !== undefined && sinceMs > untilMs) throw new Error('--since 가 --until 보다 늦다');
|
|
1518
|
+
// 축 이름이 틀렸으면 원장도 읽지 않는다(지어낸 집계를 내지 않게).
|
|
1519
|
+
const dimensions = parseOutcomeDimensions(opts.by);
|
|
1520
|
+
const snapshot = dimensions
|
|
1521
|
+
? readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(deps.taskStatePath ?? taskStatePathDefault()).tasks ?? {}
|
|
1522
|
+
: undefined;
|
|
1523
|
+
const observed = readTaskOutcomes({ sinceMs, untilMs }, deps, snapshot);
|
|
1524
|
+
const report: TaskOutcomeReport = {
|
|
1525
|
+
since: sinceMs === undefined ? null : new Date(sinceMs).toISOString(),
|
|
1526
|
+
until: untilMs === undefined ? null : new Date(untilMs).toISOString(),
|
|
1527
|
+
...observed,
|
|
1528
|
+
};
|
|
1529
|
+
try { debug.log('task-agent', 'card-outcomes', { since: report.since, until: report.until, rows: report.rows.length,
|
|
1530
|
+
missingReason: report.aggregate.missingReason, stopReason: report.stopReason,
|
|
1531
|
+
childLedgerObserved: false, reasonObserved: false }); } catch { /* fail-soft */ }
|
|
1532
|
+
// `--by model,size` 는 지금 JSON 에 «한 칸»을 더할 뿐 — 없으면 종전 JSON 그대로다.
|
|
1533
|
+
out(JSON.stringify(dimensions ? { ...report, byModelSize: readTaskOutcomeModelSize({ sinceMs, untilMs }, deps, observed, snapshot) } : report));
|
|
1534
|
+
} catch (error) {
|
|
1535
|
+
out(JSON.stringify({ error: error instanceof Error ? error.message : '결과 조회 실패' }));
|
|
1536
|
+
process.exitCode = 1;
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1054
1540
|
tasks.command('list')
|
|
1055
1541
|
.description('우선순위와 생성 시각 순으로 태스크 보기')
|
|
1056
1542
|
.option('--status <s>', '상태로 필터')
|
|
@@ -1227,7 +1713,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1227
1713
|
if (resolved.kind === 'inlined') {
|
|
1228
1714
|
try { debug.log('task-agent.hand', 'goal-file-inlined', { path: resolved.path, chars: resolved.chars, sha256: resolved.sha256 }); } catch { /* fail-soft */ }
|
|
1229
1715
|
}
|
|
1230
|
-
const
|
|
1716
|
+
const handed = await handTaskWithTierSplit({
|
|
1717
|
+
...('tierSizedDecompose' in deps ? { decompose: deps.tierSizedDecompose } : {}),
|
|
1231
1718
|
text: resolved.text,
|
|
1232
1719
|
...(opts.project !== undefined && opts.target !== undefined ? { project: { id: opts.project, target: opts.target } } : {}),
|
|
1233
1720
|
...(opts.goal !== undefined ? { goal: opts.goal } : {}),
|
|
@@ -1236,6 +1723,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1236
1723
|
...(opts.checklist ? { checklistId: opts.checklist } : {}),
|
|
1237
1724
|
...(opts.completion ? { completion: opts.completion } : {}),
|
|
1238
1725
|
live: opts.live === true,
|
|
1726
|
+
preflightGoalDoneBoundary: opts.live === true && deps.taskLauncher === undefined,
|
|
1239
1727
|
...(opts.taLand === true ? { taLand: true } : {}),
|
|
1240
1728
|
...(opts.childLlm !== undefined ? { childLlm: opts.childLlm } : {}),
|
|
1241
1729
|
...(opts.childLlmEffort !== undefined ? { childLlmEffort: opts.childLlmEffort } : {}),
|
|
@@ -1246,8 +1734,29 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1246
1734
|
...(deps.taskCompositionRoot ? { compositionRoot: deps.taskCompositionRoot } : {}),
|
|
1247
1735
|
launcher: deps.taskLauncher ?? defaultTaskLauncher,
|
|
1248
1736
|
});
|
|
1737
|
+
if (handed.kind === 'split') {
|
|
1738
|
+
// TIER-SPLIT-BEFORE-LAUNCH — 상·특 hand 를 조각으로 나눠 쐈다: 첫 줄 = 묶음 · 조각마다 한 줄(미션 출력과 같은 꼴).
|
|
1739
|
+
if (opts.json) out(JSON.stringify(handed));
|
|
1740
|
+
else {
|
|
1741
|
+
// 디스패처 계약(ta-dispatcher.sh · `grep -E '^ta-' | head -1`): 줄 머리 `ta-` 는 «카드 id» 만 — 조각 카드 줄이 먼저, 묶음 줄은 끝에 `tier-split` 머리로.
|
|
1742
|
+
for (const piece of handed.slices) {
|
|
1743
|
+
out([piece.result?.card.id ?? '-', piece.result?.launched ? 'launched' : piece.error ? 'failed' : 'not launched', `tier ${piece.slice.tier} · 파일 ${piece.slice.files} · 행동 ${piece.slice.behaviours}`, headLine(piece.slice.goal)].join('\t'));
|
|
1744
|
+
if (piece.slice.unavoidable) out(` 불가피: ${piece.slice.unavoidable}`);
|
|
1745
|
+
if (piece.error) out(` ${piece.error}`);
|
|
1746
|
+
}
|
|
1747
|
+
out(`tier-split\t${handed.group}\t${handed.fromTier} → 조각 ${handed.slices.length}`);
|
|
1748
|
+
}
|
|
1749
|
+
if (handed.slices.some((piece) => piece.error)) process.exitCode = 1;
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
const result = handed.result;
|
|
1753
|
+
if (handed.kind === 'blocked') process.exitCode = 1;
|
|
1249
1754
|
if (opts.json) out(JSON.stringify(result));
|
|
1250
|
-
else {
|
|
1755
|
+
else if (handed.kind === 'blocked') {
|
|
1756
|
+
// 발사 0 — 디스패처가 «넘김 실패» 로 읽도록 어느 줄도 `ta-` 로 시작하지 않는다.
|
|
1757
|
+
out(`tier-split-failed\t${result.card.id}\tnot launched`);
|
|
1758
|
+
out(`(tier-split-failed — 발사 0 · 카드 failed · ${handed.reason})`);
|
|
1759
|
+
} else {
|
|
1251
1760
|
out(`${result.card.id}\t${result.mode}\t${result.launched ? 'launched' : 'not launched'}`);
|
|
1252
1761
|
if (result.move.command) out(`elanous ${result.move.command.map(shellQuote).join(' ')}`);
|
|
1253
1762
|
else out(result.move.reason);
|