elanous 0.2.32 → 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/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.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/{5525.86debf231e181813.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/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
- 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/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.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/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
- 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/{4174.92ed04922709ac9e.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/3589.5444a06bcf6e775c.js +1 -0
- 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/{9398-6aed28f0a96d0d6f.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/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
- 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/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.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/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
- 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/{5173-233188df2f42c626.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/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
- 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/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
- 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/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
- 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/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.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/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
- 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/8437-8d5492094b166cfa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
- 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/{6092.a7f99e68b188ca66.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/{3278.2e5d15b53a4091c8.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/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.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/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
- 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/{7862.30a8d6482bb238eb.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-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
- 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-26e6c18a1a750cf6.js +1 -0
- 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-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
- 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-04d00ae9b0890349.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/{7a1887c4.f36b88fba31da8fd.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/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
- 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 +10 -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 +5 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/default-loop.yaml +76 -5
- package/graphs/document-loop.yaml +71 -4
- package/graphs/implement-loop.yaml +59 -4
- package/graphs/journey/SCENARIOS.md +33 -0
- package/graphs/journey/recipes.yaml +1 -0
- package/graphs/journey/ta-journey.yaml +94 -0
- package/graphs/journey/units/author/author.yaml +20 -0
- package/graphs/journey/units/author/recipes.yaml +2 -0
- 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/journey/units/green/green.yaml +20 -0
- package/graphs/journey/units/green/recipes.yaml +2 -0
- package/graphs/journey/units/pr/pr.yaml +20 -0
- package/graphs/journey/units/pr/recipes.yaml +2 -0
- package/graphs/journey/units/remember/recipes.yaml +2 -0
- package/graphs/journey/units/remember/remember.yaml +20 -0
- package/graphs/operate-loop.yaml +71 -4
- package/graphs/overlays/stop-heal-ladder.yaml +1 -1
- package/graphs/release-rehearsal/recipes.yaml +1 -1
- package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
- package/graphs/research-loop.yaml +159 -4
- package/graphs/test-diet/test-diet.yaml +3 -0
- package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
- package/graphs/units/dispatch-pod/recipes.yaml +14 -0
- package/graphs/units/entry/entry.yaml +50 -0
- package/graphs/units/entry/recipes.yaml +14 -0
- package/graphs/units/harvest/harvest.yaml +25 -0
- package/graphs/units/harvest/recipes.yaml +4 -0
- package/graphs/units/land/land.yaml +45 -0
- package/graphs/units/land/recipes.yaml +3 -0
- package/graphs/units/recipes.yaml +7 -0
- package/graphs/units/recover.yaml +39 -0
- package/graphs/units/reflect/recipes.yaml +3 -0
- package/graphs/units/reflect/reflect.yaml +15 -0
- package/graphs/units/task-agent-recover-review.yaml +17 -0
- package/graphs/units/task-agent-recover-wait.yaml +17 -0
- package/graphs/units/verbs/make-doc.yaml +34 -0
- package/graphs/units/verbs/recipes.yaml +33 -0
- package/graphs/units/verbs/verify.yaml +55 -0
- package/graphs/work/recipes.yaml +2 -0
- package/graphs/work/research-report.yaml +28 -0
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +69 -16
- package/scripts/coord-role-pack.ts +19 -6
- package/scripts/docs/generate-graph-anatomy.ts +19 -2
- package/scripts/graph-harvest-unit.ts +22 -0
- package/scripts/graph-units/journey-stub.ts +6 -0
- package/scripts/graph-units/land-enqueue.ts +78 -0
- package/scripts/graph-units/recover-plan.ts +15 -0
- package/scripts/graph-units/reflect-node.ts +88 -0
- package/scripts/graph-units/ta-journey-observe.ts +109 -0
- package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
- package/scripts/graph-units/verbs/verify-stage.ts +75 -0
- package/scripts/graph-units/verbs-envelope.ts +139 -0
- package/scripts/hq/standby-snapshot.ts +30 -0
- package/scripts/public-export.ts +43 -1
- package/scripts/ratchets/train-side-invariants.sh +45 -0
- package/scripts/release-loop/auto-approve-node.ts +30 -16
- 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-closure.ts +5 -1
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-node.ts +675 -49
- package/scripts/release-loop/gate-partial.ts +68 -14
- package/scripts/release-loop/gate-radius-live.ts +177 -0
- package/scripts/release-loop/gate-radius-shadow.ts +138 -0
- package/scripts/release-loop/gate-traffic-mode.ts +128 -0
- package/scripts/release-loop/gate-triage-node.ts +5 -2
- package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
- package/scripts/release-loop/known-issues-node.ts +77 -8
- package/scripts/release-loop/node-verdict.ts +12 -1
- package/scripts/release-loop/npm-publish-node.ts +66 -12
- package/scripts/release-loop/preflight.ts +93 -7
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
- package/scripts/release-loop/publish-node.ts +60 -9
- package/scripts/release-loop/pwa-remote.ts +166 -0
- package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
- package/scripts/release-loop/resume-cap.ts +56 -0
- package/scripts/release-loop/resume-release.ts +155 -19
- package/scripts/release-loop/resume.ts +24 -1
- package/scripts/release-loop/tui-sim-node.ts +8 -2
- package/scripts/release-loop/unattended-release.ts +10 -2
- 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/acp/core-turn-bridge.ts +20 -5
- package/src/acp/reasoning-thought-buffer.ts +45 -0
- package/src/agent/self-ambient-cache.ts +8 -0
- package/src/agent-substrate/acp-reviewer.ts +90 -15
- package/src/agent-substrate/pr-reviewer.ts +17 -0
- package/src/agent-substrate/review-finding-key.ts +53 -0
- package/src/agent-substrate/self-review-cli.ts +188 -18
- package/src/ask-user-question/pending-questions.ts +1 -1
- package/src/autopilot/pr-manager.ts +393 -65
- 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/chat/tool-render/dispatch.ts +62 -10
- package/src/cli/agent-cli.ts +13 -2
- package/src/cli/control-cli.ts +24 -7
- package/src/cli/doctor-cli.ts +4 -1
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/light-entry-route.ts +75 -0
- package/src/cli/llm-detect-cli.ts +23 -1
- package/src/cli/pod-cli.ts +77 -3
- package/src/cli/pr-cli.ts +81 -14
- package/src/cli/pr-land-base-read.ts +2 -0
- package/src/cli/pr-land-overlap-evidence.ts +154 -16
- package/src/cli/pr-land-pod-shadow-job.ts +3 -0
- package/src/cli/pr-land-recovery.ts +64 -0
- package/src/cli/pty-takeover-cli.ts +6 -5
- package/src/cli/release-checklist-read-cli.ts +79 -0
- package/src/cli/release-cli.ts +189 -132
- package/src/cli/release-run-if-ready.ts +29 -28
- package/src/cli/release-single-flight.ts +178 -0
- package/src/cli/remote-resolve.ts +1 -1
- package/src/cli/root-tui-entry.ts +48 -0
- package/src/cli/seat-cli.ts +37 -0
- package/src/cli/setup-cli.ts +40 -1
- package/src/cli/sim-cli.ts +22 -0
- package/src/cli/tasks-cli.ts +667 -14
- package/src/cli/usage-cli.ts +13 -11
- package/src/clipboard/history.ts +179 -13
- package/src/config.ts +8 -1
- package/src/control/control-status.ts +8 -3
- package/src/control-plane/ledger.ts +5 -3
- package/src/control-plane/server.ts +5 -3
- package/src/core-turn/short-question.ts +5 -1
- package/src/dashboard/chat/acp-chat.ts +8 -0
- package/src/dashboard/index.ts +114 -77
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/seat-autowake.ts +56 -3
- package/src/dashboard/render/theme-resolver.ts +33 -4
- package/src/dashboard/seat-boot-preamble.ts +1 -1
- package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
- package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
- package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
- package/src/dashboard/turn-preamble.ts +47 -1
- package/src/dashboard/turn-stream-formatter.ts +34 -1
- package/src/dashboard/turn-stream-runtime.ts +2 -0
- package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
- package/src/domains/guardian-tick.ts +54 -2
- package/src/domains/outbound-alert.ts +3 -2
- package/src/domains/schedule-registry.ts +16 -2
- package/src/extractors.ts +3 -1
- package/src/git-fs/idle-refresh.ts +76 -0
- package/src/git-fs/index.ts +18 -7
- package/src/git-fs/retry.ts +4 -0
- package/src/git-fs/runner.ts +2 -0
- package/src/git-fs/worktree.ts +42 -4
- package/src/graph-kinds/registry.ts +2 -2
- package/src/graph-runner/runner.ts +267 -54
- package/src/grok/credential.ts +15 -3
- package/src/harness/harness-cli-command.ts +151 -38
- package/src/harness/harness-incidents.ts +37 -0
- package/src/harness/harness-pod-dispatch.ts +38 -1
- package/src/harness/harness-salvage-cli.ts +14 -2
- 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 +683 -146
- package/src/intake-plane/already-built-hint.ts +91 -0
- package/src/intake-plane/requirement-funnel.ts +29 -1
- package/src/knowhow/pack.ts +199 -0
- package/src/light-cli.ts +111 -0
- 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 +268 -65
- package/src/loops/budget.ts +95 -0
- package/src/loops/msg-wake.ts +8 -2
- package/src/loops/orchestrator/traffic.ts +132 -1
- package/src/model-tier/llm-tier-map.ts +15 -1
- package/src/mss/logging/log-store.ts +4 -5
- package/src/native-tool-catalog.ts +15 -1
- package/src/nexus/api/graphs-api.ts +22 -3
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/loop-resources.ts +13 -1
- package/src/nexus/api/ops-api.ts +12 -0
- package/src/oauth/claude-pty-maturity.ts +66 -0
- package/src/oauth/codex-access-mirror.ts +55 -0
- package/src/oauth/codex.ts +7 -0
- package/src/oauth/fallback-chain.ts +1 -1
- package/src/onboarding/first-run.ts +5 -3
- package/src/onboarding/non-interactive.ts +64 -13
- package/src/onboarding.ts +10 -2
- package/src/ops/overview-collect.ts +54 -4
- package/src/ops/overview.ts +31 -7
- package/src/pr-tool/census.ts +282 -30
- package/src/pr-tool/inflight-registry.ts +160 -7
- package/src/prompt-library/gpt6-family-addendum.ts +14 -1
- package/src/pty-shell/herdr-agent-report.ts +442 -0
- package/src/pty-shell/pty-control-ipc.ts +5 -5
- package/src/pty-shell/pty-manifest.ts +7 -0
- package/src/pty-shell/pty-write-outcome.ts +24 -6
- package/src/pty-shell/tui-run-state.ts +117 -3
- package/src/release-loop/checklist.ts +103 -5
- package/src/release-loop/feature-store.ts +19 -2
- package/src/release-loop/landed-but-yellow.ts +129 -5
- package/src/release-loop/light-rc.ts +1 -0
- package/src/release-loop/placement.ts +10 -3
- package/src/release-loop/rehearsal.ts +205 -25
- package/src/release-loop/rubric.ts +16 -2
- package/src/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 +188 -13
- 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 +11 -6
- package/src/self-dev/graph-journey-route.ts +60 -6
- package/src/self-dev/harness-run-cli.ts +3 -15
- package/src/self-dev/orchestrate-cli-text.ts +10 -0
- package/src/self-dev/orchestrate.ts +79 -3
- package/src/self-dev/review-provider-fallback.ts +35 -1
- package/src/self-dev/run-supervisor.ts +107 -12
- package/src/self-dev/run-types.ts +5 -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 +95 -12
- package/src/self-implement/gate-cli.ts +1 -0
- package/src/self-implement/gate-remote.ts +40 -25
- package/src/self-implement/goal-author-decompose.ts +275 -47
- package/src/self-implement/goal-author-identity.ts +66 -0
- package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
- package/src/self-implement/goal-author.ts +254 -120
- 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 +28 -2
- package/src/self-implement/graph-unit-flatten.ts +103 -0
- package/src/self-implement/graph-unit-resolver.ts +107 -0
- package/src/self-implement/graph-yaml.ts +151 -1
- package/src/self-implement/headless-elanous-driver.ts +1 -0
- package/src/self-implement/knowhow-pack.ts +103 -0
- package/src/self-implement/orchestrator.ts +160 -45
- package/src/self-implement/pod-warm-pool-profile.ts +45 -0
- package/src/self-implement/review-mustfix-class.ts +203 -0
- package/src/self-implement/rework-budget-judgment.ts +5 -8
- package/src/self-implement/run-stop.ts +17 -2
- package/src/self-implement/running-runs.ts +29 -1
- package/src/self-implement/scope-adjacency.ts +113 -0
- package/src/self-implement/seams.ts +138 -4
- package/src/self-implement/stop-autoheal.ts +112 -2
- package/src/session/chat.ts +27 -0
- package/src/session-runtime/index.ts +1 -1
- package/src/session-runtime/retry-policy.ts +2 -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/skills/tools/schedule-wakeup.ts +66 -17
- package/src/steward/hold-hygiene.ts +24 -6
- package/src/steward/release-day.ts +7 -3
- package/src/steward/triage-budget.ts +194 -0
- package/src/steward/triage.ts +57 -7
- package/src/task-agent/actions.ts +69 -1
- package/src/task-agent/green-sweep.ts +4 -0
- package/src/task-agent/harvest-unit.ts +141 -0
- package/src/task-agent/live-moves.ts +257 -15
- package/src/task-agent/parent-host.ts +216 -6
- package/src/task-agent/postland-card.ts +80 -1
- package/src/task-agent/rejudge-on-head.ts +112 -26
- package/src/task-agent/repair-branch-cas.ts +4 -1
- package/src/task-agent/repair-cycle.ts +16 -3
- package/src/task-agent/run-identity.ts +4 -3
- package/src/task-agent/shadow.ts +19 -3
- package/src/task-agent/task-hand.ts +96 -36
- package/src/task-agent/tier-split.ts +127 -0
- package/src/task-agent/work-order-build.ts +24 -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 +72 -3
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
- 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-lifecycle-stages.ts +86 -8
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
- package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
- package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
- package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
- package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
- package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
- package/src/tool-runtime/truncation-store.ts +4 -0
- 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/dashboard-session.ts +10 -1
- 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/coercion.ts +36 -0
- package/src/user-config.ts +22 -43
- 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/ux-sim/scenario.ts +72 -13
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5543.a438b8ab5a13ea47.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989.3694300e5f000b14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
- package/src/cli/g6a-registration-probe.ts +0 -16
- /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → 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`). */
|
|
@@ -162,10 +173,23 @@ export interface DefaultTaskLauncherDeps {
|
|
|
162
173
|
launchHoldActive?: () => boolean;
|
|
163
174
|
/** HQ 판(시험 주입). */
|
|
164
175
|
localVersion?: string;
|
|
176
|
+
/** HQ-owned, refresh-less Codex access mirror to install before a remote parent launch. */
|
|
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;
|
|
182
|
+
/** Isolated integration seam; production still reads the HQ rotation snapshot and config directly. */
|
|
183
|
+
ownerCodexRotation?: () => ReturnType<typeof import('../oauth/codex-account-store.js').inspectCodexRotation>;
|
|
184
|
+
ownerCodexRotationConfig?: { accountOrder?: readonly string[]; thresholdPercentByAccount?: Readonly<Record<string, unknown>> };
|
|
185
|
+
/** The HQ owner fence is checked before any token refresh. */
|
|
186
|
+
ownerCodexLeaseHolder?: () => boolean;
|
|
165
187
|
/** 원격 → 로컬 되돌림 알림(시험 주입). 기본 = stderr 한 줄. */
|
|
166
188
|
notice?: (line: string) => void;
|
|
167
189
|
}
|
|
168
190
|
|
|
191
|
+
class NoEligibleOwnerCodexAccountError extends Error {}
|
|
192
|
+
|
|
169
193
|
/**
|
|
170
194
|
* HARNESS-PARENT-ON-MSB1 — 켜져 있고 발사 전 점검이 통과하면 원격(ssh)에서 부모를 띄운다(PR 까지만 · 병합은 HQ).
|
|
171
195
|
* 막히면 null — 호출부가 종전 로컬 발사로 간다(관측: task-agent parent-host-fallback).
|
|
@@ -180,11 +204,87 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
180
204
|
const multi = Array.isArray(configured);
|
|
181
205
|
const targets = configured === null ? [] : parentHostModule.resolveParentHosts(configured, deps.parentHost === undefined ? process.env : { ...process.env, ELANOUS_TA_PARENT_HOST: undefined });
|
|
182
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;
|
|
183
210
|
const notice = deps.notice ?? ((line: string) => { try { process.stderr.write(`${line}\n`); } catch { /* ignore */ } });
|
|
184
211
|
const failed = (target: typeof targets[number], gaps: string[], facts: Record<string, string> = {}): void => {
|
|
185
212
|
try { debug.log('task-agent', 'parent-host-fallback', { host: target.host, runId: context.runId, gaps, facts }); } catch { /* fail-soft */ }
|
|
186
213
|
notice(`[parent-host] ${target.host} 로 못 띄움 — ${multi ? '다음 호스트 또는 로컬 발사로 간다' : '로컬 발사로 간다'}: ${gaps.join(' · ')}`);
|
|
187
214
|
};
|
|
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> => {
|
|
218
|
+
if (accessMirror !== undefined) return accessMirror;
|
|
219
|
+
if (deps.codexAccessMirror) {
|
|
220
|
+
accessMirror = await deps.codexAccessMirror();
|
|
221
|
+
return accessMirror;
|
|
222
|
+
}
|
|
223
|
+
const [pod, authStore, codex, hq] = await Promise.all([
|
|
224
|
+
import('../task-orchestrator/surfaces/self-implement-pod.js'),
|
|
225
|
+
import('../oauth/store.js'),
|
|
226
|
+
import('../oauth/codex.js'),
|
|
227
|
+
import('../hq/hq.js'),
|
|
228
|
+
]);
|
|
229
|
+
const { inspectCodexRotation } = await import('../oauth/codex-account-store.js');
|
|
230
|
+
const { planOwnerCodexMirrorCandidates, podAccountThresholdPercent } = await import('../task-orchestrator/surfaces/pod-account-broker.js');
|
|
231
|
+
const { getUserConfig } = await import('../user-config.js');
|
|
232
|
+
const rotation = deps.ownerCodexRotation?.() ?? inspectCodexRotation();
|
|
233
|
+
const config = getUserConfig();
|
|
234
|
+
const ownerConfig = deps.ownerCodexRotationConfig;
|
|
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 토큰 주인 임대가 없어 원격 미러 발사를 거부한다');
|
|
240
|
+
const eligible = planOwnerCodexMirrorCandidates(candidates, {
|
|
241
|
+
accountOrder: ownerConfig?.accountOrder ?? config.llm?.codexAccountOrder ?? [],
|
|
242
|
+
thresholdPercentByAccount: ownerConfig?.thresholdPercentByAccount ?? config.llm?.codexAccountRotationThresholdPercentByAccount,
|
|
243
|
+
});
|
|
244
|
+
if (candidates.length > 0 && eligible.length === 0) throw new NoEligibleOwnerCodexAccountError('HQ 소유 Codex 계정이 모두 사용 임계에 도달해 원격 부모 발사를 거부한다');
|
|
245
|
+
const prerefreshDeps = {
|
|
246
|
+
credentials: (account: string) => pod.hostCredentials(account, authStore.authStorePath(), () => '', { requireExplicitChatgptAuthMode: true }),
|
|
247
|
+
refresh: (account: string) => codex.refreshCodexAccountHome(account),
|
|
248
|
+
isLeaseHolder: () => deps.ownerCodexLeaseHolder?.() ?? hq.hqFenceDecision('ledger-cli').run,
|
|
249
|
+
};
|
|
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.
|
|
258
|
+
let credential: Awaited<ReturnType<typeof pod.podCodexCredentialWithPrerefresh>> = null;
|
|
259
|
+
try { credential = await pod.podCodexCredentialWithPrerefresh(candidate.name, prerefreshDeps); }
|
|
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
|
+
}
|
|
284
|
+
}
|
|
285
|
+
accessMirror = mirrors.length ? { ...mirrors[0]!, mirrors } : null;
|
|
286
|
+
return accessMirror;
|
|
287
|
+
};
|
|
188
288
|
if (cwd) {
|
|
189
289
|
failed(targets[0]!, ['project-target-is-local']);
|
|
190
290
|
return null;
|
|
@@ -195,6 +295,11 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
195
295
|
// 그 앞의 readParentHostCapacity 도 ssh). 가드를 아래로 내리면 hold 경로에서 시험이 실 ssh 를 쏜다(R7 사고 모양).
|
|
196
296
|
// hold 경로를 재는 시험은 deps.ssh 가짜 또는 parentHost:null 을 주입한다(real-launch-guard.test 가 이 순서를 문다).
|
|
197
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;
|
|
198
303
|
let launchHoldActive = false;
|
|
199
304
|
try {
|
|
200
305
|
if (deps.launchHoldActive) launchHoldActive = deps.launchHoldActive();
|
|
@@ -204,8 +309,39 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
204
309
|
launchHoldActive = readLandingFreeze(prodInstanceRoot())?.holdLaunches === true;
|
|
205
310
|
}
|
|
206
311
|
} catch { launchHoldActive = true; /* 못 읽으면 막힌 것으로(fail-closed) */ }
|
|
207
|
-
const
|
|
208
|
-
|
|
312
|
+
const podGoal = context.substrate === 'pod' ? context.podGoal : undefined;
|
|
313
|
+
// 부모에서 잰 메모리 선택자만 원격 자식에도 넘긴다. 로컬의 나머지 환경·자격은 SSH 로 복사하지 않는다.
|
|
314
|
+
const remoteEnv = { ...context.env };
|
|
315
|
+
// These labels describe an HQ-selected Codex access mirror; never forward an inherited label by itself.
|
|
316
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNT;
|
|
317
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_USED_PERCENT;
|
|
318
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_THRESHOLD_PERCENT;
|
|
319
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCOUNTS;
|
|
320
|
+
delete remoteEnv.ELANOUS_REMOTE_CODEX_ACCESS_ONLY;
|
|
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) {
|
|
322
|
+
const value = context.env[key] ?? process.env[key];
|
|
323
|
+
if (value !== undefined) remoteEnv[key] = value;
|
|
324
|
+
}
|
|
325
|
+
const memoryLimit = podGoal ? (await import('../task-orchestrator/surfaces/self-implement-pod.js')).podMemoryLimitFor(podGoal, remoteEnv).limit : undefined;
|
|
326
|
+
const fits = Object.fromEntries(targets.map((target) => {
|
|
327
|
+
const fit = memoryLimit
|
|
328
|
+
? parentHostModule.readParentHostPodFit(target, memoryLimit, deps.ssh)
|
|
329
|
+
: { state: 'unmeasured' as const, memoryLimit: '', requiredBytes: null, allocatableBytes: null, reason: 'pod-context-unmeasured' };
|
|
330
|
+
try { debug.log('task-agent.parent-host', 'pod-fit', { host: target.host, runId: context.runId, ...fit }); } catch { /* fail-soft */ }
|
|
331
|
+
if (fit.state === 'never-fits') notice(`[parent-host] ${target.host} 제외 — ${fit.reason}: Pod ${fit.memoryLimit} (${fit.requiredBytes} bytes) > node allocatable ${fit.allocatableBytes} bytes`);
|
|
332
|
+
return [target.host, fit];
|
|
333
|
+
}));
|
|
334
|
+
const eligible = targets.filter((target) => fits[target.host]?.state !== 'never-fits');
|
|
335
|
+
if (!eligible.length) {
|
|
336
|
+
const details = targets.map((target) => `${target.host}: Pod ${fits[target.host]!.memoryLimit} (${fits[target.host]!.requiredBytes} bytes) > node allocatable ${fits[target.host]!.allocatableBytes} bytes`).join(' · ');
|
|
337
|
+
throw new Error(`parent-host memory-never-fits — ${details}; local fallback refused`);
|
|
338
|
+
}
|
|
339
|
+
const capacities = Object.fromEntries(multi ? eligible.map((target) => [target.host, parentHostModule.readParentHostCapacity(target, deps.ssh)]) : []);
|
|
340
|
+
const measured = eligible.filter((target) => fits[target.host]?.state === 'fits');
|
|
341
|
+
const unknown = eligible.filter((target) => fits[target.host]?.state !== 'fits');
|
|
342
|
+
const ordered = multi
|
|
343
|
+
? [...parentHostModule.orderParentHosts(measured, context.runId, capacities), ...parentHostModule.orderParentHosts(unknown, context.runId, capacities)]
|
|
344
|
+
: eligible;
|
|
209
345
|
for (const target of ordered) {
|
|
210
346
|
if (multi && (!capacities[target.host] || capacities[target.host]!.approvalHeadroom <= 0)) {
|
|
211
347
|
failed(target, ['capacity-unavailable']);
|
|
@@ -217,11 +353,64 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
|
|
|
217
353
|
if (!preflight.ok) { failed(target, preflight.gaps, preflight.facts); continue; }
|
|
218
354
|
if (preflight.warnings.length) notice(`⚠ ${target.host} 자격: ${preflight.warnings.join(' · ')}`);
|
|
219
355
|
try {
|
|
220
|
-
|
|
356
|
+
if (parentHostModule.shouldInstallRemoteCodexAccess(context.effectiveChildProvider)) {
|
|
357
|
+
let mirror: OwnerMirror | null = null;
|
|
358
|
+
let mirrorReason = 'credential-source-empty';
|
|
359
|
+
try { mirror = await getAccessMirror(); }
|
|
360
|
+
catch (error) {
|
|
361
|
+
if (error instanceof NoEligibleOwnerCodexAccountError) throw error;
|
|
362
|
+
mirrorReason = 'credential-source-error';
|
|
363
|
+
}
|
|
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
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
try { debug.log('task-agent.parent-host', 'codex-access-mirror-unavailable', { host: target.host, runId: context.runId, reason: mirrorReason }); } catch { /* fail-soft */ }
|
|
396
|
+
failed(target, ['codex-access-mirror-unavailable']);
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
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);
|
|
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';
|
|
406
|
+
}
|
|
407
|
+
const launched = parentHostModule.launchRemoteParent(target, args, remoteEnv, deps.ssh,
|
|
408
|
+
grokAccessMirror ? () => grokAccessMirror : undefined, effectiveChildProvider, deps.now);
|
|
221
409
|
try { debug.log('task-agent', 'parent-host-launched', { host: target.host, runId: context.runId, pid: launched.pid, log: launched.log }); } catch { /* fail-soft */ }
|
|
222
410
|
return { runId: context.runId, parentHost: { host: target.host, ...(target.configDir ? { configDir: target.configDir } : {}), pid: launched.pid, log: launched.log } };
|
|
223
411
|
} catch (error) {
|
|
224
412
|
if (error instanceof parentHostModule.RemoteParentNotLaunchedError) { failed(target, [error.message]); continue; }
|
|
413
|
+
if (error instanceof NoEligibleOwnerCodexAccountError) throw error;
|
|
225
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 */ }
|
|
226
415
|
throw error;
|
|
227
416
|
}
|
|
@@ -242,6 +431,7 @@ function firstStderrLine(path: string): string {
|
|
|
242
431
|
}
|
|
243
432
|
|
|
244
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
|
|
245
435
|
if (context) {
|
|
246
436
|
const remote = await tryRemoteParent(args, cwd, context, deps);
|
|
247
437
|
if (remote) return remote;
|
|
@@ -398,6 +588,7 @@ function taskCardLines(card: TaskCard): string[] {
|
|
|
398
588
|
return [
|
|
399
589
|
[card.id, card.status, card.seat ?? '-', card.checklistId ?? '-', card.createdAt, card.text].join('\t'),
|
|
400
590
|
...cardIdentityLines(card),
|
|
591
|
+
...(card.targetPaths !== undefined ? [`대상 경로: ${card.targetPaths.length ? card.targetPaths.join(' · ') : '(유효한 경로 없음)'}`] : []),
|
|
401
592
|
...(card.mission ? [`미션: ${card.mission} · after: ${card.after?.length ? card.after.join(', ') : '-'}`] : []),
|
|
402
593
|
...runLinkLine(card),
|
|
403
594
|
...liveMoveLines(card),
|
|
@@ -794,6 +985,332 @@ export function readTaskAgentCover(
|
|
|
794
985
|
limitReached: truncated.taskAgentActions || truncated.allLands || moveRead?.limitReached === true || orderRead?.limitReached === true || goalAsksTruncated || goalRunsTruncated, unreadableStores };
|
|
795
986
|
}
|
|
796
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
|
+
|
|
797
1314
|
export function registerTasksCommands(program: Command, deps: TasksCliDeps = {}): void {
|
|
798
1315
|
let activeToken: string | undefined;
|
|
799
1316
|
const output = deps.output ?? console.log;
|
|
@@ -806,6 +1323,38 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
806
1323
|
};
|
|
807
1324
|
const tasks = program.command('tasks').alias('task').description('TOX 태스크 조회 및 승인 · TASK-AGENT 과제 넘기기(hand)');
|
|
808
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
|
+
|
|
809
1358
|
tasks.command('green-sweep')
|
|
810
1359
|
.description('병합된 과제 PR 과 칸 근거를 대조해 green/기록만/건너뜀을 미리 본다 (항상 dry-run)')
|
|
811
1360
|
.requiredOption('--version <version>', '조회할 체크리스트 판')
|
|
@@ -820,6 +1369,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
820
1369
|
{ cwd: process.cwd(), encoding: 'utf8', timeout: 20_000 }));
|
|
821
1370
|
const cards = Object.values(readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(deps.taskStatePath ?? taskStatePathDefault()).tasks ?? {});
|
|
822
1371
|
let holds: Set<string> | null = null;
|
|
1372
|
+
let holdDiagnostic: string | undefined;
|
|
823
1373
|
if (opts.traffic) {
|
|
824
1374
|
try {
|
|
825
1375
|
const traffic: unknown = JSON.parse(readFileSync(opts.traffic, 'utf8'));
|
|
@@ -827,8 +1377,13 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
827
1377
|
&& Array.isArray((traffic as { hold?: unknown }).hold)
|
|
828
1378
|
&& (traffic as { hold: unknown[] }).hold.every((id) => typeof id === 'string'))
|
|
829
1379
|
holds = new Set((traffic as { hold: string[] }).hold);
|
|
830
|
-
|
|
831
|
-
|
|
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';
|
|
832
1387
|
const prCache = new Map<number, GreenSweepPr | null>();
|
|
833
1388
|
const ambiguousPrs = ambiguousGreenSweepPrs(snapshot.items, opts.version, cards);
|
|
834
1389
|
const origin = run('git', ['remote', 'get-url', 'origin']);
|
|
@@ -878,7 +1433,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
878
1433
|
return check.status === 0 ? true : check.status === 1 ? false : null;
|
|
879
1434
|
})();
|
|
880
1435
|
const decision = decideGreenSweep({ item, candidate, candidateCount: candidates.length,
|
|
881
|
-
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,
|
|
882
1437
|
ambiguousAcrossCells: ambiguousPrs.has(candidate.pr) });
|
|
883
1438
|
observeGreenSweep(decision);
|
|
884
1439
|
return decision;
|
|
@@ -890,8 +1445,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
890
1445
|
if (opts.json) out(JSON.stringify({ dryRun: true, version: opts.version, counts, decisions }));
|
|
891
1446
|
else {
|
|
892
1447
|
out(`dry-run · ${opts.version} · 후보 ${counts.candidate} · green ${counts.green} · 기록만 ${counts.recordOnly} · 건너뜀 ${counts.skipped}`);
|
|
893
|
-
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)}`);
|
|
894
|
-
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 ?? ''}`);
|
|
895
1449
|
}
|
|
896
1450
|
} catch (error) { out(`green-sweep 조회 실패: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
897
1451
|
});
|
|
@@ -948,6 +1502,41 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
948
1502
|
} catch (error) { out(error instanceof Error ? error.message : '커버 조회 실패'); process.exitCode = 1; }
|
|
949
1503
|
});
|
|
950
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
|
+
|
|
951
1540
|
tasks.command('list')
|
|
952
1541
|
.description('우선순위와 생성 시각 순으로 태스크 보기')
|
|
953
1542
|
.option('--status <s>', '상태로 필터')
|
|
@@ -1124,7 +1713,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1124
1713
|
if (resolved.kind === 'inlined') {
|
|
1125
1714
|
try { debug.log('task-agent.hand', 'goal-file-inlined', { path: resolved.path, chars: resolved.chars, sha256: resolved.sha256 }); } catch { /* fail-soft */ }
|
|
1126
1715
|
}
|
|
1127
|
-
const
|
|
1716
|
+
const handed = await handTaskWithTierSplit({
|
|
1717
|
+
...('tierSizedDecompose' in deps ? { decompose: deps.tierSizedDecompose } : {}),
|
|
1128
1718
|
text: resolved.text,
|
|
1129
1719
|
...(opts.project !== undefined && opts.target !== undefined ? { project: { id: opts.project, target: opts.target } } : {}),
|
|
1130
1720
|
...(opts.goal !== undefined ? { goal: opts.goal } : {}),
|
|
@@ -1133,6 +1723,7 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1133
1723
|
...(opts.checklist ? { checklistId: opts.checklist } : {}),
|
|
1134
1724
|
...(opts.completion ? { completion: opts.completion } : {}),
|
|
1135
1725
|
live: opts.live === true,
|
|
1726
|
+
preflightGoalDoneBoundary: opts.live === true && deps.taskLauncher === undefined,
|
|
1136
1727
|
...(opts.taLand === true ? { taLand: true } : {}),
|
|
1137
1728
|
...(opts.childLlm !== undefined ? { childLlm: opts.childLlm } : {}),
|
|
1138
1729
|
...(opts.childLlmEffort !== undefined ? { childLlmEffort: opts.childLlmEffort } : {}),
|
|
@@ -1143,8 +1734,29 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1143
1734
|
...(deps.taskCompositionRoot ? { compositionRoot: deps.taskCompositionRoot } : {}),
|
|
1144
1735
|
launcher: deps.taskLauncher ?? defaultTaskLauncher,
|
|
1145
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;
|
|
1146
1754
|
if (opts.json) out(JSON.stringify(result));
|
|
1147
|
-
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 {
|
|
1148
1760
|
out(`${result.card.id}\t${result.mode}\t${result.launched ? 'launched' : 'not launched'}`);
|
|
1149
1761
|
if (result.move.command) out(`elanous ${result.move.command.map(shellQuote).join(' ')}`);
|
|
1150
1762
|
else out(result.move.reason);
|
|
@@ -1578,7 +2190,45 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1578
2190
|
: {});
|
|
1579
2191
|
try { debug.log('task-agent', 'remote-rejudge-bind', binding); } catch { /* fail-soft */ }
|
|
1580
2192
|
}
|
|
1581
|
-
ids =
|
|
2193
|
+
if (id) ids = [id];
|
|
2194
|
+
else {
|
|
2195
|
+
const maxAgeHours = (await import('../user-config.js')).getUserConfig().taskAgent?.rejudgeMaxAgeHours ?? 72;
|
|
2196
|
+
const cards = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {};
|
|
2197
|
+
const candidates = rejudgeCandidates(cards, { maxAgeHours, onAgeSkip: (card, ageHours) => {
|
|
2198
|
+
try { debug.log('task-agent', 'rejudge-age-skip', { card: card.id, ageHours, maxAgeHours }); } catch { /* fail-soft */ }
|
|
2199
|
+
} });
|
|
2200
|
+
const { capturedLandReview } = await import('../task-agent/review-result-capture.js');
|
|
2201
|
+
const { defaultPrHead, defaultReviewRepoCandidates } = await import('../task-agent/live-moves.js');
|
|
2202
|
+
const currentHeads = new Map<string, string>();
|
|
2203
|
+
// Priority is a hint, not a gate. Consider only the three newest candidates;
|
|
2204
|
+
// a non-mf0 card still consumes one of those three places. Everyone else runs in age order.
|
|
2205
|
+
const priorityCandidates = candidates.slice(0, 3);
|
|
2206
|
+
let headProbes = 0;
|
|
2207
|
+
for (const cardId of priorityCandidates) {
|
|
2208
|
+
const card = cards[cardId];
|
|
2209
|
+
if (!card || typeof card.pr !== 'object' || !card.pr?.url) continue;
|
|
2210
|
+
const pr = card.pr.number;
|
|
2211
|
+
const lastHead = card.reviewRequests?.filter((entry) => entry.pr === pr).at(-1)?.head;
|
|
2212
|
+
if (!lastHead || capturedLandReview(card, pr, lastHead)?.mustFixCount !== 0) continue;
|
|
2213
|
+
let repos: readonly import('../task-agent/live-moves.js').ReviewRepoCandidate[] = [];
|
|
2214
|
+
try { repos = (deps.rejudge?.live?.repoCandidates ?? defaultReviewRepoCandidates)(card); } catch { /* no trusted repo */ }
|
|
2215
|
+
const repo = repos[0];
|
|
2216
|
+
if (!repo) continue;
|
|
2217
|
+
headProbes++;
|
|
2218
|
+
let view: Awaited<ReturnType<typeof defaultPrHead>>;
|
|
2219
|
+
try { view = await (deps.rejudge?.live?.prHead
|
|
2220
|
+
? deps.rejudge.live.prHead(pr, repo.cwd)
|
|
2221
|
+
: defaultPrHead(pr, repo.cwd, (args, options) => spawnSync('gh', args, {
|
|
2222
|
+
encoding: 'utf8', timeout: 3_000, env: options.env, ...(options.cwd ? { cwd: options.cwd } : {}),
|
|
2223
|
+
}))); } catch { view = null; }
|
|
2224
|
+
if (view?.state === 'OPEN' && view.url === card.pr.url) currentHeads.set(cardId, view.head);
|
|
2225
|
+
}
|
|
2226
|
+
if (candidates.length > priorityCandidates.length) {
|
|
2227
|
+
try { debug.log('task-agent', 'rejudge-head-priority-probe-cap', { considered: priorityCandidates.length,
|
|
2228
|
+
probed: headProbes, totalCandidates: candidates.length, max: 3 }); } catch { /* fail-soft */ }
|
|
2229
|
+
}
|
|
2230
|
+
ids = rejudgeCandidates(cards, { maxAgeHours, currentHeads });
|
|
2231
|
+
}
|
|
1582
2232
|
} catch (error) {
|
|
1583
2233
|
out(error instanceof Error ? error.message : '과제 카드 읽기 실패'); process.exitCode = 1; return;
|
|
1584
2234
|
}
|
|
@@ -1586,6 +2236,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1586
2236
|
const liveMoves = deps.rejudge?.liveMoves ?? await configuredTaskAgentLiveMoves();
|
|
1587
2237
|
const repairBudget = opts.all ? { max: (await import('../user-config.js')).getUserConfig().taskAgent?.repairMaxPerTick ?? 3,
|
|
1588
2238
|
requested: 0, capped: 0 } : undefined;
|
|
2239
|
+
const reviewBudget = opts.all ? { max: 1, requested: 0 } : undefined;
|
|
2240
|
+
const landBudget = opts.all ? { max: 1, requested: 0 } : undefined;
|
|
1589
2241
|
const all = [];
|
|
1590
2242
|
for (const cardId of ids) {
|
|
1591
2243
|
await mirrorRemoteCardLedger(cardId, deps);
|
|
@@ -1594,7 +2246,8 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
|
|
|
1594
2246
|
}
|
|
1595
2247
|
let outcomes: Awaited<ReturnType<typeof rejudgeCardOnHead>>;
|
|
1596
2248
|
try { outcomes = await rejudgeCardOnHead(cardId, { ...deps.rejudge, liveMoves,
|
|
1597
|
-
...(repairBudget ? { repairBudget } : {}),
|
|
2249
|
+
...(repairBudget ? { repairBudget } : {}), ...(reviewBudget ? { reviewBudget } : {}), ...(landBudget ? { landBudget } : {}),
|
|
2250
|
+
live: { ...deps.rejudge?.live, statePath } }); } catch (error) {
|
|
1598
2251
|
// 카드 하나의 예외가 --all 의 나머지 카드 판단을 멈추지 않게 — 사유를 남기고 다음 카드로.
|
|
1599
2252
|
const reason = (error instanceof Error ? error.message : String(error)).slice(-300);
|
|
1600
2253
|
try { debug.log('task-agent', 'rejudge-on-head', { card: cardId, pr: null, fromHead: null, toHead: null, step: 'target', decision: 'rejudge-threw', reason }, { level: 'warn' }); } catch { /* fail-soft */ }
|