elanous 0.2.28 → 0.2.29
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/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 058a98ba.7eb28d5e6dc03565.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4565-67e4c620597965c8.js → 1015-9cba22a5a4554797.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 1142.65d002789ab3af7d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +34 -0
- package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1516.dfaceff3fd2d0e0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +286 -0
- package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1782-59db1b5aa06df38a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 1852.7f7b53991fcb99ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +36 -0
- package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +64 -0
- package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 285adb1a.5654e605dddf86d2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +115 -0
- package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3160-95c96f4d2a21dd26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +90 -0
- package/apps/pwa/out/_next/static/chunks/328bb3ab-6628a1114fe3fb3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 3396-97b97928c49190c9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 3403.7199205e65124486.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/419.736c0d6f426249a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → 425cfc4d.fb91158e3971c39f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 46bd8bea.2f4b4099172fcdb7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 4759.1f76713aefb87db5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +62 -0
- package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +27 -0
- package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 5591.a35e7a217734a8b9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 6013-2f769370d8b4c2c6.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 6534.1ab00f370db7b105.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +148 -0
- package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +149 -0
- package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +79 -0
- package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 6767.1fcfc9b8be83975f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6776.06ff1e3b464cc607.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 6853.cc5174a9dee59593.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +287 -0
- package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 7375.050ea0d72968e49f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +74 -0
- package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7725-4f83d5541fbdb81b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8332.6f0f49df772e163b.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 8398.73a19b39715eda04.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 8471.8d2a8c74f09c36ff.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 8767-2f6a634f5abeaa01.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +32 -0
- package/apps/pwa/out/_next/static/chunks/8795.32573a185af18c7b.js +41 -0
- package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 9143.ff14585db1d275ff.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9907.49be0fcadaf214b5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{973cbf1b.3bbcf2b41548eca7.js → a435ad95.577add051b4facb2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-fa46d4588e8442c2.js → page-a5635eba0d73b84e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/{page-66ad46ed0279feb9.js → page-86feb08080261a2f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-646b50f63b6fe732.js → page-8aaa6dedc4c10dfb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-6f131b51193a36f9.js → page-33bf667a5fb297bf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29900ed0011b2c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → bc324b7c.02a09dd93f6a399b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +1 -0
- package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +122 -0
- package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.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/graphs/release/release-loop.yaml +6 -2
- package/package.json +1 -1
- package/plugins/agent-team/agents/research.md +1 -0
- package/scripts/ci-typecheck-changed.ts +3 -2
- package/scripts/coord-channel-watch.sh +26 -6
- package/scripts/coord-role-pack.ts +143 -0
- package/scripts/lib/morning-report-options.ts +41 -0
- package/scripts/pr-land-extra-remote-gates.ts +49 -0
- package/scripts/release-loop/gate-batch-safe.ts +23 -0
- package/scripts/release-loop/gate-history.ts +422 -0
- package/scripts/release-loop/gate-node.ts +310 -46
- package/scripts/release-loop/gate-triage-node.ts +190 -0
- package/scripts/release-loop/spawn-lane.ts +68 -0
- package/scripts/release-loop/tui-node-checks.ts +23 -0
- package/scripts/release-loop/version-node.ts +62 -4
- package/scripts/test-deterministic.ts +41 -12
- package/scripts/usage-rollup.ts +11 -3
- package/src/acp/core-turn-bridge.ts +98 -22
- package/src/acp/elanous-extensions.ts +2 -0
- package/src/acp/server.ts +2 -0
- package/src/agent/ref-grounding.ts +18 -0
- package/src/agent-substrate/pr-reviewer.ts +29 -21
- package/src/budget/pty-usage-reemit.ts +7 -0
- package/src/budget/run-usage-rollup.ts +9 -0
- package/src/budget/usage-daily-store.ts +98 -0
- package/src/capture/tui-self-report.ts +22 -4
- package/src/chat/index.ts +31 -10
- package/src/chat/pickers/modal-runtime.ts +1 -0
- package/src/chat/pickers/modals.ts +3 -1
- package/src/chat/turn-typeahead.ts +123 -16
- package/src/cli/dashboard-name-flag.ts +48 -0
- package/src/cli/doctor-cli.ts +80 -0
- package/src/cli/log-event-names.ts +12 -0
- package/src/cli/msg-cli.ts +45 -2
- package/src/cli/pr-cli.ts +382 -105
- package/src/cli/pr-land-heavy-remote.ts +233 -0
- package/src/cli/pr-land-overlap-evidence.ts +104 -5
- package/src/cli/pty-takeover-cli.ts +125 -16
- package/src/cli/release-cli.ts +44 -2
- package/src/cli/remote-resolve.ts +2 -1
- package/src/cli/seat-cli.ts +26 -16
- package/src/cli/tasks-cli.ts +8 -2
- package/src/cli/usage-cli.ts +146 -12
- package/src/cli/usage-daily-cli.ts +84 -0
- package/src/context-bus/context-now.ts +82 -5
- package/src/core-turn/auth-rejected-notice.ts +41 -0
- package/src/core-turn/run-core-turn.ts +13 -2
- package/src/core-turn/run-goal-loop.ts +17 -1
- package/src/core-turn/short-question.ts +45 -12
- package/src/core-turn/types.ts +7 -0
- package/src/dashboard/acp-active-model.ts +40 -0
- package/src/dashboard/auto-compact-runtime.ts +2 -0
- package/src/dashboard/boot-banner.ts +80 -0
- package/src/dashboard/dashboard-status-lines.ts +11 -0
- package/src/dashboard/detail-viewer-runtime.ts +15 -2
- package/src/dashboard/event-loop-stall-monitor.ts +4 -0
- package/src/dashboard/goal-loop-thinking.ts +16 -0
- package/src/dashboard/hitl-boot.ts +9 -4
- package/src/dashboard/index.ts +228 -387
- package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
- package/src/dashboard/input/chat-main-log-actions.ts +4 -0
- package/src/dashboard/input/chat-main-log-command.ts +12 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +172 -3
- package/src/dashboard/input/chat-main-session.ts +6 -2
- package/src/dashboard/input/chat-main-slash-command.ts +7 -0
- package/src/dashboard/input/chat-main-turn.ts +2 -1
- package/src/dashboard/input/compact-prepass-recovery.ts +97 -0
- package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
- package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
- package/src/dashboard/input/external-input-host.ts +45 -0
- package/src/dashboard/input/log-fold-binding.ts +18 -0
- package/src/dashboard/input/mouse-wiring.ts +17 -4
- package/src/dashboard/input/turn-steer-bridge.ts +94 -0
- package/src/dashboard/log-click-runtime.ts +5 -3
- package/src/dashboard/running-build-status.ts +74 -0
- package/src/dashboard/seat-boot-preamble.ts +113 -0
- package/src/dashboard/seat-local-instructions.ts +305 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +100 -28
- package/src/dashboard/slash-runtime/model-choices.ts +35 -0
- package/src/dashboard/term-slash-runtime.ts +15 -0
- package/src/dashboard/turn-preamble.ts +30 -2
- package/src/dashboard/turn-session-layers.ts +176 -0
- package/src/dashboard/turn-stream-formatter.ts +14 -6
- package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
- package/src/domains/release-tool.ts +8 -9
- package/src/domains/surface-events.ts +4 -1
- package/src/domains/watch-default-scheduler.ts +8 -9
- package/src/fold-stack.ts +24 -1
- package/src/git-fs/dirty.ts +32 -4
- package/src/git-fs/index.ts +43 -1
- package/src/graph-runner/runner.ts +1 -0
- package/src/harness/harness-gc.ts +32 -5
- package/src/index.ts +14 -1
- package/src/input/external-input-queue.ts +219 -0
- package/src/interactive-terminal-modal.ts +13 -0
- package/src/llm/route-decision.ts +25 -0
- package/src/llm-stream-retry-display.ts +59 -0
- package/src/llm.ts +253 -55
- package/src/log-entry.ts +3 -3
- package/src/log-pane/search.ts +29 -4
- package/src/loops/agent-reply.ts +256 -0
- package/src/loops/budget.ts +37 -7
- package/src/loops/loop-cli.ts +3 -2
- package/src/loops/msg-address.ts +57 -0
- package/src/loops/msg-wake.ts +282 -0
- package/src/loops/orchestrator/inbox.ts +60 -3
- package/src/loops/orchestrator/tick.ts +24 -4
- package/src/loops/registry.ts +42 -4
- package/src/memory.ts +20 -5
- package/src/native-tool-catalog.ts +125 -0
- package/src/nexus/api/http-server.ts +5 -0
- package/src/nexus/api/ops-api.ts +2 -0
- package/src/nexus/api/project-autopsy.ts +127 -0
- package/src/nexus/api/terminals.ts +3 -0
- package/src/nexus/api/workflow-approvals.ts +2 -0
- package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
- package/src/oauth/codex-account-store.ts +15 -3
- package/src/oauth/codex-billing-route.ts +31 -0
- package/src/ops/overview-collect.ts +19 -2
- package/src/panes/log-pane.ts +67 -8
- package/src/persona/presets.ts +44 -0
- package/src/plugins/maker/wizard-generate.ts +6 -4
- package/src/preview/terminal.ts +14 -1
- package/src/prompt-cache/types.ts +2 -0
- package/src/prompt-enhance/enhance.ts +24 -8
- package/src/prompt-library/universal-preamble.ts +273 -56
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/pty-shell/pty-manifest.ts +77 -5
- package/src/pty-shell/registry.ts +19 -2
- package/src/pty-shell/tui-run-state.ts +253 -0
- package/src/release-loop/light-rc.ts +28 -3
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/render.ts +5 -1
- package/src/seat-loop/seat-report.ts +42 -2
- package/src/self-dev/run-supervisor.ts +71 -5
- package/src/self-dev/shard-aggregate.ts +2 -0
- package/src/self-dev/shard-run.ts +23 -2
- package/src/self-health/signatures.ts +132 -0
- package/src/self-implement/doctor-visit.ts +118 -0
- package/src/self-implement/gate-cli.ts +11 -2
- package/src/self-implement/goal-author-decompose.ts +80 -16
- package/src/self-implement/goal-author.ts +114 -72
- package/src/self-implement/goal-authoring-grounding.ts +1 -1
- package/src/self-implement/goal-file-name.ts +65 -0
- package/src/self-implement/ground-goal.ts +2 -1
- package/src/self-implement/host-regate.ts +14 -0
- package/src/self-implement/review-mustfix-class.ts +115 -0
- package/src/self-implement/run-ledger.ts +111 -7
- package/src/self-implement/running-runs.ts +10 -6
- package/src/self-implement/self-implement-runtime.ts +32 -0
- package/src/session/pending-input.ts +62 -11
- package/src/session-runtime/index.ts +7 -1
- package/src/skills/tools/ops-ledger.ts +707 -0
- package/src/skills/tools/persistent-grounding.ts +47 -7
- package/src/skills/tools/shell.ts +117 -1
- package/src/status/bar.ts +32 -2
- package/src/status/status-provider-info.ts +58 -0
- package/src/task-agent/rejudge-on-head.ts +4 -1
- package/src/task-agent/remote-rejudge-bind.ts +34 -5
- package/src/task-agent/repair-cycle.ts +13 -0
- package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +63 -7
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +6 -11
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +76 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +107 -33
- package/src/terminal/session-registry.ts +6 -0
- package/src/thinking-line.ts +12 -3
- package/src/tool-runtime/index.ts +4 -0
- package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
- package/src/tool-runtime/ref-consult-runtime.ts +17 -2
- package/src/tool-runtime/run-shell-runtime.ts +4 -1
- package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
- package/src/tui.ts +5 -0
- package/src/user-config.ts +54 -6
- package/src/ux-sim/fake-llm.ts +29 -0
- package/src/ux-sim/in-process-cli.ts +175 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +0 -148
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +0 -34
- package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
- package/apps/pwa/out/_next/static/chunks/7752.5cbdd0b433c54af9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
- package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +0 -90
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +0 -79
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-ced0bcfc6542b3fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-cb249e81ed339318.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e117f801.e92bf10242653497.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
- package/src/dashboard/bench-slash-runtime.ts +0 -40
- package/src/dashboard/input/search-modal-router.ts +0 -9
- package/src/dashboard/modals/pane-key-router.ts +0 -27
- package/src/dashboard/view-slash-runtime.ts +0 -48
- /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_ssgManifest.js +0 -0
|
@@ -16,10 +16,11 @@ import { collectPodArtifacts } from './pod-artifact-return.js';
|
|
|
16
16
|
import { getDefaultLogStore, type LogStore } from '../../mss/logging/log-store.js';
|
|
17
17
|
import { podBunCacheVolume } from './pod-bun-cache.js';
|
|
18
18
|
import { POD_JOB_TTL_AFTER_FINISHED_SECONDS } from './pod-lease.js';
|
|
19
|
-
import {
|
|
19
|
+
import { podHostDirsScript, podInstallSlotsVolume } from './pod-install-slots.js';
|
|
20
20
|
import { type PodPoolMember, PodPoolScheduler, resolvePodPoolSpec, parsePodPool, checkPodPool, syncPoolImages, 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 { seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
|
|
23
24
|
import {
|
|
24
25
|
POD_CHILD_REQUESTS,
|
|
25
26
|
POD_JOB_DEADLINE_SECONDS,
|
|
@@ -132,13 +133,18 @@ export function tailBytes(text: string, maxBytes: number): string {
|
|
|
132
133
|
return `…[앞 ${bytes.length - maxBytes}바이트 생략]\n${cut.subarray(start).toString('utf8')}`;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
/** The isolation probe: wait until the NetworkPolicy blocks the host/prod daemons, then run `onPass` (default `exit 0`). */
|
|
137
|
+
function isolationGateScript(onPass = 'exit 0'): string {
|
|
138
|
+
return `ok=0
|
|
136
139
|
for i in $(seq 1 60); do
|
|
137
140
|
if curl -s -m 1 -o /dev/null http://host.orb.internal:31415/health || curl -s -m 1 -o /dev/null http://core.elanous-prod:8080/; then ok=0; else ok=$((ok+1)); fi
|
|
138
|
-
[ "$ok" -ge 3 ] && { echo "[gate] isolation enforced after \${i} probes";
|
|
141
|
+
[ "$ok" -ge 3 ] && { echo "[gate] isolation enforced after \${i} probes"; ${onPass}; }
|
|
139
142
|
sleep 0.5
|
|
140
143
|
done
|
|
141
144
|
echo "[gate] ISOLATION NOT ENFORCED within 30s"; exit 1`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const GATE = isolationGateScript();
|
|
142
148
|
|
|
143
149
|
/** Export the command's log store into the existing outbox return channel without changing the command exit status. */
|
|
144
150
|
const COMMAND_LOG_EXPORT = `if mkdir -p "$HOME/outbox/pod-logs" && elanous --test="$HOME/.elanous-test" logs --instance prod --since 12h --limit 20000 --json --json-data > "$HOME/outbox/pod-logs/logs.jsonl"; then
|
|
@@ -244,6 +250,10 @@ export function podCommandJobManifest(o: PodCommandJobInput): Record<string, unk
|
|
|
244
250
|
// A command may not end in LF; keep artifact markers on their own line for the existing parser.
|
|
245
251
|
...(o.returnLogs ? ["printf '\\n'", COMMAND_LOG_EXPORT] : []),
|
|
246
252
|
ARTIFACT_EMIT,
|
|
253
|
+
// GATE-POD-RESULT-MARKER: the last line says «the child is done» so the host need not wait for the Job condition
|
|
254
|
+
// (k3d on node-b flips it 90~550s late). Leading LF keeps it on its own line; the host strips exactly this tail.
|
|
255
|
+
// The token is this launch's random id — a command that prints the bare marker word cannot end the wait early.
|
|
256
|
+
`printf '\\n${podResultMarker(o.launch ?? o.name)} rc=%s\\n' "$rc"`,
|
|
247
257
|
'exit $rc',
|
|
248
258
|
].join('\n');
|
|
249
259
|
const secretKeys = grok || skillNames.length || o.clone === true;
|
|
@@ -261,8 +271,12 @@ export function podCommandJobManifest(o: PodCommandJobInput): Record<string, unk
|
|
|
261
271
|
restartPolicy: 'Never',
|
|
262
272
|
securityContext: { runAsUser: 1000, fsGroup: 1000 },
|
|
263
273
|
initContainers: [
|
|
264
|
-
|
|
265
|
-
|
|
274
|
+
// GATE-WARM-BOOT (10-15): ONE init container. Each extra container cost minutes on a loaded k3d node (the measured
|
|
275
|
+
// gap between a finished init script and the next container start), so the root host-dir hand-over runs inside
|
|
276
|
+
// the isolation init after the probe passes instead of as a second `host-dirs` container.
|
|
277
|
+
hostDirMounts.length
|
|
278
|
+
? { name: 'isolation-gate', image: o.image, imagePullPolicy: o.imagePullPolicy ?? 'Never', securityContext: { runAsUser: 0 }, command: ['bash', '-c'], args: [isolationGateScript(podHostDirsScript(hostDirMounts))], volumeMounts: hostDirMounts.map((mount) => ({ ...mount })) }
|
|
279
|
+
: { name: 'isolation-gate', image: o.image, imagePullPolicy: o.imagePullPolicy ?? 'Never', command: ['bash', '-c'], args: [GATE] },
|
|
266
280
|
],
|
|
267
281
|
containers: [{
|
|
268
282
|
name: 'child', image: o.image, imagePullPolicy: o.imagePullPolicy ?? 'Never',
|
|
@@ -380,6 +394,10 @@ export interface RunPodCommandOptions {
|
|
|
380
394
|
kubectl?: Kubectl;
|
|
381
395
|
/** A caller-owned scheduler is self-capped: acquires count only its own Jobs, never cluster occupancy (POOLGLOBAL-REG). */
|
|
382
396
|
poolScheduler?: PodPoolScheduler;
|
|
397
|
+
/** GATE-WARM-BOOT — seeds a commit-pinned clone's commit into the pool host mirror (test seam · default {@link seedMirrorOnce}). */
|
|
398
|
+
seedMirror?: (o: { host: string; commit: string; cwd: string }) => Promise<MirrorSeedResult | undefined>;
|
|
399
|
+
/** GATE-WARM-BOOT — the git tree the seed pushes from (default: the process cwd — the gate runs in the repo tree). */
|
|
400
|
+
mirrorSeedCwd?: string;
|
|
383
401
|
checkPool?: typeof checkPodPool;
|
|
384
402
|
syncImages?: typeof syncPoolImages;
|
|
385
403
|
imageCommit?: string | null;
|
|
@@ -396,6 +414,19 @@ export interface RunPodCommandOptions {
|
|
|
396
414
|
childLogMaxBytes?: number;
|
|
397
415
|
}
|
|
398
416
|
|
|
417
|
+
/** GATE-POD-RESULT-MARKER — the child script's final line (`\n<marker> <token> rc=<n>\n`), printed after the artifact emit. */
|
|
418
|
+
export const POD_RESULT_MARKER = '__ELANOUS_POD_DONE__';
|
|
419
|
+
/** The marker bound to one launch (`token` = the launch's random id · the Job name when the manifest has no launch). */
|
|
420
|
+
export function podResultMarker(token: string): string { return `${POD_RESULT_MARKER} ${token}`; }
|
|
421
|
+
|
|
422
|
+
/** Split the child's logs into the command output (marker tail removed, bytes otherwise unchanged) and the marker rc (null = no marker for this token). */
|
|
423
|
+
export function splitPodResultMarker(logs: string, token: string): { logs: string; rc: number | null } {
|
|
424
|
+
const escaped = podResultMarker(token).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
425
|
+
const match = new RegExp(`\\n${escaped} rc=(\\d+)\\n?$`).exec(logs);
|
|
426
|
+
if (!match) return { logs, rc: null };
|
|
427
|
+
return { logs: logs.slice(0, match.index), rc: Number(match[1]) };
|
|
428
|
+
}
|
|
429
|
+
|
|
399
430
|
function jobFinished(types: string): 'complete' | 'failed' | null {
|
|
400
431
|
if (/Complete|SuccessCriteriaMet/.test(types)) return 'complete';
|
|
401
432
|
if (/Failed|FailureTarget/.test(types)) return 'failed';
|
|
@@ -522,6 +553,16 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
522
553
|
}
|
|
523
554
|
const imageRef = member?.imageRef;
|
|
524
555
|
if (!imageRef) log('pod.command-job', 'image-fallback-local', { reason: !member ? 'no-pool-member' : !imageCommit ? 'image-commit-unavailable' : 'registry-tag-unavailable' });
|
|
556
|
+
// GATE-WARM-BOOT (10-15): a commit-pinned clone on a pool host — put that commit into the host's mirror first (once per
|
|
557
|
+
// host·commit in this process), so the Pod's podSourceScript finds it (`cat-file -e`) instead of fetching from GitHub.
|
|
558
|
+
// Best effort: a failed seed only logs; the Pod keeps the old path. Never with an injected kubectl (tests) unless seeded.
|
|
559
|
+
const seedMirror = options.seedMirror ?? (options.kubectl ? undefined : seedMirrorOnce);
|
|
560
|
+
if (seedMirror && options.clone && options.source?.kind === 'commit' && hostMirror && member?.sshHost) {
|
|
561
|
+
// Worst case added to a cold start: the push limit (GATE_MIRROR_SEED_LIMIT_MS), once per host·commit.
|
|
562
|
+
const seed = await seedMirror({ host: member.sshHost, commit: options.source.sha, cwd: options.mirrorSeedCwd ?? process.cwd() })
|
|
563
|
+
.catch((error: unknown) => ({ host: member!.sshHost!, ok: false, ms: 0, detail: String(error).slice(0, 300) }));
|
|
564
|
+
log('pod.command-job', 'mirror-seed', { host: member.sshHost, commit: options.source.sha, ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) });
|
|
565
|
+
}
|
|
525
566
|
const ghToken = options.clone ? (options.ghToken ?? defaultGhToken)() : undefined;
|
|
526
567
|
const secret = commandJobSecret({ name, namespace, launch, skills, skillEnvText, ...(grokAuth !== undefined ? { grokAuth } : {}), ...(ghToken !== undefined ? { ghToken } : {}) });
|
|
527
568
|
if (secret) {
|
|
@@ -543,10 +584,24 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
543
584
|
}
|
|
544
585
|
let state: 'complete' | 'failed' = 'failed';
|
|
545
586
|
let unreadableSince: number | null = null;
|
|
587
|
+
let markerRc: number | null = null;
|
|
588
|
+
const appliedAt = Date.now();
|
|
546
589
|
for (;;) {
|
|
547
590
|
const got = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.status.conditions[*].type}']);
|
|
548
591
|
const finished = jobFinished(got.stdout);
|
|
549
592
|
if (finished) { state = finished; break; }
|
|
593
|
+
// GATE-POD-RESULT-MARKER: the condition is not there yet — the child may already be done (k3d condition lag).
|
|
594
|
+
// A tail read that fails (Pod still pending · init container) or lacks the marker changes nothing.
|
|
595
|
+
const tail = kubectl(['-n', namespace, 'logs', `job/${name}`, '-c', 'child', '--tail=2']);
|
|
596
|
+
if (tail.status === 0) {
|
|
597
|
+
const seen = splitPodResultMarker(tail.stdout.startsWith('\n') ? tail.stdout : `\n${tail.stdout}`, launch).rc;
|
|
598
|
+
if (seen !== null) {
|
|
599
|
+
markerRc = seen;
|
|
600
|
+
state = seen === 0 ? 'complete' : 'failed';
|
|
601
|
+
log('pod.command-job', 'result-marker-early', { job: name, waitedMs: Date.now() - appliedAt, rc: seen });
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
550
605
|
if (got.status !== 0 && options.statusUnreadableMs !== undefined) {
|
|
551
606
|
unreadableSince ??= Date.now();
|
|
552
607
|
if (Date.now() - unreadableSince >= options.statusUnreadableMs) {
|
|
@@ -558,7 +613,7 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
558
613
|
}
|
|
559
614
|
const logsResult = kubectl(['-n', namespace, 'logs', `job/${name}`, '-c', 'child']);
|
|
560
615
|
const logsFailed = logsResult.status !== 0;
|
|
561
|
-
const logs = logsFailed ? '' : logsResult.stdout;
|
|
616
|
+
const logs = logsFailed ? '' : splitPodResultMarker(logsResult.stdout, launch).logs;
|
|
562
617
|
const artifactDir = artifactRoot;
|
|
563
618
|
let artifacts: PodArtifactCollection;
|
|
564
619
|
if (logsFailed) {
|
|
@@ -591,7 +646,8 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
|
|
|
591
646
|
const maxBytes = options.childLogMaxBytes ?? podChildLogMaxBytes();
|
|
592
647
|
const childLog = logsFailed ? `산출 회수 못 함: ${artifacts.error}` : tailBytes(logs, maxBytes);
|
|
593
648
|
writeFileSync(resolve(artifactsDir, 'child.log'), childLog);
|
|
594
|
-
|
|
649
|
+
// Marker path: the rc the child printed (the Pod's terminated state may lag like the condition). Condition path: unchanged.
|
|
650
|
+
const exitCode = markerRc ?? exitCodeFromPod(kubectl, namespace, name, state);
|
|
595
651
|
cleanupSecret();
|
|
596
652
|
log('pod.command', 'job-finished', {
|
|
597
653
|
job: name,
|
|
@@ -22,7 +22,7 @@ export const POD_INSTALL_SLOTS_DEFAULT = 4;
|
|
|
22
22
|
export const POD_INSTALL_SLOTS_MOUNT = '/gate-install-slots';
|
|
23
23
|
|
|
24
24
|
/** hostPath volume ⊕ mount for the tokens. `DirectoryOrCreate` makes a root-owned 0755 directory, so the Pod also needs
|
|
25
|
-
* {@link
|
|
25
|
+
* {@link podHostDirsScript} (the child runs as uid 1000). */
|
|
26
26
|
export function podInstallSlotsVolume(hostPath: string = POD_INSTALL_SLOTS_HOST_PATH) {
|
|
27
27
|
return {
|
|
28
28
|
volume: { name: 'install-slots', hostPath: { path: hostPath, type: 'DirectoryOrCreate' } },
|
|
@@ -31,19 +31,14 @@ export function podInstallSlotsVolume(hostPath: string = POD_INSTALL_SLOTS_HOST_
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* The root shell that hands the mounted hostPath directories to the child's uid. Without it a `DirectoryOrCreate`
|
|
35
35
|
* hostPath stays root:root 0755 and the child's `[ -w … ]` guard silently skips it (the Bun cache option was a no-op).
|
|
36
|
+
* Never fails the Pod: an unchanged directory only means the child falls back (no cache · no throttle).
|
|
37
|
+
* GATE-WARM-BOOT — it runs inside the Pod's single init container (after the isolation probe), not as a second one.
|
|
36
38
|
*/
|
|
37
|
-
export function
|
|
39
|
+
export function podHostDirsScript(mounts: ReadonlyArray<{ mountPath: string }>): string {
|
|
38
40
|
const paths = mounts.map((mount) => `'${mount.mountPath.replace(/'/g, `'\\''`)}'`).join(' ');
|
|
39
|
-
return {
|
|
40
|
-
name: 'host-dirs', image, imagePullPolicy,
|
|
41
|
-
securityContext: { runAsUser: 0 },
|
|
42
|
-
command: ['sh', '-c'],
|
|
43
|
-
// Never fails the Pod: an unchanged directory only means the child falls back (no cache · no throttle).
|
|
44
|
-
args: [`for d in ${paths}; do mkdir -p "$d" && chown 1000:1000 "$d" && chmod 0775 "$d" || echo "[host-dirs] could not prepare $d"; done; exit 0`],
|
|
45
|
-
volumeMounts: mounts.map((mount) => ({ ...mount })),
|
|
46
|
-
};
|
|
41
|
+
return `for d in ${paths}; do mkdir -p "$d" && chown 1000:1000 "$d" && chmod 0775 "$d" || echo "[host-dirs] could not prepare $d"; done; exit 0`;
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
const int = (value: number, label: string) => {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// GATE-WARM-BOOT (10-15) — put the cut commit into each pool host's git mirror before the shard Pods start.
|
|
2
|
+
//
|
|
3
|
+
// S: 0.2.29 gate Pods spent 750–840 s before the shard shell; the tests took 0–69 s. Every Pod clones from the host
|
|
4
|
+
// mirror (`pod.hostMirror` → `/host-mirror`, podSourceScript), but the cut commit e1783835 was not in the node-b mirror
|
|
5
|
+
// (the mirror's own fetch loop follows `main`; only the `--remote` host executor pushed `refs/elanous/gate/<sha>`).
|
|
6
|
+
// So all 68 Pods fell to `git fetch --depth 1 origin <sha>` from GitHub, under load, one by one.
|
|
7
|
+
// A: push `<sha>:refs/elanous/gate/<sha>` to the placed pool member's mirror once per (host, commit) per process — podSourceScript's commit branch
|
|
8
|
+
// then passes `git cat-file -e` and skips the GitHub fetch. Best effort: a failed push is recorded and the Pod keeps
|
|
9
|
+
// its old path (fetch from GitHub) — never a silent use of another tree.
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
import { debug } from '../../debug/log.js';
|
|
12
|
+
|
|
13
|
+
/** Host-side mirror path (relative to the ssh user's home) — the k3d node binds `~/mirror` at `/mirror-host`. */
|
|
14
|
+
export const GATE_POOL_MIRROR_PATH = 'mirror/elanous-agent.git';
|
|
15
|
+
export const GATE_MIRROR_SEED_LIMIT_MS = 120_000;
|
|
16
|
+
|
|
17
|
+
export interface MirrorSeedResult { host: string; ok: boolean; ms: number; detail?: string }
|
|
18
|
+
|
|
19
|
+
type Push = (args: string[], cwd: string, limitMs: number) => Promise<{ rc: number; output: string }>;
|
|
20
|
+
|
|
21
|
+
export async function seedPoolMirrors(o: { hosts: readonly (string | undefined)[]; commit: string; tree: string; push: Push; mirrorPath?: string; limitMs?: number }): Promise<MirrorSeedResult[]> {
|
|
22
|
+
if (!/^[0-9a-f]{40}$/.test(o.commit)) throw new Error('invalid gate commit');
|
|
23
|
+
const mirror = o.mirrorPath ?? GATE_POOL_MIRROR_PATH;
|
|
24
|
+
const hosts = [...new Set(o.hosts.filter((host): host is string => !!host && /^[\w.@-]+$/.test(host) && !host.startsWith('-')))];
|
|
25
|
+
const results = await Promise.all(hosts.map(async (host): Promise<MirrorSeedResult> => {
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
try {
|
|
28
|
+
const run = await o.push(['push', '--quiet', '--no-verify', `${host}:${mirror}`, `${o.commit}:refs/elanous/gate/${o.commit}`], o.tree, o.limitMs ?? GATE_MIRROR_SEED_LIMIT_MS);
|
|
29
|
+
const ms = Date.now() - start;
|
|
30
|
+
return run.rc === 0 ? { host, ok: true, ms } : { host, ok: false, ms, detail: run.output.trim().slice(-300) };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return { host, ok: false, ms: Date.now() - start, detail: String(error).slice(0, 300) };
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
for (const result of results) {
|
|
36
|
+
debug.log('release-loop.gate', result.ok ? 'pod-mirror-seeded' : 'pod-mirror-seed-failed', { ...result, commit: o.commit }, result.ok ? undefined : { level: 'warn' });
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const seeded = new Map<string, Promise<MirrorSeedResult | undefined>>();
|
|
42
|
+
|
|
43
|
+
/** Bounded `git <args>` in `cwd` — killed after `limitMs`; never throws. */
|
|
44
|
+
export function gitWithin(args: string[], cwd: string, limitMs: number): Promise<{ rc: number; output: string }> {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
let output = '';
|
|
47
|
+
let child;
|
|
48
|
+
try { child = spawn('git', args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] }); }
|
|
49
|
+
catch (error) { resolve({ rc: 2, output: String(error) }); return; }
|
|
50
|
+
const timer = setTimeout(() => { output += `\n[mirror-seed] timed out after ${limitMs} ms`; child.kill('SIGKILL'); }, limitMs);
|
|
51
|
+
child.stdout?.on('data', (chunk) => { output += String(chunk); });
|
|
52
|
+
child.stderr?.on('data', (chunk) => { output += String(chunk); });
|
|
53
|
+
child.on('error', (error) => { clearTimeout(timer); resolve({ rc: 2, output: `${output}\n${String(error)}` }); });
|
|
54
|
+
child.on('close', (code) => { clearTimeout(timer); resolve({ rc: code ?? 2, output }); });
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Seed once per (host, commit) in this process: every shard Job placed on the same member awaits the same push, so a
|
|
60
|
+
* 28-shard gate pushes once per host. `cwd` must be a git tree that has the commit (the gate runs in the repo tree).
|
|
61
|
+
*/
|
|
62
|
+
export function seedMirrorOnce(o: { host: string; commit: string; cwd: string; push?: Push }): Promise<MirrorSeedResult | undefined> {
|
|
63
|
+
const key = `${o.host}\0${o.commit}`;
|
|
64
|
+
let pending = seeded.get(key);
|
|
65
|
+
if (!pending) {
|
|
66
|
+
// A failed seed is not memoized — the next Job on that host tries again (a transient ssh drop must not send the whole gate to GitHub).
|
|
67
|
+
pending = seedPoolMirrors({ hosts: [o.host], commit: o.commit, tree: o.cwd, push: o.push ?? gitWithin })
|
|
68
|
+
.then((results) => { if (!results[0]?.ok) seeded.delete(key); return results[0]; },
|
|
69
|
+
(error: unknown) => { seeded.delete(key); return { host: o.host, ok: false, ms: 0, detail: String(error).slice(0, 300) }; });
|
|
70
|
+
seeded.set(key, pending);
|
|
71
|
+
}
|
|
72
|
+
return pending;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Test seam — forget the per-process seed memo. */
|
|
76
|
+
export function resetMirrorSeedMemo(): void { seeded.clear(); }
|
|
@@ -79,17 +79,20 @@ import { envLiteral } from '../../platform/env-literal.js';
|
|
|
79
79
|
import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
|
|
80
80
|
import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
|
|
81
81
|
import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
|
|
82
|
+
import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
|
|
82
83
|
import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
|
|
83
84
|
import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
|
|
84
85
|
import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
|
|
85
|
-
import { getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
|
|
86
|
+
import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
|
|
86
87
|
import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
|
|
87
88
|
import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
|
|
88
89
|
import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
|
|
89
90
|
import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiPodSlot, zaiOverflowChildArgs, zaiPodEnv, type ZaiPodSpec } from './pod-zai-child.js';
|
|
90
91
|
import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
|
|
91
|
-
import { selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
|
|
92
|
+
import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
|
|
93
|
+
import { inferProviderFromModel } from '../../llm.js';
|
|
92
94
|
import { classifyPodExit, extractPodFailureReason, podTerminalRow, type PodExitClass } from './pod-failure-reason.js';
|
|
95
|
+
import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
|
|
93
96
|
import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
|
|
94
97
|
|
|
95
98
|
export type Kubectl = (args: readonly string[], input?: string) => { status: number | null; stdout: string; stderr: string };
|
|
@@ -119,6 +122,8 @@ export interface PodSpawnOptions {
|
|
|
119
122
|
budgetSnapshot?: (childLlm: PodBudgetChildLlm) => Promise<BudgetSnapshot | undefined> | BudgetSnapshot | undefined;
|
|
120
123
|
/** Input reader seam; the host still runs its normal budget decision and Job propagation. */
|
|
121
124
|
budgetInputDeps?: ReadBudgetInputsDeps & { readLiveGrok?: () => Promise<number | undefined> };
|
|
125
|
+
/** Test seam for the planning Codex quota check; production reads the existing budget-gate candidates. */
|
|
126
|
+
planningCodexQuota?: (account: string) => { usable: boolean; reason?: string };
|
|
122
127
|
/** Child model/effort chosen at launch (`--child-llm-model/--child-llm-effort`) — carried into the Pod child. */
|
|
123
128
|
childModel?: string;
|
|
124
129
|
childEffort?: string;
|
|
@@ -136,6 +141,8 @@ export interface PodSpawnOptions {
|
|
|
136
141
|
configHostMirror?: () => string | undefined;
|
|
137
142
|
/** AUTHOR-POD2 host config seam; Pod itself has no host config. */
|
|
138
143
|
authorConfig?: () => UserConfig;
|
|
144
|
+
/** Host fallback chain seam; a Pod has no access to the host config. */
|
|
145
|
+
fallbackConfig?: () => UserConfig;
|
|
139
146
|
/** 원천 — 없으면 종전 `git clone --depth 50`. bundle 이면 apply 뒤 kubectl cp 로 싣는다. */
|
|
140
147
|
source?: PodSource;
|
|
141
148
|
/** Existing PR repair: pin the source head and export a commit bundle instead of opening a PR. */
|
|
@@ -284,6 +291,20 @@ async function measureHostBudgetSnapshot(childLlm: PodBudgetChildLlm, env: NodeJ
|
|
|
284
291
|
};
|
|
285
292
|
}
|
|
286
293
|
|
|
294
|
+
/** Planning uses a subscription account inside an OpenRouter Pod. Credits are not a silent fallback for this role. */
|
|
295
|
+
async function hostPlanningCodexQuota(account: string, deps?: ReadBudgetInputsDeps): Promise<{ usable: boolean; reason?: string }> {
|
|
296
|
+
try {
|
|
297
|
+
const { readBudgetInputs } = await import('../../self-implement/budget-gate.js');
|
|
298
|
+
const inputs = readBudgetInputs(deps);
|
|
299
|
+
const candidate = inputs.codexCandidates.find((item) => item.name === account);
|
|
300
|
+
const configuredCap = inputs.maxUsedPercent['openai-codex'];
|
|
301
|
+
const cap = typeof configuredCap === 'number' && Number.isFinite(configuredCap) ? configuredCap : DEFAULT_BUDGET_GATE_MAX_USED_PERCENT['openai-codex']!;
|
|
302
|
+
if (!candidate || typeof candidate.usedPercent !== 'number' || !Number.isFinite(candidate.usedPercent)) return { usable: false, reason: 'quota-unmeasured' };
|
|
303
|
+
if (candidate.reached === true || candidate.usedPercent >= cap) return { usable: false, reason: 'quota-exhausted' };
|
|
304
|
+
return { usable: true };
|
|
305
|
+
} catch { return { usable: false, reason: 'quota-unavailable' }; }
|
|
306
|
+
}
|
|
307
|
+
|
|
287
308
|
/** «3시간 안 만료» — 선갱신 대상이라는 표지(다른 자격 오류와 구분한다). */
|
|
288
309
|
export class PodCodexExpiringError extends Error {
|
|
289
310
|
constructor(readonly account: string, readonly hoursLeft: number) {
|
|
@@ -956,7 +977,7 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
|
|
|
956
977
|
return `trap '{ [ -n "$si_pid" ] && kill "$si_pid" 2>/dev/null || true; [ -n "\${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true; si_seq=$(cat ${seqFile} 2>/dev/null || true); case "$si_seq" in ""|*[!0-9]*) si_seq=0;; esac; si_seq=$((10#$si_seq + 1)); { [ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h --partial --seq "$si_seq"; } & si_rollup_pid=$!; for si_i in 1 2 3 4 5 6 7 8; do kill -0 "$si_rollup_pid" 2>/dev/null || break; sleep 1; done; kill "$si_rollup_pid" 2>/dev/null || true; wait "$si_rollup_pid" 2>/dev/null || true; exit 143; }' TERM`;
|
|
957
978
|
}
|
|
958
979
|
|
|
959
|
-
export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec }): Record<string, unknown> {
|
|
980
|
+
export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' } }): Record<string, unknown> {
|
|
960
981
|
if (o.repairCommitOnly && (o.source?.kind !== 'pr' || o.source.number !== o.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(o.repairCommitOnly.baseHead) || o.args.includes('--open-pr') || o.args.includes('--merge-by-host') || o.args.includes('--auto-merge'))) {
|
|
961
982
|
throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
|
|
962
983
|
}
|
|
@@ -981,6 +1002,10 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
981
1002
|
: '';
|
|
982
1003
|
const script = [
|
|
983
1004
|
'set -u',
|
|
1005
|
+
...(o.fallbackChain ? [
|
|
1006
|
+
'mkdir -p "$HOME/.elanous" && install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json" || exit 6',
|
|
1007
|
+
`echo "ELANOUS_POD_FALLBACK_CHAIN source=${o.fallbackChain.source} steps=${o.fallbackChain.steps.join(',')}"`,
|
|
1008
|
+
] : []),
|
|
984
1009
|
openrouterModel
|
|
985
1010
|
? o.reviewerCodexAuth
|
|
986
1011
|
? 'mkdir -p ~/.elanous ~/.codex && cp /creds/elanous-auth.json ~/.elanous/auth.json && cp /creds/codex-auth.json ~/.codex/auth.json && chmod 600 ~/.elanous/auth.json ~/.codex/auth.json && export ELANOUS_LLM_PROVIDER=openrouter'
|
|
@@ -1533,8 +1558,23 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1533
1558
|
? (options.grokCredentials ?? (() => hostGrokCredentials({ env, apiKeyOptIn: options.grokApiKeyOptIn })))()
|
|
1534
1559
|
: apiKeyChild ? { ghToken: (options.openrouterGhToken ?? defaultGhToken)() }
|
|
1535
1560
|
: codexCredentials?.[0] ?? usable[0]!.credential;
|
|
1536
|
-
// POD-ROLE-LLM — OpenRouter
|
|
1561
|
+
// POD-ROLE-LLM — OpenRouter 자식의 Codex 역할(리뷰·저작 grounding)은 별도 access 자격을 검증해 싣는다.
|
|
1537
1562
|
// ⛔ kubectl 주입(=시험)이면 호스트 자격 스토어를 읽지 않는다 — 시험은 credentials 를 명시한다.
|
|
1563
|
+
const roleCodexAccount = options.account ?? 'team';
|
|
1564
|
+
const loadRoleCodexCredential = async (): Promise<{ credential?: { elanousAuth: string; codexAuth: string }; skipped?: string }> => {
|
|
1565
|
+
const credentialSource = options.credentials ?? (options.kubectl ? undefined : (account: string) => hostCredentials(account, authStorePath(), () => ''));
|
|
1566
|
+
if (!credentialSource) return { skipped: 'no-credential-source' };
|
|
1567
|
+
try {
|
|
1568
|
+
const got = await podCodexCredentialWithPrerefresh(roleCodexAccount, { ...prerefreshDeps, credentials: credentialSource });
|
|
1569
|
+
if (!got) return { skipped: 'expiring' };
|
|
1570
|
+
const elanous = JSON.parse(got.elanousAuth) as { providers?: Record<string, { tokens?: { accessToken?: unknown; refreshToken?: unknown } }> };
|
|
1571
|
+
const codex = JSON.parse(got.codexAuth) as { tokens?: { access_token?: unknown; refresh_token?: unknown } };
|
|
1572
|
+
const elanousTokens = elanous.providers?.['openai-codex']?.tokens;
|
|
1573
|
+
const nonEmpty = (v: unknown): boolean => typeof v === 'string' && v.trim().length > 0;
|
|
1574
|
+
if (!elanousTokens || !nonEmpty(elanousTokens.accessToken) || elanousTokens.refreshToken || !codex.tokens || !nonEmpty(codex.tokens.access_token) || codex.tokens.refresh_token) return { skipped: 'credential-shape' };
|
|
1575
|
+
return { credential: { elanousAuth: got.elanousAuth, codexAuth: got.codexAuth } };
|
|
1576
|
+
} catch { return { skipped: 'credential-error' }; } // 자격 오류 원문에는 토큰이 섞일 수 있다.
|
|
1577
|
+
};
|
|
1538
1578
|
let reviewerCredential: { elanousAuth: string; codexAuth: string } | undefined;
|
|
1539
1579
|
let reviewerPin: string | undefined;
|
|
1540
1580
|
const reviewerPick = openrouter ? resolvePodOpenRouterReviewer(options.openrouterReviewer, env) : undefined;
|
|
@@ -1544,29 +1584,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1544
1584
|
} else if (reviewerPick?.choice === 'off') {
|
|
1545
1585
|
debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'off', source: reviewerPick.source, reason: 'off' });
|
|
1546
1586
|
} else if (reviewerPick?.choice === 'codex-sol') {
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
let skipped: string | undefined;
|
|
1550
|
-
if (!reviewerCredentials) skipped = 'no-credential-source';
|
|
1551
|
-
else {
|
|
1552
|
-
try {
|
|
1553
|
-
const got = await podCodexCredentialWithPrerefresh(reviewerAccount, { ...prerefreshDeps, credentials: reviewerCredentials });
|
|
1554
|
-
if (!got) skipped = 'expiring';
|
|
1555
|
-
else {
|
|
1556
|
-
const elanous = JSON.parse(got.elanousAuth) as { providers?: Record<string, { tokens?: { accessToken?: unknown; refreshToken?: unknown } }> };
|
|
1557
|
-
const codex = JSON.parse(got.codexAuth) as { tokens?: { access_token?: unknown; refresh_token?: unknown } };
|
|
1558
|
-
const elanousTokens = elanous.providers?.['openai-codex']?.tokens;
|
|
1559
|
-
const nonEmpty = (v: unknown): boolean => typeof v === 'string' && v.trim().length > 0;
|
|
1560
|
-
// 불완전한 자격(access 비었음·refresh 있음)이면 고정을 켜지 않는다 — 켜면 Pod 리뷰가 인증 실패로 no-real-review 가 된다.
|
|
1561
|
-
if (!elanousTokens || !nonEmpty(elanousTokens.accessToken) || elanousTokens.refreshToken || !codex.tokens || !nonEmpty(codex.tokens.access_token) || codex.tokens.refresh_token) skipped = 'credential-shape';
|
|
1562
|
-
else reviewerCredential = { elanousAuth: got.elanousAuth, codexAuth: got.codexAuth };
|
|
1563
|
-
}
|
|
1564
|
-
} catch { skipped = 'credential-error'; } // ⛔ 원문 메시지는 싣지 않는다 — 자격 오류 문면에 토큰이 섞일 수 있다(비밀 0)
|
|
1565
|
-
}
|
|
1587
|
+
const { credential, skipped } = await loadRoleCodexCredential();
|
|
1588
|
+
reviewerCredential = credential;
|
|
1566
1589
|
if (reviewerCredential) {
|
|
1567
1590
|
reviewerPin = POD_OPENROUTER_REVIEWER_PINS['codex-sol'];
|
|
1568
|
-
debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'review', env: roleLlmEnvName('review'), value: reviewerPin, choice: 'codex-sol', source: reviewerPick.source, account:
|
|
1569
|
-
} else debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'codex-sol', source: reviewerPick.source, account:
|
|
1591
|
+
debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'review', env: roleLlmEnvName('review'), value: reviewerPin, choice: 'codex-sol', source: reviewerPick.source, account: roleCodexAccount });
|
|
1592
|
+
} else debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'codex-sol', source: reviewerPick.source, account: roleCodexAccount, reason: skipped });
|
|
1570
1593
|
}
|
|
1571
1594
|
if (grok && !('grokAuth' in creds && creds.grokAuth) && !('grokApiKey' in creds && creds.grokApiKey && options.grokApiKeyOptIn === true)) {
|
|
1572
1595
|
throw new Error('grok: 구독 자격 없음 · API 키 opt-in 꺼짐 또는 키 없음');
|
|
@@ -1697,13 +1720,48 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1697
1720
|
debug.log('self-implement.pod', 'goal-doc-mode', { spaceId: input.spaceId, mode, reason: shard ? 'shard-identity' : requestedPath ? 'goal-doc-env' : 'no-goal-doc' });
|
|
1698
1721
|
const goalDoc = shard ? undefined : requestedPath;
|
|
1699
1722
|
const goalDocument = goalDoc ? originalGoal : undefined;
|
|
1723
|
+
const authorOnPod = env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !goalDoc && !shard;
|
|
1724
|
+
// Relay provenance is set by this host after selection; caller env cannot assert it.
|
|
1725
|
+
const hostAuthorEnv = { ...env };
|
|
1726
|
+
for (const key of Object.keys(hostAuthorEnv)) {
|
|
1727
|
+
if (key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== 'ELANOUS_PROMPT_ENHANCE_MODEL' && key !== 'ELANOUS_PROMPT_ENHANCE_EFFORT') delete hostAuthorEnv[key];
|
|
1728
|
+
}
|
|
1729
|
+
let authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, hostAuthorEnv) : undefined;
|
|
1730
|
+
let authorFallbackReason: string | undefined;
|
|
1731
|
+
let authorRequestedModel: string | undefined;
|
|
1732
|
+
let authorRequestedSource: string | undefined;
|
|
1733
|
+
let roleCodexCredential = reviewerCredential;
|
|
1734
|
+
if (openrouter && authorChoice && inferProviderFromModel(authorChoice.model) === 'openai-codex') {
|
|
1735
|
+
const quota = options.planningCodexQuota?.(roleCodexAccount) ?? await hostPlanningCodexQuota(roleCodexAccount, options.budgetInputDeps);
|
|
1736
|
+
if (!quota.usable) authorFallbackReason = normalizePlanningFallbackReason(quota.reason ?? 'quota-unavailable');
|
|
1737
|
+
else if (!roleCodexCredential) {
|
|
1738
|
+
const { credential, skipped } = await loadRoleCodexCredential();
|
|
1739
|
+
if (credential) roleCodexCredential = credential;
|
|
1740
|
+
else authorFallbackReason = normalizePlanningFallbackReason(skipped ?? 'credential-unavailable');
|
|
1741
|
+
}
|
|
1742
|
+
if (authorFallbackReason) {
|
|
1743
|
+
const childModel = podDelegatedChildLlm(jobArgs)?.model;
|
|
1744
|
+
if (!childModel || inferProviderFromModel(childModel) !== 'openrouter') throw new Error(`pod: planning sol·자식 모델 모두 불가 (${authorFallbackReason})`);
|
|
1745
|
+
authorRequestedModel = authorChoice.model;
|
|
1746
|
+
authorRequestedSource = authorChoice.modelSource;
|
|
1747
|
+
debug.log('self-implement.pod', 'planning-model-fallback', { job: name, provider: 'openrouter', model: childModel, reason: authorFallbackReason, requestedModel: authorChoice.model, account: roleCodexAccount });
|
|
1748
|
+
authorChoice = { ...authorChoice, model: childModel, modelSource: 'fallback-child' };
|
|
1749
|
+
} else debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'planning', model: authorChoice.model, source: authorChoice.modelSource, account: roleCodexAccount });
|
|
1750
|
+
}
|
|
1700
1751
|
const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouter ? openrouterKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
|
|
1752
|
+
const hostFallbackNames = (options.fallbackConfig ?? getUserConfig)().llm.fallbackChain;
|
|
1753
|
+
const normalizedFallback = normalizeFallbackChain(hostFallbackNames);
|
|
1754
|
+
const fallbackChain = { steps: normalizedFallback.chain, source: normalizedFallback.usedDefault ? 'default' as const : 'host' as const };
|
|
1755
|
+
debug.log('self-implement.pod', 'fallback-chain-carried', {
|
|
1756
|
+
job: name, source: fallbackChain.source, steps: fallbackChain.steps,
|
|
1757
|
+
...(normalizedFallback.dropped.length ? { droppedCount: normalizedFallback.dropped.length } : {}),
|
|
1758
|
+
});
|
|
1701
1759
|
const secret = {
|
|
1702
1760
|
apiVersion: 'v1', kind: 'Secret', type: 'Opaque',
|
|
1703
1761
|
metadata: { name: `${name}-creds`, namespace, labels: { 'elanous.job': name } },
|
|
1704
1762
|
stringData: {
|
|
1705
1763
|
...(anthropic || bedrockChild || zaiChild ? {}
|
|
1706
|
-
: openrouter ? (
|
|
1764
|
+
: openrouter ? (roleCodexCredential ? { 'elanous-auth.json': roleCodexCredential.elanousAuth, 'codex-auth.json': roleCodexCredential.codexAuth } : {})
|
|
1707
1765
|
: grok
|
|
1708
1766
|
? ('grokAuth' in creds && creds.grokAuth
|
|
1709
1767
|
? { 'grok-auth.json': creds.grokAuth }
|
|
@@ -1712,6 +1770,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1712
1770
|
? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
|
|
1713
1771
|
: { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
|
|
1714
1772
|
'gh-token': podGhToken, feature: input.feature,
|
|
1773
|
+
'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps } }),
|
|
1715
1774
|
...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
|
|
1716
1775
|
...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
|
|
1717
1776
|
...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
|
|
@@ -1808,7 +1867,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1808
1867
|
const removed = kubectl(['-n', namespace, 'delete', 'job', name, '--ignore-not-found', '--wait=true']);
|
|
1809
1868
|
if (removed.status !== 0) return { exitCode: 1, output: removed.stderr, error: { code: 'pod-delete', message: removed.stderr.trim() } };
|
|
1810
1869
|
}
|
|
1811
|
-
const
|
|
1870
|
+
const applySecret = () => kubectl(['apply', '-f', '-'], JSON.stringify(secret));
|
|
1871
|
+
let s = applySecret();
|
|
1872
|
+
// K3S-SECRET-DB-LOCK-RETRY — k3s sqlite «database is locked» 는 백오프 재시도 · 소진 시에만 아래 pod-secret 실패.
|
|
1873
|
+
if (kubectlTransientReason(s)) s = await retryKubectlTransient(applySecret, s, { sleep, category: 'pod.secret', data: { job: name, namespace, context } });
|
|
1812
1874
|
if (s.status !== 0) return { exitCode: 1, output: s.stderr, error: { code: 'pod-secret', message: s.stderr.trim() } };
|
|
1813
1875
|
const jobPassEnv = [
|
|
1814
1876
|
...passEnv,
|
|
@@ -1819,12 +1881,16 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1819
1881
|
const detail = selectLiveDetail(options.liveDetailFile ? { path: options.liveDetailFile } : {}).state;
|
|
1820
1882
|
const detailUntil = detail && (detail.scope === 'all' || detail.scope === parentRunId || detail.scope === launchRunId) && detail.until > Date.now()
|
|
1821
1883
|
? String(detail.until) : undefined;
|
|
1822
|
-
const armEnv = Object.fromEntries(Object.entries(options.armEnv ?? {}).filter(([key]) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL' && key
|
|
1884
|
+
const armEnv = Object.fromEntries(Object.entries(options.armEnv ?? {}).filter(([key]) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL' && !key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV && (!hostRefresh || !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key))));
|
|
1823
1885
|
const seat = env.ELANOUS_HARNESS_SEAT;
|
|
1824
|
-
const authorOnPod = env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !goalDoc && !shard;
|
|
1825
|
-
const authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, env) : undefined;
|
|
1826
1886
|
const authorEnv = authorChoice ? {
|
|
1827
|
-
...(authorChoice.modelSource !== 'default'
|
|
1887
|
+
...(authorChoice.modelSource !== 'default' || inferProviderFromModel(authorChoice.model) === 'openai-codex' ? {
|
|
1888
|
+
ELANOUS_PROMPT_ENHANCE_MODEL: authorChoice.model,
|
|
1889
|
+
ELANOUS_PROMPT_ENHANCE_MODEL_RELAY: 'pod',
|
|
1890
|
+
ELANOUS_PROMPT_ENHANCE_MODEL_SOURCE: authorChoice.modelSource,
|
|
1891
|
+
...(authorFallbackReason ? { ELANOUS_PROMPT_ENHANCE_MODEL_FALLBACK_REASON: authorFallbackReason } : {}),
|
|
1892
|
+
...(authorRequestedModel ? { ELANOUS_PROMPT_ENHANCE_REQUESTED_MODEL: authorRequestedModel, ELANOUS_PROMPT_ENHANCE_REQUESTED_SOURCE: authorRequestedSource! } : {}),
|
|
1893
|
+
} : {}),
|
|
1828
1894
|
...(authorChoice.effortSource !== 'default' ? { ELANOUS_PROMPT_ENHANCE_EFFORT: authorChoice.effort } : {}),
|
|
1829
1895
|
} : {};
|
|
1830
1896
|
const budgetRead = hostBudgetSnapshot(podDelegatedChildLlm(jobArgs) ?? {}, options, env, name);
|
|
@@ -1872,7 +1938,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1872
1938
|
slotId: env.ELANOUS_POD_SLOT_ID,
|
|
1873
1939
|
work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
|
|
1874
1940
|
};
|
|
1875
|
-
const job = podJobManifest({ name, namespace, image: jobImage, workIdentity, ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: options.deadlineSeconds ?? POD_JOB_DEADLINE_SECONDS, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: options.imageCommit !== undefined ? options.imageCommit : options.kubectl ? null : podImageFreshness({ image }).imageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(
|
|
1941
|
+
const job = podJobManifest({ name, namespace, fallbackChain, image: jobImage, workIdentity, ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: options.deadlineSeconds ?? POD_JOB_DEADLINE_SECONDS, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: options.imageCommit !== undefined ? options.imageCommit : options.kubectl ? null : podImageFreshness({ image }).imageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
|
|
1876
1942
|
const carriedBranch = goalDoc ? 'goal-doc' as const : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'author' as const : undefined;
|
|
1877
1943
|
const carriedChildLlm = carriedBranch ? podDelegatedChildLlm(jobArgs) : undefined;
|
|
1878
1944
|
const a = kubectl(['apply', '-f', '-'], JSON.stringify(job));
|
|
@@ -2468,8 +2534,16 @@ export function reemitPodUsage(logs: string, job: string, log: (category: string
|
|
|
2468
2534
|
const rows = parsed.rows ?? [];
|
|
2469
2535
|
for (const r of rows) {
|
|
2470
2536
|
const cost = podRowCost(r, reprice);
|
|
2537
|
+
const role = typeof r.role === 'string' && r.role.trim() ? r.role : undefined;
|
|
2538
|
+
const stage = typeof r.stage === 'string' && r.stage.trim() ? r.stage : undefined;
|
|
2539
|
+
const account = typeof r.account === 'string' && r.account.trim() ? r.account : undefined;
|
|
2471
2540
|
log('llm.usage', 'llm-usage', {
|
|
2472
2541
|
site: `pod-rollup:${String(r.site)}`, provider: r.provider, model: r.model, calls: r.calls,
|
|
2542
|
+
// Preserve only source-observed dimensions. A Pod bucket can contain the
|
|
2543
|
+
// same model under several roles, so these also distinguish dedup keys.
|
|
2544
|
+
...(role !== undefined ? { role } : {}),
|
|
2545
|
+
...(stage !== undefined ? { stage } : {}),
|
|
2546
|
+
...(account !== undefined ? { account } : {}),
|
|
2473
2547
|
inputTokens: r.inputTokens, outputTokens: r.outputTokens, cacheReadInputTokens: r.cacheReadInputTokens,
|
|
2474
2548
|
// ⭐ 캐시 쓰기 — 옛 Pod 이미지 rollup 엔 칸이 없다 ⇒ 없으면 «잰 0» 으로 꾸미지 않고 뺀다.
|
|
2475
2549
|
...(r.cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens: r.cacheCreationInputTokens } : {}),
|
|
@@ -2482,7 +2556,7 @@ export function reemitPodUsage(logs: string, job: string, log: (category: string
|
|
|
2482
2556
|
// 부분(seq 달라도)·최종·abort⊕resume 재방출이 몇 번 만나도 집계(rollup)에서 한 번만 센다. 키 없는 기존 행은 종전대로.
|
|
2483
2557
|
// ⭐ METER-POD-ROLLUP-GAP-2 — podName 을 키에 넣는다: gh-login·usage-limit 재시도는 «같은 job 이름·runId» 로 새 Pod 를 띄우므로
|
|
2484
2558
|
// (podJobName 은 spaceId 결정적) 그것 없이는 서로 다른 시도의 사용량이 한 번으로 접혀 앞 시도분이 사라진다.
|
|
2485
|
-
podRollupKey: `${job}|${parsed.podName ?? ''}|${parsed.runId ?? ''}|pod-rollup:${String(r.site)}|${String(r.provider)}|${String(r.model)}`,
|
|
2559
|
+
podRollupKey: `${job}|${parsed.podName ?? ''}|${parsed.runId ?? ''}|pod-rollup:${String(r.site)}|${String(r.provider)}|${String(r.model)}${role !== undefined || stage !== undefined || account !== undefined ? `|${JSON.stringify([role ?? null, stage ?? null, account ?? null])}` : ''}`,
|
|
2486
2560
|
...(parsed.podName ? { podName: parsed.podName } : {}), ...(parsed.nodeName ? { nodeName: parsed.nodeName } : {}), ...(parsed.hostId ? { podHostId: parsed.hostId } : {}),
|
|
2487
2561
|
// ⭐ PARTIAL 폴백 재방출 꼬리표 — 최종 줄 행은 그대로(부분이 아님을 꾸미지 않는다).
|
|
2488
2562
|
...(partialLine ? { partial: true, ...(parsed.seq !== undefined ? { partialSeq: parsed.seq } : {}), ...(parsed.at !== undefined ? { partialAt: parsed.at } : {}), ...(livePartial ? { partialSource: 'live-capture' } : {}) } : {}),
|
|
@@ -158,6 +158,12 @@ export class TerminalSessionRegistry {
|
|
|
158
158
|
shellArgs: spec.shellArgs,
|
|
159
159
|
env: spec.env,
|
|
160
160
|
termName: spec.termName,
|
|
161
|
+
useRegistry: spec.useRegistry,
|
|
162
|
+
registryKind: spec.registryKind,
|
|
163
|
+
registryNickname: spec.registryNickname,
|
|
164
|
+
registryOrigin: spec.registryOrigin,
|
|
165
|
+
registryPurpose: spec.registryPurpose,
|
|
166
|
+
registrySeat: spec.registrySeat,
|
|
161
167
|
bounds: spec.bounds,
|
|
162
168
|
sizePreset: spec.sizePreset,
|
|
163
169
|
onExit: (code) => {
|
package/src/thinking-line.ts
CHANGED
|
@@ -295,10 +295,19 @@ export function startPinnedThinking(opts: StartPinnedThinkingOpts): ThinkingHand
|
|
|
295
295
|
const interval = opts.intervalMs ?? INTERVAL_MS;
|
|
296
296
|
const timer = interval > 0 ? setInterval(tick, interval) : null;
|
|
297
297
|
|
|
298
|
+
// ⛔ stop() 뒤엔 칠하지 않는다 — 멈춘 손잡이에 늦게 온 update/updateMetrics(다음 반복이 같은 손잡이를
|
|
299
|
+
// 재사용하거나 턴 마감 뒤 도착한 이벤트)가 «✢ Thinking…» 프레임을 footer 에 다시 써서, 타이머 없는
|
|
300
|
+
// 멈춘 표시로 남았다(TUI 결함 #5 · 10-14 13:43 오류 뒤 «Thinking…» 정지).
|
|
301
|
+
const repaint = (): void => {
|
|
302
|
+
if (stopped) return;
|
|
303
|
+
paint();
|
|
304
|
+
opts.onFrame();
|
|
305
|
+
};
|
|
306
|
+
|
|
298
307
|
return {
|
|
299
|
-
update: (m) => { message = m; messageFactory = null;
|
|
300
|
-
updateAnimated: (fn) => { messageFactory = fn;
|
|
301
|
-
updateMetrics: (m) => { metrics = { ...metrics, ...m };
|
|
308
|
+
update: (m) => { message = m; messageFactory = null; repaint(); },
|
|
309
|
+
updateAnimated: (fn) => { messageFactory = fn; repaint(); },
|
|
310
|
+
updateMetrics: (m) => { metrics = { ...metrics, ...m }; repaint(); },
|
|
302
311
|
reflow: () => { if (!stopped) paint(); opts.onFrame(); },
|
|
303
312
|
stop: (stopOpts) => {
|
|
304
313
|
if (stopped) return;
|
|
@@ -32,6 +32,7 @@ import { agentReplyRuntime } from './agent-reply-runtime.js';
|
|
|
32
32
|
import { agentStopRuntime } from './agent-stop-runtime.js';
|
|
33
33
|
import { ALL_TEAM_TOOL_RUNTIMES } from './team-tool-runtimes.js';
|
|
34
34
|
import { ALL_OPS_FLEET_RUNTIMES } from './ops-fleet-runtimes.js';
|
|
35
|
+
import { ALL_OPS_LEDGER_RUNTIMES } from './ops-ledger-runtimes.js';
|
|
35
36
|
import { ALL_AUTO_RESEARCH_RUNTIMES } from './auto-research-runtimes.js';
|
|
36
37
|
import { ALL_INTELLIGENCE_MAP_RUNTIMES } from './intelligence-map-runtimes.js';
|
|
37
38
|
import { ALL_CFT_ANDON_RUNTIMES } from './cft-andon-runtimes.js';
|
|
@@ -115,6 +116,9 @@ export function registerAllDefaultToolRuntimes(): void {
|
|
|
115
116
|
registerToolRuntime(agentStopRuntime);
|
|
116
117
|
for (const rt of ALL_TEAM_TOOL_RUNTIMES) registerToolRuntime(rt);
|
|
117
118
|
for (const rt of ALL_OPS_FLEET_RUNTIMES) registerToolRuntime(rt);
|
|
119
|
+
// Ops-ledger (우편 msg · 판 release checklist) — in-process ledger tools so
|
|
120
|
+
// TUI OP turns stop paying 1.3–2s of `eln` CLI startup per msg/checklist op.
|
|
121
|
+
for (const rt of ALL_OPS_LEDGER_RUNTIMES) registerToolRuntime(rt);
|
|
118
122
|
for (const rt of ALL_AUTO_RESEARCH_RUNTIMES) registerToolRuntime(rt);
|
|
119
123
|
for (const rt of ALL_INTELLIGENCE_MAP_RUNTIMES) registerToolRuntime(rt);
|
|
120
124
|
for (const rt of ALL_CFT_ANDON_RUNTIMES) registerToolRuntime(rt);
|