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
|
@@ -10,10 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { DecomposeInput } from './generator.js';
|
|
12
12
|
import type { ProposalValidationError } from './generator-schema.js';
|
|
13
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
14
|
+
import { resolve } from 'node:path';
|
|
13
15
|
|
|
14
16
|
export type DecomposePromptProfile = 'goal-author-coarse';
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
/** TaskGenerator's safety ceiling, not an authoring target; goal-author splits by slice size. */
|
|
19
|
+
export const GOAL_AUTHOR_SIZE_SAFETY_MAX_SLICES = 15;
|
|
17
20
|
|
|
18
21
|
export interface BuildPromptOptions {
|
|
19
22
|
maxTasks: number;
|
|
@@ -39,6 +42,35 @@ const CODING_GOAL_KINDS: ReadonlySet<string> = new Set([
|
|
|
39
42
|
'agentic',
|
|
40
43
|
]);
|
|
41
44
|
|
|
45
|
+
/** Read the existing device sources at authoring time; the LLM has no file tools in this phase. */
|
|
46
|
+
let deviceInventoryCache: string[] | undefined;
|
|
47
|
+
function deviceInventory(): string[] {
|
|
48
|
+
if (deviceInventoryCache) return deviceInventoryCache;
|
|
49
|
+
const root = resolve(import.meta.dir, '../..');
|
|
50
|
+
const fallback = ['- Device inventory unavailable in this installation; verify a named device before claiming it exists.'];
|
|
51
|
+
if (!existsSync(resolve(root, 'src/ux-sim'))) return deviceInventoryCache = fallback;
|
|
52
|
+
try {
|
|
53
|
+
const files = readdirSync(resolve(root, 'src/ux-sim'))
|
|
54
|
+
.filter((name) => name.endsWith('.ts') && !name.endsWith('.test.ts')).sort();
|
|
55
|
+
const monkey = readFileSync(resolve(root, 'src/ux-sim/event-monkey.ts'), 'utf8');
|
|
56
|
+
const kinds = monkey.match(/export const EVENT_MONKEY_KINDS = \[([\s\S]*?)\] as const;/)?.[1]
|
|
57
|
+
?.match(/'[^']+'/g)?.map((kind) => kind.slice(1, -1)) ?? [];
|
|
58
|
+
let rows: string[] = [];
|
|
59
|
+
try {
|
|
60
|
+
const manual = readFileSync(resolve(root, 'docs/manual/MANUAL-ux-simulation-devices-2026-08-23.md'), 'utf8');
|
|
61
|
+
rows = manual.split('\n').filter((line) => line.startsWith('|') && line.includes('`src/ux-sim/'));
|
|
62
|
+
} catch { /* Published packages omit docs/manual; source catalog still applies. */ }
|
|
63
|
+
return deviceInventoryCache = [
|
|
64
|
+
`- src/ux-sim files: ${files.join(', ')}`,
|
|
65
|
+
`- event-monkey kinds: ${kinds.join(', ')}`,
|
|
66
|
+
...(rows.length ? [] : ['- manual §1 table unavailable in this installation; use the source files and event kinds above.']),
|
|
67
|
+
...rows.map((row) => `- manual §1: ${row.replace(/\s*\|\s*/g, ' · ').slice(0, 500)}`),
|
|
68
|
+
];
|
|
69
|
+
} catch {
|
|
70
|
+
return deviceInventoryCache = fallback;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
42
74
|
export function buildDecomposePrompt(
|
|
43
75
|
input: DecomposeInput,
|
|
44
76
|
opts: BuildPromptOptions
|
|
@@ -53,7 +85,7 @@ export function buildDecomposePrompt(
|
|
|
53
85
|
lines.push(
|
|
54
86
|
'You are the monad-agent Task Orchestrator decomposition planner.',
|
|
55
87
|
isGoalAuthorCoarse
|
|
56
|
-
?
|
|
88
|
+
? 'Break the objective into implementation slices that a low or medium tier model can finish. Split by slice size, not a target number of slices; the task count limit is only a safety ceiling.'
|
|
57
89
|
: 'Break the objective into 3-7 concrete, single-responsibility tasks.',
|
|
58
90
|
'',
|
|
59
91
|
'## Output (STRICT JSON)',
|
|
@@ -119,9 +151,10 @@ export function buildDecomposePrompt(
|
|
|
119
151
|
'- ★ Complete dependsOn contracts: if a phase CONSUMES another phase\'s output, that producing phase MUST be in this phase\'s `dependsOn` (by index). A consumer with no dependsOn on its producer looks like an ungrounded/orphan dependency to the critique. Trace every consumed symbol to either grounding (exists) or a dependsOn phase (produced this mission).',
|
|
120
152
|
...(isGoalAuthorCoarse
|
|
121
153
|
? [
|
|
122
|
-
'-
|
|
123
|
-
'-
|
|
124
|
-
'- Keep
|
|
154
|
+
'- Goal-author size: each slice should touch at most 4 target files, change at most 2 behaviors, and create at most 2 files. Count tests and runtime wiring among target files.',
|
|
155
|
+
'- Prefer low tier (at most 2 files, 1 behavior, 1 new file), then medium tier (at most 4 files, 2 behaviors, 2 new files). Do not make a high tier slice merely to reduce the number of slices.',
|
|
156
|
+
'- Keep the executable dependency path through dependsOn; split oversized work into dependent slices rather than hiding multiple behaviors in one title.',
|
|
157
|
+
'- A high tier slice is allowed only when it cannot be split further without breaking an inseparable operation. State its unavoidable reason in the rationale.',
|
|
125
158
|
]
|
|
126
159
|
: [
|
|
127
160
|
'- Small scope: keep each task ≈≤250 LOC of change. If a step is bigger, split it into sibling tasks or defer to a recursive decompose (depth) rather than one giant task.',
|
|
@@ -155,13 +188,29 @@ export function buildDecomposePrompt(
|
|
|
155
188
|
if (isGoalAuthorCoarse) {
|
|
156
189
|
lines.push(
|
|
157
190
|
'',
|
|
158
|
-
'## Goal-author
|
|
159
|
-
'-
|
|
160
|
-
'-
|
|
161
|
-
'-
|
|
162
|
-
'- Every
|
|
191
|
+
'## Goal-author size-bounded slicing (follow strictly)',
|
|
192
|
+
'- Use the task budget as a safety ceiling, not a target. Add dependent slices whenever one slice would exceed medium size.',
|
|
193
|
+
'- Give each slice an executable outcome with tests or runtime wiring inside its size limit; place further wiring in a dependent slice.',
|
|
194
|
+
'- Every slice title MUST name at least one actual file path or function name because only the title is passed to the next stage; slices must remain grounded and verifiable.',
|
|
195
|
+
'- Every task JSON must include files, behaviours, newFiles and tier. Example: {"index":0,"title":"대상 경로: src/a.ts · 동작: 연결","files":1,"behaviours":1,"newFiles":0,"tier":"low","surface":{"kind":"llm-direct","prompt":"wire src/a.ts"}}.',
|
|
196
|
+
'- Only the title reaches the sizing fallback: start it with "대상 경로:" and name all touched paths; add one "동작:" clause per changed behavior and "신규 경로:" for each new file. Keep the title within 80 characters by splitting oversized work.',
|
|
163
197
|
'- Fold non-code investigation or design into the implementation slice that needs it; do not emit it as a standalone slice.',
|
|
164
|
-
'- Use dependsOn
|
|
198
|
+
'- Use dependsOn for genuine ordering between independently completable slices, including definition before dependent runtime wiring.',
|
|
199
|
+
);
|
|
200
|
+
// ── 장치 우선 분해 (DEVICE-FIRST-AUTHORING · 대표 10-21 18:1x 골 저작 지침) ──
|
|
201
|
+
// 골 저작의 검증 계획(TDD) 절이 무대·층을 고를 때 그 시험에 필요한 mock 장치·주입 사건 정의의
|
|
202
|
+
// 존재를 먼저 확인하게 한다. 장치가 없으면 «실물 없음»으로 초록이 막히므로 첫 조각이 장치 조각이 된다.
|
|
203
|
+
lines.push(
|
|
204
|
+
'',
|
|
205
|
+
'## Device-first decomposition (DEVICE-FIRST-AUTHORING — follow strictly)',
|
|
206
|
+
'### Existing device inventory (read from this checkout; use these names before proposing a new device)',
|
|
207
|
+
...deviceInventory(),
|
|
208
|
+
'- The objective\'s verification plan (검증 계획/TDD) section picks a stage and ladder tier (무대·층) — e.g. a `src/ux-sim/*` stage at L2 (fake-llm·fake-bin·fake-clock). BEFORE writing slices, CHECK whether the mock device or injected event definition that this verification plan needs ALREADY EXISTS: look in `src/ux-sim/*`, the §1 device table of `docs/manual/MANUAL-ux-simulation-devices-2026-08-23.md`, and the event-monkey event kinds.',
|
|
209
|
+
'- Two branches — exactly one applies per needed device:',
|
|
210
|
+
' - Device EXISTS: its name MUST go into the verification plan wording — the slice that tests the feature carries the device\'s exact name (device file / §1 table row / event kind) in its acceptance criteria and reuses the device; never re-create it.',
|
|
211
|
+
' - Device MISSING: the FIRST slice MUST be a device slice that develops that device feature first — the mock device or injected event definition under `src/ux-sim/*` — and every slice that tests the feature depends on it (구현할 때 해당 시험 mock 장치나 이벤트 정의가 있나 확인하고, 없으면 그 장치 피처를 먼저 개발).',
|
|
212
|
+
'- Do NOT create the device itself here beyond emitting that device slice (장치 자체는 만들지 않는다 — 조각으로 내보낼 뿐); consumer slices reference it only via dependsOn.',
|
|
213
|
+
'- Device slices obey the same size bounds and acceptance bar as every other slice — the size rules (TIER-SIZED-DECOMPOSE) and the green-judgment rules are UNCHANGED.',
|
|
165
214
|
);
|
|
166
215
|
}
|
|
167
216
|
|
|
@@ -17,6 +17,17 @@ export type PodProviderPlan =
|
|
|
17
17
|
| { provider: 'grok'; excluded: PodAccountPlan['excluded']; grokSubscriptionEligible: boolean }
|
|
18
18
|
| { provider: null; reasons: string[]; grokSubscriptionEligible: boolean };
|
|
19
19
|
|
|
20
|
+
/** Effective cap used by the Pod broker; callers carrying an owner-approved selection must carry this same value. */
|
|
21
|
+
export function podAccountThresholdPercent(name: string, options: {
|
|
22
|
+
excludeAt?: number;
|
|
23
|
+
thresholdPercentByAccount?: Readonly<Record<string, unknown>>;
|
|
24
|
+
} = {}): number {
|
|
25
|
+
return codexAccountThresholdPercent(name, {
|
|
26
|
+
thresholdPercent: options.excludeAt ?? POD_ACCOUNT_EXCLUDE_AT_PERCENT,
|
|
27
|
+
thresholdPercentByAccount: options.thresholdPercentByAccount,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
/** Pod 의 codex → grok 선택. 자격 종류는 과금 동의와 별도로 판단한다. */
|
|
21
32
|
export function planPodProvider(input: {
|
|
22
33
|
codexCandidates: readonly RotationCandidate[];
|
|
@@ -85,9 +96,7 @@ export function planPodAccounts(
|
|
|
85
96
|
const known: RotationCandidate[] = [];
|
|
86
97
|
const unknown: RotationCandidate[] = [];
|
|
87
98
|
for (const c of candidates) {
|
|
88
|
-
const threshold = typeof options === 'number'
|
|
89
|
-
? excludeAt
|
|
90
|
-
: codexAccountThresholdPercent(c.name, { thresholdPercent: excludeAt, thresholdPercentByAccount });
|
|
99
|
+
const threshold = typeof options === 'number' ? excludeAt : podAccountThresholdPercent(c.name, { excludeAt, thresholdPercentByAccount });
|
|
91
100
|
if (c.reached === true) { excluded.push({ name: c.name, why: 'quota reached' }); continue; }
|
|
92
101
|
if (c.usedPercent !== undefined && c.usedPercent >= threshold) { excluded.push({ name: c.name, why: `used ${c.usedPercent}% ≥ ${threshold}%` }); continue; }
|
|
93
102
|
(c.usedPercent === undefined ? unknown : known).push(c);
|
|
@@ -113,6 +122,66 @@ export function planPodAccounts(
|
|
|
113
122
|
return { usable, excluded };
|
|
114
123
|
}
|
|
115
124
|
|
|
125
|
+
/** HQ selects one owner account before remote-parent launch; keep the configured rotation order. */
|
|
126
|
+
export function planOwnerCodexMirrorCandidates(candidates: readonly RotationCandidate[], options: {
|
|
127
|
+
accountOrder: readonly string[];
|
|
128
|
+
thresholdPercentByAccount?: Readonly<Record<string, unknown>>;
|
|
129
|
+
}): RotationCandidate[] {
|
|
130
|
+
const usable = new Set(planPodAccounts(candidates, { thresholdPercentByAccount: options.thresholdPercentByAccount }).usable);
|
|
131
|
+
const rank = (name: string): number => {
|
|
132
|
+
const index = options.accountOrder.indexOf(name);
|
|
133
|
+
return index < 0 ? options.accountOrder.length : index;
|
|
134
|
+
};
|
|
135
|
+
return candidates.map((candidate, index) => ({ candidate, index })).filter(({ candidate }) => usable.has(candidate.name))
|
|
136
|
+
.sort((a, b) => rank(a.candidate.name) - rank(b.candidate.name) || a.index - b.index)
|
|
137
|
+
.map(({ candidate }) => candidate);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Remote owner-mirror runs may plan against exactly the account HQ selected and its measured usage. */
|
|
141
|
+
export function ownerCodexMirrorCandidate(candidates: readonly RotationCandidate[], account: string, usedPercent?: number): RotationCandidate[] {
|
|
142
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(account)) return [];
|
|
143
|
+
return candidates.filter((candidate) => candidate.name === account).map((candidate) => {
|
|
144
|
+
const ownerCandidate = { ...candidate };
|
|
145
|
+
delete ownerCandidate.usedPercent;
|
|
146
|
+
ownerCandidate.reached = false;
|
|
147
|
+
const measured = usedPercent !== undefined && Number.isFinite(usedPercent) ? usedPercent : undefined;
|
|
148
|
+
return { ...ownerCandidate, reached: false, ...(measured !== undefined ? { usedPercent: measured } : {}) };
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface OwnerCodexMirrorAccount { account: string; usedPercent: number | null; thresholdPercent: number; expiresAt: number }
|
|
153
|
+
|
|
154
|
+
/** The remote may rotate only across the accounts HQ actually installed in this launch snapshot. */
|
|
155
|
+
export function parseOwnerCodexMirrorAccounts(raw: string): OwnerCodexMirrorAccount[] {
|
|
156
|
+
let parsed: unknown;
|
|
157
|
+
try { parsed = JSON.parse(raw); } catch { throw new Error('HQ Codex 미러 계정 목록이 잘못됐다'); }
|
|
158
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || parsed.length > 16) throw new Error('HQ Codex 미러 계정 목록이 잘못됐다');
|
|
159
|
+
const seen = new Set<string>();
|
|
160
|
+
return parsed.map((item: unknown) => {
|
|
161
|
+
if (!item || typeof item !== 'object') throw new Error('HQ Codex 미러 계정 항목이 잘못됐다');
|
|
162
|
+
const value = item as Record<string, unknown>;
|
|
163
|
+
const { account, usedPercent, thresholdPercent, expiresAt } = value;
|
|
164
|
+
if (typeof account !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(account) || seen.has(account)
|
|
165
|
+
|| (usedPercent !== null && (typeof usedPercent !== 'number' || !Number.isFinite(usedPercent) || usedPercent < 0 || usedPercent > 100))
|
|
166
|
+
|| typeof thresholdPercent !== 'number' || !Number.isFinite(thresholdPercent) || thresholdPercent <= 0 || thresholdPercent > 100
|
|
167
|
+
|| typeof expiresAt !== 'number' || !Number.isFinite(expiresAt) || expiresAt <= 0)
|
|
168
|
+
throw new Error('HQ Codex 미러 계정 항목이 잘못됐다');
|
|
169
|
+
seen.add(account);
|
|
170
|
+
return { account, usedPercent: usedPercent as number | null, thresholdPercent, expiresAt };
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Do not plan a Pod against an access token that might expire while it starts and runs. */
|
|
175
|
+
export function freshOwnerCodexMirrorAccounts(accounts: readonly OwnerCodexMirrorAccount[], now = Date.now()): OwnerCodexMirrorAccount[] {
|
|
176
|
+
return accounts.filter(({ expiresAt }) => expiresAt > now + 3 * 60 * 60 * 1000);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function selectOwnerCodexMirrorCandidates(candidates: readonly RotationCandidate[], accounts: readonly OwnerCodexMirrorAccount[]): RotationCandidate[] {
|
|
180
|
+
const selected = accounts.flatMap(({ account, usedPercent }) => ownerCodexMirrorCandidate(candidates, account, usedPercent ?? undefined));
|
|
181
|
+
if (selected.length !== accounts.length) throw new Error('HQ Codex 미러 계정 일부가 원격 auth-store 후보에 없다');
|
|
182
|
+
return selected;
|
|
183
|
+
}
|
|
184
|
+
|
|
116
185
|
/** Job 마다 다음 계정 — 잔량 순으로 돌려 가며. 쓸 계정이 없으면 만들 때 이유를 대고 던진다. */
|
|
117
186
|
export function makePodAccountBroker(plan: PodAccountPlan): () => string {
|
|
118
187
|
if (plan.usable.length === 0) {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
// BEDROCK-PROVIDER ② (0.2.24) — bedrock 은 «이름 있는 AWS Secret» 이 클러스터에 있을 때만 뜬다(pod-bedrock-child.ts · 발사 전 거부).
|
|
11
11
|
// ZAI-POD-CHILD (0.2.24) — glm 은 Z.ai GLM Coding Plan(정액 구독) · «이름 있는 ZAI Secret» 이 클러스터에 있을 때만 뜬다(pod-zai-child.ts · 발사 전 거부 · 동시 상한 넘치면 정책대로).
|
|
12
|
-
export const POD_CHILD_PROVIDERS = ['openai-codex', 'grok', 'openrouter', 'anthropic', 'bedrock', 'glm'] as const;
|
|
12
|
+
export const POD_CHILD_PROVIDERS = ['openai-codex', 'grok', 'openrouter', 'opengateway', 'anthropic', 'bedrock', 'glm'] as const;
|
|
13
13
|
export type PodChildProvider = typeof POD_CHILD_PROVIDERS[number];
|
|
14
14
|
|
|
15
15
|
/** 사람이 쓰는 별칭 → 정식 이름. */
|
|
@@ -17,9 +17,10 @@ import { getDefaultLogStore, type LogStore } from '../../mss/logging/log-store.j
|
|
|
17
17
|
import { podBunCacheVolume } from './pod-bun-cache.js';
|
|
18
18
|
import { POD_JOB_TTL_AFTER_FINISHED_SECONDS } from './pod-lease.js';
|
|
19
19
|
import { podHostDirsCheckScript, podInstallSlotsVolume, prepareHostDirsOnce, type HostDirsPrepResult, podHostDirsScript } from './pod-install-slots.js';
|
|
20
|
-
import { type PodPoolMember, PodPoolScheduler, resolvePodPoolSpec, parsePodPool, checkPodPool, syncPoolImages, type PoolKubectl } from './pod-pool.js';
|
|
20
|
+
import { type PodPoolMember, PodPoolScheduler, resolvePodPoolSpec, parsePodPool, checkPodPool, syncPoolImages, registryImageRef, type PoolKubectl } from './pod-pool.js';
|
|
21
21
|
import { podSkillsDigest, readSkillEnvFiles, resolvePodSkills } from './pod-skills.js';
|
|
22
22
|
import { podSourceScript, type PodSource } from './pod-source-receive.js';
|
|
23
|
+
import { podProvenanceMetadata, type PodProvenance } from './pod-provenance.js';
|
|
23
24
|
import { seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
|
|
24
25
|
import {
|
|
25
26
|
POD_CHILD_REQUESTS,
|
|
@@ -201,6 +202,8 @@ if [ -d "$HOME/outbox" ]; then
|
|
|
201
202
|
fi`;
|
|
202
203
|
|
|
203
204
|
export interface PodCommandJobInput {
|
|
205
|
+
provenance?: Partial<PodProvenance>;
|
|
206
|
+
provenanceGate?: boolean;
|
|
204
207
|
/** POD1 — this launch's own label; cleanup selects by it, never by name alone. */
|
|
205
208
|
launch?: string;
|
|
206
209
|
name: string;
|
|
@@ -236,8 +239,21 @@ function bashSingleQuote(value: string): string {
|
|
|
236
239
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
function assertGateProvenanceException(gate: boolean | undefined, provenance: Partial<PodProvenance> | undefined,
|
|
243
|
+
clone: boolean | undefined, source: PodSource | undefined): void {
|
|
244
|
+
if (!gate) return;
|
|
245
|
+
const shardEntrance = process.env.ELANOUS_RELEASE_ENTRANCE?.trim() || 'release-run';
|
|
246
|
+
const shard = provenance?.kind === 'gate-shard' && provenance.entrance === shardEntrance;
|
|
247
|
+
const recheck = provenance?.kind === 'gate-recheck' && provenance.entrance === 'release-recheck';
|
|
248
|
+
if (!(shard || recheck) || clone !== true || source?.kind !== 'commit') {
|
|
249
|
+
throw new Error('pod provenance gate exception requires a release shard/recheck commit Job');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
239
253
|
/** 명령 Job 매니페스트. `skills`·`llm` 을 안 주면 Secret 키를 하나도 참조하지 않는다. */
|
|
240
254
|
export function podCommandJobManifest(o: PodCommandJobInput): Record<string, unknown> {
|
|
255
|
+
assertGateProvenanceException(o.provenanceGate, o.provenance, o.clone, o.source);
|
|
256
|
+
const provenance = podProvenanceMetadata(o.provenance, o.provenanceGate);
|
|
241
257
|
const skillNames = [...new Set(o.skills.map((s) => s.trim()).filter(Boolean))];
|
|
242
258
|
for (const name of skillNames) {
|
|
243
259
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(name)) throw new Error(`pod command skill name rejected: ${name}`);
|
|
@@ -284,13 +300,13 @@ export function podCommandJobManifest(o: PodCommandJobInput): Record<string, unk
|
|
|
284
300
|
return {
|
|
285
301
|
apiVersion: 'batch/v1',
|
|
286
302
|
kind: 'Job',
|
|
287
|
-
metadata: { name: o.name, namespace: o.namespace, labels: { 'elanous.substrate': 'pod', 'elanous.job': o.name, 'elanous.kind': 'command', ...(o.launch ? { 'elanous.launch': o.launch } : {}) } },
|
|
303
|
+
metadata: { name: o.name, namespace: o.namespace, labels: { 'elanous.substrate': 'pod', 'elanous.job': o.name, 'elanous.kind': 'command', ...(o.launch ? { 'elanous.launch': o.launch } : {}), ...provenance?.labels }, ...(provenance ? { annotations: provenance.annotations } : {}) },
|
|
288
304
|
spec: {
|
|
289
305
|
backoffLimit: 0,
|
|
290
306
|
ttlSecondsAfterFinished: POD_JOB_TTL_AFTER_FINISHED_SECONDS,
|
|
291
307
|
activeDeadlineSeconds: o.deadlineSeconds,
|
|
292
308
|
template: {
|
|
293
|
-
metadata: { labels: { 'elanous.job': o.name, 'elanous.kind': 'command', ...(o.launch ? { 'elanous.launch': o.launch } : {}) } },
|
|
309
|
+
metadata: { labels: { 'elanous.job': o.name, 'elanous.kind': 'command', ...(o.launch ? { 'elanous.launch': o.launch } : {}), ...provenance?.labels }, ...(provenance ? { annotations: provenance.annotations } : {}) },
|
|
294
310
|
spec: {
|
|
295
311
|
restartPolicy: 'Never',
|
|
296
312
|
securityContext: { runAsUser: 1000, fsGroup: 1000 },
|
|
@@ -306,6 +322,7 @@ export function podCommandJobManifest(o: PodCommandJobInput): Record<string, unk
|
|
|
306
322
|
...(o.runId ? [{ name: 'ELANOUS_RUN_ID', value: o.runId }] : []),
|
|
307
323
|
{ name: 'ELANOUS_SUBSTRATE', value: 'pod' },
|
|
308
324
|
{ name: 'ELANOUS_POD_NAME', valueFrom: { fieldRef: { fieldPath: 'metadata.name' } } },
|
|
325
|
+
...(provenance?.env ?? []),
|
|
309
326
|
...(tmpfs ? [{ name: 'TMPDIR', value: POD_TMPFS_MOUNT_PATH }] : []),
|
|
310
327
|
],
|
|
311
328
|
...(secretKeys || o.hostMirror || hostDirMounts.length || tmpfs ? { volumeMounts: [
|
|
@@ -382,6 +399,9 @@ export interface PodCommandResult {
|
|
|
382
399
|
}
|
|
383
400
|
|
|
384
401
|
export interface RunPodCommandOptions {
|
|
402
|
+
provenance?: Partial<PodProvenance>;
|
|
403
|
+
/** Release gate keeps availability: missing required identity becomes unknown and emits a warning. */
|
|
404
|
+
provenanceGate?: boolean;
|
|
385
405
|
command: readonly string[];
|
|
386
406
|
/** pod run opt-in; other runPodCommand callers keep their existing Job script. */
|
|
387
407
|
returnLogs?: boolean;
|
|
@@ -434,6 +454,9 @@ export interface RunPodCommandOptions {
|
|
|
434
454
|
checkPool?: typeof checkPodPool;
|
|
435
455
|
syncImages?: typeof syncPoolImages;
|
|
436
456
|
imageCommit?: string | null;
|
|
457
|
+
/** Shelf: require this exact registry tag; never fall back to a mutable local image. */
|
|
458
|
+
shelfImage?: string;
|
|
459
|
+
shelfLookup?: typeof registryImageRef;
|
|
437
460
|
readSkillEnv?: (skills: readonly string[]) => Record<string, string>;
|
|
438
461
|
grokCredentials?: () => { grokAuth?: string; grokApiKey?: string; ghToken: string };
|
|
439
462
|
artifactsRoot?: string;
|
|
@@ -510,6 +533,9 @@ function awaitPodCommandAbort<T>(pending: Promise<T>, signal?: AbortSignal): Pro
|
|
|
510
533
|
|
|
511
534
|
/** 풀 자리 · 이미지 판 · Job 적용 · 완료 대기 · 산출 회수 · Secret 정리. */
|
|
512
535
|
export async function runPodCommand(options: RunPodCommandOptions): Promise<PodCommandResult> {
|
|
536
|
+
// A non-gate Job must have its owner before a pool lease, Secret, or Job is created.
|
|
537
|
+
assertGateProvenanceException(options.provenanceGate, options.provenance, options.clone, options.source);
|
|
538
|
+
const provenance = podProvenanceMetadata(options.provenance, options.provenanceGate);
|
|
513
539
|
const nowMs = options.nowMs ?? Date.now;
|
|
514
540
|
const ensureLive = () => {
|
|
515
541
|
if (options.signal?.aborted) throw options.signal.reason ?? new Error('pod command aborted');
|
|
@@ -521,11 +547,15 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
521
547
|
const skills = [...new Set((options.skills ?? []).map((s) => s.trim()).filter(Boolean))];
|
|
522
548
|
const llm = options.llm;
|
|
523
549
|
const log = options.log ?? ((c, e, d) => debug.log(c, e, d));
|
|
550
|
+
if (provenance.missing.length) log('pod.provenance', 'missing-gate-fields', { missing: provenance.missing });
|
|
524
551
|
const baseKubectl = options.kubectl ?? ((args: readonly string[], input?: string) =>
|
|
525
552
|
defaultKubectl(args, input, options.signal ? POD_COMMAND_CANCEL_KUBECTL_TIMEOUT_MS : undefined));
|
|
526
553
|
const sleep = options.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));
|
|
527
554
|
const namespace = options.namespace ?? 'elanous-test';
|
|
528
555
|
const image = options.image ?? podCommandImageFor(skills, options.clone === true, options.lite === true);
|
|
556
|
+
if (options.shelfImage && (options.image !== options.shelfImage || !options.imageCommit || !options.clone || options.source?.kind !== 'commit' || options.source.sha !== options.imageCommit)) {
|
|
557
|
+
throw new Error('pod shelf: image and source commit must match');
|
|
558
|
+
}
|
|
529
559
|
const memoryLimit = options.memoryLimit ?? (image === POD_LITE_IMAGE ? POD_LITE_MEMORY_LIMIT : undefined);
|
|
530
560
|
const repoUrl = options.repoUrl ?? 'https://github.com/ElanvitalAI/elanous';
|
|
531
561
|
const deadlineSeconds = options.deadlineSeconds ?? POD_COMMAND_DEADLINE_SECONDS;
|
|
@@ -579,6 +609,7 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
579
609
|
if (member && pool) pool.release(member);
|
|
580
610
|
ensureLive();
|
|
581
611
|
}
|
|
612
|
+
if (options.shelfImage && !member) throw new Error('pod shelf: remote pool member required');
|
|
582
613
|
const currentContext = member || options.kubectl ? null : baseKubectl(['config', 'current-context']);
|
|
583
614
|
const context = member?.context ?? (currentContext?.status === 0 ? currentContext.stdout.trim() : '');
|
|
584
615
|
const kubectlRaw: Kubectl = (args, stdin) => baseKubectl(context ? ['--context', context, ...args] : [...args], stdin);
|
|
@@ -592,7 +623,8 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
592
623
|
if (!context && !options.kubectl) throw new Error('pod command: kubectl context 를 확인할 수 없다');
|
|
593
624
|
let grokAuth: string | undefined;
|
|
594
625
|
if (llm === 'grok') {
|
|
595
|
-
|
|
626
|
+
// POD-GROK-VALIDITY-FIT — this Job's deadline is not fitted to the token, so the copy must outlive the whole Job.
|
|
627
|
+
const creds = (options.grokCredentials ?? (() => hostGrokCredentials({ env, apiKeyOptIn: false, minValidityMs: deadlineSeconds * 1000 })))();
|
|
596
628
|
if (!creds.grokAuth) throw new Error('grok: 구독 자격 없음 · API 키 opt-in 꺼짐 또는 키 없음');
|
|
597
629
|
let parsed: unknown;
|
|
598
630
|
try { parsed = JSON.parse(creds.grokAuth); } catch { throw new Error('grok: Pod 구독 자격 JSON 이 아니다'); }
|
|
@@ -616,10 +648,16 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
616
648
|
const localSkillsDigest = options.kubectl ? null : image === POD_LITE_IMAGE
|
|
617
649
|
? podSkillsDigest(POD_NETWORK_SKILLS, resolve(import.meta.dir, '../../../skills')).digest
|
|
618
650
|
: podSkillsDigest(resolvePodSkills(env).skills).digest;
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
651
|
+
if (options.shelfImage) {
|
|
652
|
+
const found = (options.shelfLookup ?? registryImageRef)(member, imageCommit);
|
|
653
|
+
if (found !== options.shelfImage) throw new Error(`pod shelf: selected image unavailable on ${member.context}`);
|
|
654
|
+
member = { ...member, imageRef: found };
|
|
655
|
+
} else {
|
|
656
|
+
const syncs = await awaitPodCommandAbort((options.syncImages ?? syncPoolImages)([member], image, imageCommit, { localSkillsDigest }), options.signal);
|
|
657
|
+
const synced = syncs.get(member.context);
|
|
658
|
+
if (synced && !synced.ok) throw new Error(`pod command: 이미지 판을 못 맞췄다: ${synced.detail}`);
|
|
659
|
+
if (synced?.imageRef) member = { ...member, imageRef: synced.imageRef };
|
|
660
|
+
}
|
|
623
661
|
}
|
|
624
662
|
const imageRef = member?.imageRef;
|
|
625
663
|
if (!imageRef) log('pod.command-job', 'image-fallback-local', { reason: !member ? 'no-pool-member' : !imageCommit ? 'image-commit-unavailable' : 'registry-tag-unavailable' });
|
|
@@ -660,6 +698,7 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
660
698
|
}
|
|
661
699
|
const manifest = podCommandJobManifest({
|
|
662
700
|
name, namespace, launch, image: imageRef ?? image,
|
|
701
|
+
provenance: options.provenance, provenanceGate: options.provenanceGate,
|
|
663
702
|
...(imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}),
|
|
664
703
|
repoUrl, command, skills, ...(options.returnLogs ? { returnLogs: true } : {}), ...(llm ? { llm } : {}), ...(options.clone ? { clone: true } : {}),
|
|
665
704
|
...(options.source ? { source: options.source } : {}), ...(hostMirror ? { hostMirror } : {}), ...(bunCache ? { bunCache } : {}), ...(installSlots ? { installSlots } : {}), ...(memoryLimit ? { memoryLimit } : {}), ...(options.cpu ? { cpu: options.cpu } : {}), ...(options.tmpfsSizeLimit ? { tmpfsSizeLimit: options.tmpfsSizeLimit } : {}), deadlineSeconds,
|
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
* 이미지는 표준판(elanous-harness)만 — 이 발사 경로는 lite 를 쓰지 않는다.
|
|
15
15
|
*/
|
|
16
16
|
import { spawnSync } from 'node:child_process';
|
|
17
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
17
20
|
import { SPAWN_SYNC_MAX_BUFFER } from '../../util/spawn-sync-output.js';
|
|
18
21
|
import { debug } from '../../debug/log.js';
|
|
19
|
-
import { memberHasRegistry, registryImageRef, type RemoteRun } from './pod-pool.js';
|
|
22
|
+
import { memberHasRegistry, registryImageRef, syncPoolImages, parsePodPool, type PodPoolMember, type RemoteRun } from './pod-pool.js';
|
|
20
23
|
|
|
21
24
|
const POD_IMAGE = 'elanous-harness';
|
|
22
25
|
|
|
@@ -59,6 +62,91 @@ export function resolvePodImageSource(
|
|
|
59
62
|
return { kind: 'pinned', ref: podImageRef(registry, commit), commit, registry };
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
export interface PodShelfImage { readonly commit: string; readonly image: string; readonly action: 'fresh' | 'built' }
|
|
66
|
+
|
|
67
|
+
export function resolvePodShelfRef(ref: string, cwd = process.cwd(), exec = spawnSync): string {
|
|
68
|
+
const requested = ref.trim();
|
|
69
|
+
if (!requested || requested.startsWith('-') || /[\s\x00-\x1f]/u.test(requested)) throw new Error('pod shelf: invalid ref');
|
|
70
|
+
const spec = /^#?(\d+)$/u.exec(requested);
|
|
71
|
+
if (spec) {
|
|
72
|
+
const pr = exec('gh', ['pr', 'view', spec[1]!, '--json', 'headRefOid', '--jq', '.headRefOid'], { cwd, encoding: 'utf8', timeout: 30_000 });
|
|
73
|
+
const sha = String(pr.stdout ?? '').trim().toLowerCase();
|
|
74
|
+
if (pr.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: PR head unavailable: ${requested}`);
|
|
75
|
+
return sha;
|
|
76
|
+
}
|
|
77
|
+
const git = exec('git', ['rev-parse', '--verify', `${requested}^{commit}`], { cwd, encoding: 'utf8', timeout: 30_000 });
|
|
78
|
+
const sha = String(git.stdout ?? '').trim().toLowerCase();
|
|
79
|
+
if (git.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: ref unavailable: ${requested}`);
|
|
80
|
+
return sha;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Checkout only the requested commit; syncPoolImages retains its per-host build lock and SHA12 registry check. */
|
|
84
|
+
export async function putPodShelfImage(ref: string, pool: string, deps: {
|
|
85
|
+
resolve?: (ref: string) => string;
|
|
86
|
+
sync?: typeof syncPoolImages;
|
|
87
|
+
checkout?: (commit: string, dir: string) => void;
|
|
88
|
+
tempDir?: () => string;
|
|
89
|
+
remove?: (dir: string) => void;
|
|
90
|
+
hasRegistry?: (member: PodPoolMember) => boolean;
|
|
91
|
+
} = {}): Promise<PodShelfImage> {
|
|
92
|
+
const members = parsePodPool(pool);
|
|
93
|
+
if (members.length !== 1 || !members[0]!.sshHost) throw new Error('pod shelf: one remote registry pool member is required');
|
|
94
|
+
const member: PodPoolMember = members[0]!;
|
|
95
|
+
if (!(deps.hasRegistry ?? memberHasRegistry)(member)) throw new Error('pod shelf: remote registry unavailable');
|
|
96
|
+
const commit = (deps.resolve ?? resolvePodShelfRef)(ref);
|
|
97
|
+
if (!/^[0-9a-f]{40}$/u.test(commit)) throw new Error('pod shelf: full commit required');
|
|
98
|
+
const registry = member.registry ?? podImageRegistry();
|
|
99
|
+
const image = podImageRef(registry, commit);
|
|
100
|
+
if (!deps.sync && registryImageRef(member, commit) === image) return { commit, image, action: 'fresh' };
|
|
101
|
+
const dir = (deps.tempDir ?? (() => mkdtempSync(join(tmpdir(), 'pod-shelf-'))))();
|
|
102
|
+
try {
|
|
103
|
+
if (deps.checkout) deps.checkout(commit, dir);
|
|
104
|
+
else {
|
|
105
|
+
const clone = spawnSync('git', ['clone', '-q', '--no-checkout', process.cwd(), dir], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
106
|
+
if (clone.status !== 0) throw new Error(`pod shelf: clone failed: ${clone.stderr}`);
|
|
107
|
+
const fetch = spawnSync('git', ['-C', dir, 'fetch', '-q', 'origin', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
108
|
+
if (fetch.status !== 0) {
|
|
109
|
+
const remote = spawnSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8', timeout: 10_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
110
|
+
if (remote.status !== 0) throw new Error(`pod shelf: fetch failed: ${fetch.stderr}`);
|
|
111
|
+
const fromOrigin = spawnSync('git', ['-C', dir, 'fetch', '-q', String(remote.stdout).trim(), commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
112
|
+
if (fromOrigin.status !== 0) throw new Error(`pod shelf: fetch failed: ${fromOrigin.stderr}`);
|
|
113
|
+
}
|
|
114
|
+
const checkout = spawnSync('git', ['-C', dir, 'checkout', '--detach', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
115
|
+
if (checkout.status !== 0) throw new Error(`pod shelf: checkout failed: ${checkout.stderr}`);
|
|
116
|
+
}
|
|
117
|
+
const sync = deps.sync ?? syncPoolImages;
|
|
118
|
+
const results = await sync([member], 'elanous-harness:local', commit, {
|
|
119
|
+
buildScript: join(dir, 'docker/harness/build.sh'),
|
|
120
|
+
...(deps.sync ? {} : { ship: () => ({ ok: false, action: 'failed' as const, detail: 'shelf build failed; local image fallback prohibited' }) }),
|
|
121
|
+
remoteBuild: deps.sync ? undefined : async (host, cluster, registry) => {
|
|
122
|
+
const { spawn } = await import('node:child_process');
|
|
123
|
+
return new Promise((done) => {
|
|
124
|
+
const child = spawn('bash', [join(dir, 'docker/harness/build.sh')], { env: { ...process.env, ELANOUS_BUILD_REMOTE: host, ELANOUS_L2_CLUSTER: cluster, ...(registry ? { ELANOUS_BUILD_REGISTRY: registry } : {}) }, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
125
|
+
let output = '';
|
|
126
|
+
child.stdout.on('data', (chunk) => { output += chunk; });
|
|
127
|
+
child.stderr.on('data', (chunk) => { output += chunk; });
|
|
128
|
+
child.on('close', (code) => done({ ok: code === 0, detail: output.slice(-300) }));
|
|
129
|
+
child.on('error', (error) => done({ ok: false, detail: error.message }));
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
const result = results.get(member.context);
|
|
134
|
+
if (!result?.ok || result.imageRef !== image) throw new Error(`pod shelf: image unavailable: ${result?.detail ?? image}`);
|
|
135
|
+
return { commit, image, action: result.action === 'fresh' ? 'fresh' : 'built' };
|
|
136
|
+
} finally { (deps.remove ?? ((path) => rmSync(path, { recursive: true, force: true })))(dir); }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function listPodShelfImages(pool: string, run: RemoteRun): string[] {
|
|
140
|
+
const member = parsePodPool(pool)[0];
|
|
141
|
+
if (!member?.sshHost) throw new Error('pod shelf: remote pool member required');
|
|
142
|
+
const registry = member.registry ?? podImageRegistry();
|
|
143
|
+
const port = registry.slice(registry.lastIndexOf(':') + 1);
|
|
144
|
+
const result = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${port}/v2/elanous-harness/tags/list 2>/dev/null`);
|
|
145
|
+
if (result.status !== 0) throw new Error(`pod shelf: registry unavailable: ${result.stderr}`);
|
|
146
|
+
const tags: unknown = JSON.parse(result.stdout).tags;
|
|
147
|
+
return Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string' && /^[0-9a-f]{12}$/u.test(tag)).map((tag) => `${registry}/elanous-harness:${tag}`) : [];
|
|
148
|
+
}
|
|
149
|
+
|
|
62
150
|
export function podImageMissingMessage(ref: string): string {
|
|
63
151
|
return `기준 이미지 ${ref} 가 레지스트리에 없다 — 레일이 굽기 전이다`;
|
|
64
152
|
}
|
|
@@ -236,6 +236,10 @@ export interface ExternalGitHubProbe {
|
|
|
236
236
|
githubHttps: boolean | null;
|
|
237
237
|
measuredAt: string | null;
|
|
238
238
|
reason: string | null;
|
|
239
|
+
/** Name of the disposable Pod for matching this reading with its Kubernetes logs. */
|
|
240
|
+
podName?: string;
|
|
241
|
+
/** Unmodified stdout from `kubectl logs` for this Pod (only present when readable). */
|
|
242
|
+
podLog?: string;
|
|
239
243
|
}
|
|
240
244
|
const DNS_CACHE_MS = 10 * 60_000;
|
|
241
245
|
const DNS_STALE_OK_MS = 30 * 60_000;
|
|
@@ -261,9 +265,11 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
261
265
|
if (typeof record?.at !== 'number' || now() < record.at || now() - record.at >= 60_000) return null;
|
|
262
266
|
if (typeof record.measuredAt !== 'string' || ![true, false].includes(record.externalDns as boolean) ||
|
|
263
267
|
![true, false, null].includes(record.githubHttps as boolean | null) ||
|
|
264
|
-
!(record.reason === null || typeof record.reason === 'string')
|
|
268
|
+
!(record.reason === null || typeof record.reason === 'string') ||
|
|
269
|
+
typeof record.podName !== 'string' || typeof record.podLog !== 'string') return null;
|
|
265
270
|
return { externalDns: record.externalDns as boolean, githubHttps: record.githubHttps as boolean | null,
|
|
266
|
-
measuredAt: record.measuredAt, reason: record.reason as string | null
|
|
271
|
+
measuredAt: record.measuredAt, reason: record.reason as string | null,
|
|
272
|
+
podName: record.podName, podLog: record.podLog };
|
|
267
273
|
} catch { return null; }
|
|
268
274
|
};
|
|
269
275
|
const fresh = cached();
|
|
@@ -285,6 +291,7 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
285
291
|
const shared = cached();
|
|
286
292
|
if (shared) return shared;
|
|
287
293
|
const result = runPoolGitHubProbe(context, kubectl, new Date(now()).toISOString());
|
|
294
|
+
debug.log('pod.lease', 'github-egress-probe', { context, ...result });
|
|
288
295
|
if (result.measuredAt !== null) {
|
|
289
296
|
const temp = `${cache}.${randomUUID()}.tmp`;
|
|
290
297
|
try { writeFileSync(temp, JSON.stringify({ ...result, at: now() }), { mode: 0o600 }); renameSync(temp, cache); }
|
|
@@ -300,16 +307,18 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
300
307
|
function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: string): ExternalGitHubProbe {
|
|
301
308
|
const name = `elanous-egress-${randomUUID().slice(0, 12)}`;
|
|
302
309
|
const base = ['--context', context, '--request-timeout=15s'];
|
|
303
|
-
const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason });
|
|
304
310
|
let created = false;
|
|
311
|
+
const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason,
|
|
312
|
+
...(created ? { podName: name } : {}) });
|
|
305
313
|
try {
|
|
306
314
|
const manifest = JSON.stringify({ apiVersion: 'v1', kind: 'Pod', metadata: { name, namespace: 'elanous-test', labels: { 'elanous.probe': 'github-egress' } }, spec: {
|
|
307
315
|
restartPolicy: 'Never', activeDeadlineSeconds: 35, automountServiceAccountToken: false,
|
|
308
316
|
containers: [{ name: 'probe', image: 'busybox:1.36', command: ['sh', '-c',
|
|
309
|
-
'if nslookup github.com
|
|
317
|
+
'if nslookup github.com 2>&1; then echo EXTERNAL_DNS_OK; if wget -T 8 -O /dev/null https://github.com/ 2>&1; then echo GITHUB_HTTPS_OK; else echo GITHUB_HTTPS_FAILED; fi; else echo EXTERNAL_DNS_FAILED; fi'],
|
|
310
318
|
resources: { requests: { cpu: '0', memory: '16Mi' }, limits: { cpu: '100m', memory: '64Mi' } } }],
|
|
311
319
|
} });
|
|
312
|
-
|
|
320
|
+
const createdPod = kubectl([...base, 'create', '-f', '-'], manifest);
|
|
321
|
+
if (createdPod.status !== 0) return unknown(`probe create failed${createdPod.stderr.trim() ? `: ${createdPod.stderr.trim().split('\n').pop()!.slice(0, 160)}` : ''}`);
|
|
313
322
|
created = true;
|
|
314
323
|
const waited = kubectl([...base, '-n', 'elanous-test', 'wait', '--for=jsonpath={.status.phase}=Succeeded', `pod/${name}`, '--timeout=25s']);
|
|
315
324
|
const podResult = kubectl([...base, '-n', 'elanous-test', 'get', `pod/${name}`, '-o', 'json']);
|
|
@@ -327,10 +336,10 @@ function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: s
|
|
|
327
336
|
const httpsOk = markers.includes('GITHUB_HTTPS_OK');
|
|
328
337
|
const httpsFail = markers.includes('GITHUB_HTTPS_FAILED');
|
|
329
338
|
if (dnsFail && !dnsOk && !httpsOk && !httpsFail)
|
|
330
|
-
return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed' };
|
|
339
|
+
return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed', podName: name, podLog: logs.stdout };
|
|
331
340
|
if (dnsOk && !dnsFail && httpsOk !== httpsFail)
|
|
332
|
-
return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null };
|
|
333
|
-
return unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout');
|
|
341
|
+
return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null, podName: name, podLog: logs.stdout };
|
|
342
|
+
return { ...unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout'), podLog: logs.stdout };
|
|
334
343
|
} catch { return unknown('probe failed'); }
|
|
335
344
|
finally {
|
|
336
345
|
if (created) try { kubectl([...base, '-n', 'elanous-test', 'delete', `pod/${name}`, '--ignore-not-found=true', '--wait=false']); }
|