elanous 0.2.27 → 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/{Ev2jivDMTSoEc-5rIXdcy → 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-a5635eba0d73b84e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +1 -0
- 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-ff27902d0b11ef4f.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-25a302273b054fd7.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-87b88f551f421d8b.js → page-9eb56166774eb256.js} +1 -1
- 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/implement-loop.yaml +38 -1
- package/graphs/release/release-loop.yaml +6 -2
- package/graphs/steward/recipes.yaml +6 -0
- package/graphs/steward/release-day.yaml +23 -0
- package/graphs/steward/steward.yaml +9 -1
- package/graphs/work/code-pr.yaml +23 -0
- package/package.json +1 -1
- package/plugins/agent-team/agents/research.md +1 -0
- package/scripts/browser-observe-cycle.ts +76 -2
- package/scripts/ci-typecheck-changed.ts +53 -19
- package/scripts/coord-channel-watch.sh +26 -6
- package/scripts/coord-role-pack.ts +143 -0
- package/scripts/detect-test-interference.ts +31 -1
- package/scripts/lib/morning-report-options.ts +41 -0
- package/scripts/pr-land-extra-remote-gates.ts +49 -0
- package/scripts/release-loop/docs-node.ts +51 -22
- 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 +336 -39
- package/scripts/release-loop/gate-triage-node.ts +190 -0
- package/scripts/release-loop/node-verdict.ts +3 -1
- package/scripts/release-loop/publish-node.ts +3 -0
- package/scripts/release-loop/spawn-lane.ts +68 -0
- package/scripts/release-loop/tui-node-checks.ts +28 -2
- package/scripts/release-loop/version-node.ts +62 -4
- package/scripts/skills/public-check.ts +5 -2
- package/scripts/test-deterministic.ts +549 -37
- package/scripts/usage-rollup.ts +11 -3
- package/scripts/ux-sim.ts +7 -1
- package/scripts/verify-kpack6-live.ts +230 -0
- package/src/acp/codex-plugins.ts +17 -0
- 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/task-notification.ts +2 -1
- package/src/agent-mission/in-agent-plugin.ts +8 -3
- package/src/agent-substrate/pr-reviewer.ts +29 -21
- package/src/agent-substrate/self-review-cli.ts +34 -10
- package/src/briefing/brief-items.ts +151 -35
- package/src/budget/llm-cost.ts +25 -2
- 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/budget/usage-outcomes.ts +32 -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/claims/claims-ledger.ts +23 -0
- package/src/claims/claims-render.ts +22 -2
- package/src/cli/brief-cli.ts +131 -10
- package/src/cli/claims-cli.ts +24 -4
- 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 +210 -11
- package/src/cli/plugin-cli.ts +11 -3
- package/src/cli/pr-cli.ts +443 -104
- package/src/cli/pr-land-heavy-remote.ts +233 -0
- package/src/cli/pr-land-overlap-evidence.ts +104 -5
- package/src/cli/pr-land-refusal.ts +20 -0
- package/src/cli/pty-takeover-cli.ts +125 -16
- package/src/cli/release-cli.ts +46 -2
- package/src/cli/remote-resolve.ts +2 -1
- package/src/cli/rfc-cli.ts +24 -0
- package/src/cli/seat-cli.ts +26 -16
- package/src/cli/tailscale-serve.ts +5 -8
- package/src/cli/tasks-cli.ts +400 -27
- package/src/cli/usage-cli.ts +155 -16
- 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/first-screen-band.ts +63 -13
- package/src/dashboard/goal-loop-thinking.ts +16 -0
- package/src/dashboard/hitl-boot.ts +9 -4
- package/src/dashboard/index.ts +235 -389
- 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/skill-detection-runtime.ts +24 -4
- 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/morning-report.ts +3 -1
- 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/github/pr-labels.ts +10 -4
- package/src/graph-runner/runner.ts +102 -14
- package/src/harness/harness-clean.ts +21 -3
- package/src/harness/harness-cli-command.ts +22 -6
- package/src/harness/harness-gc.ts +32 -5
- package/src/harness/harness-pod-dispatch.ts +11 -4
- package/src/hq/seats.ts +17 -3
- package/src/index.ts +48 -6
- package/src/input/external-input-queue.ts +219 -0
- package/src/intelligence-map/model-bench-scores.ts +102 -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 +130 -0
- package/src/loops/orchestrator/resync-shadow.ts +100 -12
- package/src/loops/orchestrator/tick.ts +94 -3
- package/src/loops/registry.ts +42 -4
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/memory.ts +20 -5
- package/src/msg/msg-sse-server.ts +141 -0
- package/src/msg/msg-store.ts +84 -14
- 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/patents/ledger.ts +128 -0
- package/src/persona/presets.ts +44 -0
- package/src/plugins/install/market-fetch.ts +32 -1
- package/src/plugins/maker/wizard-generate.ts +6 -4
- package/src/pod-lease/admission.ts +116 -41
- 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/checklist.ts +11 -0
- package/src/release-loop/light-rc.ts +28 -3
- package/src/release-loop/merged-pr-checklist.ts +24 -5
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/release-loop/rubric.ts +70 -0
- package/src/render.ts +5 -1
- package/src/rfc-registry/registry.ts +88 -0
- package/src/seat-dispatch/seat-request-ledger.ts +4 -0
- package/src/seat-loop/knowhow-lint.ts +233 -0
- package/src/seat-loop/seat-pack.ts +16 -4
- package/src/seat-loop/seat-report.ts +42 -2
- package/src/seat-loop/traffic-signal.ts +7 -0
- package/src/self-dev/ask-launch-flow.ts +48 -8
- package/src/self-dev/ask-path-candidates.ts +69 -14
- package/src/self-dev/decompose-proposal.ts +43 -1
- package/src/self-dev/graph-journey-nodes.ts +2 -0
- package/src/self-dev/launch-preflight-text.ts +5 -1
- package/src/self-dev/launch-preflight.ts +143 -10
- 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 +17 -4
- package/src/self-implement/goal-author-decompose.ts +80 -16
- package/src/self-implement/goal-author.ts +116 -73
- package/src/self-implement/goal-authoring-grounding.ts +1 -1
- package/src/self-implement/goal-file-name.ts +65 -0
- package/src/self-implement/goal-new-paths.ts +4 -5
- package/src/self-implement/graph-authority.ts +17 -3
- package/src/self-implement/graph-yaml.ts +15 -7
- package/src/self-implement/ground-goal.ts +2 -1
- package/src/self-implement/headless-elanous-driver.ts +16 -1
- package/src/self-implement/host-regate.ts +58 -9
- package/src/self-implement/orchestrator.ts +3 -10
- package/src/self-implement/review-mustfix-class.ts +115 -0
- package/src/self-implement/rework-policy.ts +80 -2
- 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/self-implement/speed-claims.ts +145 -6
- 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 +103 -8
- package/src/skills/tools/shell.ts +196 -2
- package/src/status/bar.ts +32 -2
- package/src/status/status-provider-info.ts +58 -0
- package/src/steward/rejudge-tick.ts +12 -1
- package/src/steward/release-day.ts +158 -0
- package/src/steward/resync-tick.ts +123 -0
- package/src/task-agent/actions.ts +1 -0
- package/src/task-agent/adopt-pr.ts +140 -0
- package/src/task-agent/board.ts +11 -1
- package/src/task-agent/card-evidence.ts +37 -5
- package/src/task-agent/cover.ts +84 -17
- package/src/task-agent/failure-notify.ts +61 -0
- package/src/task-agent/green-sweep.ts +170 -0
- package/src/task-agent/land-worktree.ts +52 -5
- package/src/task-agent/live-move-history.ts +1 -0
- package/src/task-agent/live-moves.ts +43 -12
- package/src/task-agent/parent-host.ts +1 -1
- package/src/task-agent/postland-card.ts +139 -0
- package/src/task-agent/rejudge-on-head.ts +109 -7
- package/src/task-agent/remote-rejudge-bind.ts +91 -0
- package/src/task-agent/repair-branch-cas.ts +182 -0
- package/src/task-agent/repair-cycle.ts +288 -0
- package/src/task-agent/repair-next-move.ts +31 -0
- package/src/task-agent/repair-review.ts +24 -0
- package/src/task-agent/repair-worker.ts +87 -0
- package/src/task-agent/review-result-capture.ts +2 -1
- package/src/task-agent/shadow.ts +13 -7
- package/src/task-agent/task-hand.ts +115 -6
- 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/pod-repair-commit.ts +96 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +175 -43
- package/src/telegram.ts +30 -1
- 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 +62 -7
- package/src/ux-sim/fake-llm.ts +29 -0
- package/src/ux-sim/fault-sqlite-busy.ts +50 -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-a9c338f5bb556f42.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-a914cc0468f56143.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-a1ce306364f08da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-fcb06e305f515527.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.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-ae7aff07e32676bb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-15c0a4095baddfba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.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-76cdb531668b5191.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.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/{Ev2jivDMTSoEc-5rIXdcy → cIpv5nU9AycwYWZI9H589}/_ssgManifest.js +0 -0
package/src/task-agent/shadow.ts
CHANGED
|
@@ -15,8 +15,8 @@ import { extname, join, relative, resolve } from 'node:path';
|
|
|
15
15
|
import { debug } from '../debug/log.js';
|
|
16
16
|
import { readTaskAgentState, readTaskCard, taskAgentStatePath, TASK_CARD_PREFIX, type CompletionKind, type TaskCard } from './task-hand.js';
|
|
17
17
|
import type { SupervisorJobResult, SupervisorStopReason } from '../self-dev/run-supervisor.js';
|
|
18
|
-
import { executeNextAction, type DeliveryKind, type NextAction } from './actions.js';
|
|
19
|
-
import { judgeNextMove, type TaskJudgeInput, type TaskJudgement } from './judge.js';
|
|
18
|
+
import { executeNextAction, type ActionDeps, type DeliveryKind, type NextAction } from './actions.js';
|
|
19
|
+
import { judgeNextMove, LIVE_RETRY_MOVES, type TaskJudgeInput, type TaskJudgement } from './judge.js';
|
|
20
20
|
import { HARNESS_RUN_ID_ENV } from '../harness/harness-space.js';
|
|
21
21
|
import { appendRunLedgerEntry, loadRunLedger } from '../self-implement/run-ledger.js';
|
|
22
22
|
import { collectWiringEvidence, readCardRunSnapshot, type WiringEvidenceDeps, type CardRunEvidenceDeps } from './card-evidence.js';
|
|
@@ -57,8 +57,10 @@ export interface TaskAgentShadowMove {
|
|
|
57
57
|
|
|
58
58
|
export interface TaskAgentShadowDeps {
|
|
59
59
|
log?: (category: string, event: string, data: Record<string, unknown>) => void;
|
|
60
|
-
/**
|
|
61
|
-
command?:
|
|
60
|
+
/** 재발사 live 실행부 명령(주입되지 않으면 shadow). */
|
|
61
|
+
command?: ActionDeps['command'];
|
|
62
|
+
/** 재발사 live 부하 관문(주입되지 않으면 shadow). */
|
|
63
|
+
loadGate?: ActionDeps['loadGate'];
|
|
62
64
|
readCard?: (taskId: string) => TaskCard | undefined;
|
|
63
65
|
/** Explicit live invocation only; supervisor's default hook always uses shadow. */
|
|
64
66
|
mode?: 'shadow' | 'live';
|
|
@@ -265,6 +267,9 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
265
267
|
: { move: 'wait', stage: 'waiting', reason: '전달 후보 없음' }
|
|
266
268
|
: judgeNextMove(judgeInput);
|
|
267
269
|
if (cardLookupFailed) judgement.reason = `${judgement.reason} · 종결 종류 미확인(카드 조회 실패)`;
|
|
270
|
+
// 판단마다 해석한다 — 허용되지 않은 수를 판단할 때도 모르는 항목 경고가 남게.
|
|
271
|
+
const liveMoves = deps.liveMoves ?? await configuredTaskAgentLiveMoves();
|
|
272
|
+
const retryLaunches = { count: 0 };
|
|
268
273
|
let executorResult: string | null = null;
|
|
269
274
|
let wouldDo: string | null = null;
|
|
270
275
|
if (judgement.executorKind) {
|
|
@@ -279,10 +284,13 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
279
284
|
checklistId: delivery ? card?.checklistId ?? '' : '',
|
|
280
285
|
...(delivery ? { delivery } : {}),
|
|
281
286
|
};
|
|
287
|
+
const liveRetry = !delivery && deps.command !== undefined && deps.loadGate !== undefined
|
|
288
|
+
&& (LIVE_RETRY_MOVES as readonly string[]).includes(judgement.move) && liveMoves.has(judgement.move as TaskAgentLiveMove);
|
|
282
289
|
executorResult = await executeNextAction(action, {
|
|
283
|
-
mode: delivery ? (deps.mode ?? 'shadow') : 'shadow',
|
|
290
|
+
mode: delivery ? (deps.mode ?? 'shadow') : liveRetry ? 'live' : 'shadow',
|
|
284
291
|
command: deps.command ?? (async () => { throw new Error('task-agent shadow path must not run commands'); }),
|
|
285
292
|
observe: (_event, data) => { wouldDo = data.reason; },
|
|
293
|
+
...(liveRetry ? { liveMoves, retryLaunches, loadGate: deps.loadGate } : {}),
|
|
286
294
|
});
|
|
287
295
|
}
|
|
288
296
|
const move: TaskAgentShadowMove = {
|
|
@@ -305,8 +313,6 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
305
313
|
move.wouldDo = null;
|
|
306
314
|
}
|
|
307
315
|
const liveKind: TaskAgentLiveMove | null = move.move === 'review' || move.move === 'propose-green' || move.move === 'propose-land' || move.move === 'decision-card' ? move.move : null;
|
|
308
|
-
// 판단마다 해석한다 — 허용되지 않은 수를 판단할 때도 모르는 항목 경고가 남게.
|
|
309
|
-
const liveMoves = deps.liveMoves ?? await configuredTaskAgentLiveMoves();
|
|
310
316
|
// 카드 id 는 모든 판단 관측에 싣는다(그림자 일치율을 카드로 잇는다) — 읽기 전용 조회.
|
|
311
317
|
// live 수는 «근거 결과»에 묶는다 — PR 수는 그 PR 을 낸 결과의 카드·작업 트리, 전달은 전달한 카드(다중 결과에서 남의 카드에 쓰지 않게).
|
|
312
318
|
const prResult = typeof judgeInput.pr === 'number' ? input.results.find((result) => result.prNumber === judgeInput.pr) : undefined;
|
|
@@ -11,6 +11,10 @@ import { execFileSync } from 'node:child_process';
|
|
|
11
11
|
import { createHash, randomBytes } from 'node:crypto';
|
|
12
12
|
import { mkdirSync, readFileSync, statSync, writeFileSync, type Stats } from 'node:fs';
|
|
13
13
|
import { dirname, join, resolve } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { parse as parseYaml } from 'yaml';
|
|
16
|
+
import { validateUnitCalls } from '../graph-runner/runner.js';
|
|
17
|
+
import { parseGraphTemplateYaml } from '../self-implement/graph-yaml.js';
|
|
14
18
|
import { resolveDaemonHarnessTarget } from '../intake-plane/harness-target.js';
|
|
15
19
|
import { HARNESS_RUN_ID_ENV, mintRunId, normalizeRunId } from '../harness/harness-space.js';
|
|
16
20
|
import { debug } from '../debug/log.js';
|
|
@@ -89,6 +93,66 @@ export function taskCardLabelContext(card: Pick<TaskCard, 'id'>): TaskCardLabelC
|
|
|
89
93
|
export const COMPLETION_KINDS = ['code-pr', 'artifact', 'research-report', 'ops-action', 'content', 'watch-brief', 'decision-support', 'deliverable'] as const;
|
|
90
94
|
export type CompletionKind = typeof COMPLETION_KINDS[number];
|
|
91
95
|
|
|
96
|
+
export interface TaskComposition {
|
|
97
|
+
file: string;
|
|
98
|
+
/** null = 파일은 있으나 파싱 실패로 판을 확인하지 못했다. */
|
|
99
|
+
version: number | null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface CompositionSelection {
|
|
103
|
+
composition?: TaskComposition;
|
|
104
|
+
unitsResolved: boolean;
|
|
105
|
+
missingUnits: string[];
|
|
106
|
+
launcher?: 'harness-say' | 'graph-run';
|
|
107
|
+
error?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** 1판은 조합을 고르고 단위 해석 결과를 기록한다. 단위 실행은 2판의 몫이다. */
|
|
111
|
+
export function selectTaskComposition(completion: CompletionKind, root = join(dirname(fileURLToPath(import.meta.url)), '..', '..')): CompositionSelection {
|
|
112
|
+
const file = `graphs/work/${completion}.yaml`;
|
|
113
|
+
const path = join(root, file);
|
|
114
|
+
let source: string;
|
|
115
|
+
try { source = readFileSync(path, 'utf8'); } catch (error) {
|
|
116
|
+
if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return { unitsResolved: false, missingUnits: [] };
|
|
117
|
+
return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
|
|
118
|
+
error: `조합 읽기 오류: ${file}: ${error instanceof Error ? error.message : String(error)}` };
|
|
119
|
+
}
|
|
120
|
+
const parsed = parseGraphTemplateYaml(source, path);
|
|
121
|
+
if (!parsed.template || parsed.errors.length) {
|
|
122
|
+
let version: number | null = null;
|
|
123
|
+
try {
|
|
124
|
+
const raw: unknown = parseYaml(source);
|
|
125
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
|
|
126
|
+
const candidate = (raw as Record<string, unknown>).version;
|
|
127
|
+
if (typeof candidate === 'number' && Number.isInteger(candidate)) version = candidate;
|
|
128
|
+
}
|
|
129
|
+
} catch { /* 파싱 실패 자체를 아래 원장에 적는다. */ }
|
|
130
|
+
return { composition: { file, version }, unitsResolved: false, missingUnits: [],
|
|
131
|
+
error: `조합 오류: ${file}: ${parsed.errors.map(e => e.message).join('; ')}` };
|
|
132
|
+
}
|
|
133
|
+
const raw: unknown = parseYaml(source);
|
|
134
|
+
const launcher = raw && typeof raw === 'object' && !Array.isArray(raw) ? (raw as Record<string, unknown>).launcher : undefined;
|
|
135
|
+
if (launcher !== undefined && launcher !== 'harness-say' && launcher !== 'graph-run') {
|
|
136
|
+
return { composition: { file, version: parsed.template.version }, unitsResolved: false, missingUnits: [],
|
|
137
|
+
error: `조합 오류: ${file}: 모르는 launcher` };
|
|
138
|
+
}
|
|
139
|
+
if (completion === 'code-pr' && launcher === undefined) {
|
|
140
|
+
return { composition: { file, version: parsed.template.version }, unitsResolved: false, missingUnits: [],
|
|
141
|
+
error: `조합 오류: ${file}: launcher 없음` };
|
|
142
|
+
}
|
|
143
|
+
const missingUnits: string[] = [];
|
|
144
|
+
let unitError: string | undefined;
|
|
145
|
+
try { validateUnitCalls(parsed.template, path, [], call => missingUnits.push(call)); }
|
|
146
|
+
catch (error) { unitError = error instanceof Error ? error.message : String(error); }
|
|
147
|
+
return {
|
|
148
|
+
composition: { file, version: parsed.template.version },
|
|
149
|
+
unitsResolved: missingUnits.length === 0 && !unitError,
|
|
150
|
+
missingUnits,
|
|
151
|
+
...(launcher === 'harness-say' || launcher === 'graph-run' ? { launcher } : {}),
|
|
152
|
+
...(unitError ? { error: `조합 단위 해석 오류: ${file}: ${unitError}` } : {}),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
92
156
|
/**
|
|
93
157
|
* `run-bound`·`goal-bound`·`pr-bound` 은 runId(⊕ pr)를 싣는다 — 옛 카드의 칸은 at·event·detail 뿐이다.
|
|
94
158
|
* TA-LIVE-MOVE-CARD-HISTORY — `live-move` 줄만 kind·executed·ok·executorResult·head·effect 를 더 싣는다(`live-move-history.ts`).
|
|
@@ -104,6 +168,8 @@ export interface TaskCardEvent {
|
|
|
104
168
|
resultPath?: string;
|
|
105
169
|
/** TA-REVIEW-RESULT-CAPTURE — `live-move-result` 줄만: 회수한 `self review --json` 의 칸(못 읽은 칸은 null). */
|
|
106
170
|
verdict?: string | null; reviewed?: boolean | null; mustFix?: number | null; reviewRoute?: string | null;
|
|
171
|
+
/** Exact bytes of the captured review stdout; repair must read the same resultPath and digest. */
|
|
172
|
+
reviewSha256?: string;
|
|
107
173
|
}
|
|
108
174
|
/** 카드 history 의 live-move 줄 이벤트 이름 — 상태 사유(«마지막 칸») 판정에서 뺀다. */
|
|
109
175
|
export const LIVE_MOVE_HISTORY_EVENT = 'live-move';
|
|
@@ -117,8 +183,15 @@ export interface TaskCard {
|
|
|
117
183
|
text: string;
|
|
118
184
|
seat?: TaskSeat;
|
|
119
185
|
checklistId?: string;
|
|
186
|
+
/** Explicit release version for an adopted PR; post-land still confirms the cell exists there. */
|
|
187
|
+
checklistVersion?: string;
|
|
120
188
|
/** 종결 종류 — 비면 code-pr. */
|
|
121
189
|
completion?: CompletionKind;
|
|
190
|
+
/** 선택된 일 조합 파일과 판(1판: 실행은 launcher 에 위임). */
|
|
191
|
+
composition?: TaskComposition;
|
|
192
|
+
graphSelectedBy?: 'completion';
|
|
193
|
+
unitsResolved?: boolean;
|
|
194
|
+
missingUnits?: string[];
|
|
122
195
|
/** 과제 대상 프로젝트(§A4b②) — target 은 절대 경로(git 이 아닐 수 있다). id 는 `task hand --project` 가 싣는다(옛 카드엔 없을 수 있다). */
|
|
123
196
|
project?: { id?: string; target: string };
|
|
124
197
|
/** 보드(§A4b① `board.ts`) 소속 — 목표 id · 이정표 id(`task hand --goal/--milestone`). 조각 카드의 `goalId`(골 sha 16자)와 다른 칸이다. */
|
|
@@ -130,7 +203,7 @@ export interface TaskCard {
|
|
|
130
203
|
* failed = 발사된 런이 PR·수확 가지 없이 죽었거나 끝내 안 떴다(TA-JUDGE-DEAD-RUN · `card-evidence.ts`) — 사유
|
|
131
204
|
* (`failed/needs-owner|needs-relaunch — …`)는 history 마지막 칸 · 자동 재발사하지 않는다(사람/판단부 몫).
|
|
132
205
|
*/
|
|
133
|
-
status: 'handed' | 'launched' | 'launch-failed' | 'failed';
|
|
206
|
+
status: 'handed' | 'launched' | 'launch-failed' | 'failed' | 'done';
|
|
134
207
|
history: TaskCardEvent[];
|
|
135
208
|
/** 미션 카드만 — 조각 카드 id(순서대로) · 쪼갠 출처(`mission.ts` splitMission). */
|
|
136
209
|
pieces?: string[];
|
|
@@ -145,6 +218,12 @@ export interface TaskCard {
|
|
|
145
218
|
* 번호는 `cardPrNumber` 로 읽는다(옛 카드의 number 도 그대로 읽힌다).
|
|
146
219
|
*/
|
|
147
220
|
pr?: number | TaskCardPr;
|
|
221
|
+
/** Host-verified existing OPEN PR adopted without launching a new implementation run. */
|
|
222
|
+
adoptedPr?: { pr: number; url: string; head: string; at: string };
|
|
223
|
+
/** Bound PR observed in a terminal GitHub state. Only applies while the card still binds the same PR and URL. */
|
|
224
|
+
prTerminal?: { pr: number; url: string; head: string; state: 'MERGED' | 'CLOSED'; at: string };
|
|
225
|
+
/** Post-land checklist judgement. A partial slice closes this card while leaving the checklist cell yellow. */
|
|
226
|
+
postLand?: { pr: number; head: string; at: string; outcome: 'complete' | 'partial'; evidence: string[]; remaining: string[] };
|
|
148
227
|
goalId?: string;
|
|
149
228
|
/** `manual` = pr/goalId 를 사람이 적었다(`recordPieceRef`) — 런 묶기가 건드리지 않는다. */
|
|
150
229
|
refSource?: 'manual';
|
|
@@ -185,6 +264,10 @@ export interface TaskCard {
|
|
|
185
264
|
taLand?: true;
|
|
186
265
|
/** TASKS-HAND-CHILD-LLM — `tasks hand --child-llm <provider>/<model> [--child-llm-effort <level>]` → 발사 인자 `--child-llm-provider/-model/-effort`. */
|
|
187
266
|
childLlm?: TaskChildLlm;
|
|
267
|
+
/** Same-PR repair launches; exact source head and worker result are retained for CAS and retry limits. */
|
|
268
|
+
repairs?: Array<{ pr: number; head: string; branch: string; at: string; move: string; runId: string;
|
|
269
|
+
resultPath: string; fromModel: string; toModel: string; status: 'requested' | 'unconfirmed' | 'failed' | 'applied';
|
|
270
|
+
detail?: string; commit?: string; bundleSha256?: string; bundlePath?: string }>;
|
|
188
271
|
}
|
|
189
272
|
|
|
190
273
|
/** 구현 자식 LLM 선택 — 하니스 `--child-llm-provider/--child-llm-model/--child-llm-effort` 로 그대로 넘긴다(검증 권위는 하니스). */
|
|
@@ -215,6 +298,12 @@ export function cardPrNumber(card: Pick<TaskCard, 'pr'>): number | undefined {
|
|
|
215
298
|
return typeof card.pr === 'number' ? card.pr : card.pr?.number;
|
|
216
299
|
}
|
|
217
300
|
|
|
301
|
+
/** A stale terminal marker must never close a card after its PR binding changes. */
|
|
302
|
+
export function boundPrTerminal(card: Pick<TaskCard, 'pr' | 'prTerminal'>): TaskCard['prTerminal'] | undefined {
|
|
303
|
+
const marker = card.prTerminal;
|
|
304
|
+
return marker && typeof card.pr === 'object' && card.pr.number === marker.pr && card.pr.url === marker.url ? marker : undefined;
|
|
305
|
+
}
|
|
306
|
+
|
|
218
307
|
/** A uniquely launched code-PR card may own a draft through its PR or its opening run. */
|
|
219
308
|
export function draftTaskOwner(cards: readonly TaskCard[], draft: { number: number; runId?: string | null }): TaskCard | undefined {
|
|
220
309
|
const owners = cards.filter((card) => card.status === 'launched' && (card.completion ?? 'code-pr') === 'code-pr'
|
|
@@ -374,6 +463,8 @@ export interface HandTaskOptions {
|
|
|
374
463
|
childLlm?: string;
|
|
375
464
|
childLlmEffort?: string;
|
|
376
465
|
statePath?: string;
|
|
466
|
+
/** 시험에서만 조합 저장소를 바꿔 해석·거부를 검증한다. */
|
|
467
|
+
compositionRoot?: string;
|
|
377
468
|
/** `--live` 일 때만 불린다. */
|
|
378
469
|
launcher?: TaskLauncher;
|
|
379
470
|
now?: () => Date;
|
|
@@ -443,6 +534,11 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
443
534
|
}
|
|
444
535
|
if (opts.childLlmEffort !== undefined && opts.childLlm === undefined) throw new Error('--child-llm-effort 는 --child-llm <provider>/<model> 과 함께 준다');
|
|
445
536
|
const childLlm = opts.childLlm !== undefined ? parseChildLlm(opts.childLlm, opts.childLlmEffort) : undefined;
|
|
537
|
+
const completion = opts.completion ?? 'code-pr';
|
|
538
|
+
const selected = selectTaskComposition(completion, opts.compositionRoot);
|
|
539
|
+
const selectionFailure = !selected.composition ? `조합 없음: graphs/work/${completion}.yaml`
|
|
540
|
+
: selected.error ?? (completion !== 'code-pr' || selected.launcher !== 'harness-say'
|
|
541
|
+
? `조합 실행기 없음: ${selected.composition.file} (1판은 code-pr harness-say만 발사)` : undefined);
|
|
446
542
|
let project: TaskCard['project'];
|
|
447
543
|
let targetIsGit: boolean | null = null;
|
|
448
544
|
if (opts.project) {
|
|
@@ -467,19 +563,25 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
467
563
|
...(opts.seat ? { seat: opts.seat } : {}),
|
|
468
564
|
...(opts.checklistId ? { checklistId: opts.checklistId } : {}),
|
|
469
565
|
...(opts.completion ? { completion: opts.completion } : {}),
|
|
566
|
+
...(selected.composition ? { composition: selected.composition, graphSelectedBy: 'completion' as const } : {}),
|
|
567
|
+
unitsResolved: selected.unitsResolved,
|
|
568
|
+
missingUnits: selected.missingUnits,
|
|
470
569
|
...(project ? { project } : {}),
|
|
471
570
|
...(opts.goal ? { goal: opts.goal } : {}),
|
|
472
571
|
...(opts.milestone ? { milestone: opts.milestone } : {}),
|
|
473
572
|
...(opts.taLand === true ? { taLand: true as const } : {}),
|
|
474
573
|
...(childLlm ? { childLlm } : {}),
|
|
475
574
|
createdAt: now.toISOString(),
|
|
476
|
-
status: 'handed',
|
|
477
|
-
history: [
|
|
575
|
+
status: selectionFailure ? 'failed' : 'handed',
|
|
576
|
+
history: selectionFailure ? [{ at: now.toISOString(), event: !selected.composition ? 'composition-missing'
|
|
577
|
+
: selected.error ? 'composition-invalid' : 'composition-launcher-unavailable', detail: selectionFailure }] : [],
|
|
478
578
|
...(opts.mission ? { mission: opts.mission, after: [...(opts.after ?? [])] } : {}),
|
|
479
|
-
...(opts.cardFields
|
|
579
|
+
...(opts.cardFields?.pr !== undefined ? { pr: opts.cardFields.pr } : {}),
|
|
580
|
+
...(opts.cardFields?.goalId !== undefined ? { goalId: opts.cardFields.goalId } : {}),
|
|
581
|
+
...(opts.cardFields?.handed !== undefined ? { handed: opts.cardFields.handed } : {}),
|
|
480
582
|
};
|
|
481
|
-
const move = nextMoveFor(card, opts.landed);
|
|
482
|
-
if (move.kind !== 'launch') throw new Error(`발사할 수 없는 과제다 — ${move.reason}`);
|
|
583
|
+
const move = selectionFailure ? undefined : nextMoveFor(card, opts.landed);
|
|
584
|
+
if (move && move.kind !== 'launch') throw new Error(`발사할 수 없는 과제다 — ${move.reason}`);
|
|
483
585
|
const guard = opts.writeGuard;
|
|
484
586
|
const writeCard = (target: string, next: TaskCard): void => {
|
|
485
587
|
if (!guard) { writeTaskCards(target, [next]); return; }
|
|
@@ -495,6 +597,13 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
495
597
|
if (!owned.ok) throw new TaskCardSupersededError(next.id);
|
|
496
598
|
};
|
|
497
599
|
writeCard(path, card);
|
|
600
|
+
try { debug.log('task-agent.graph-select', !selected.composition ? 'composition-missing' : selected.error ? 'composition-invalid' : 'composition-selected', {
|
|
601
|
+
completion, file: selected.composition?.file ?? `graphs/work/${completion}.yaml`,
|
|
602
|
+
unitsResolved: selected.unitsResolved, missingUnits: selected.missingUnits,
|
|
603
|
+
...(selected.error ? { error: selected.error } : {}),
|
|
604
|
+
}); } catch { /* fail-soft */ }
|
|
605
|
+
if (selectionFailure) throw new Error(`${selectionFailure} (카드 ${id})`);
|
|
606
|
+
if (!move || move.kind !== 'launch') throw new Error('조합 선택 뒤 발사 수가 없다');
|
|
498
607
|
try { debug.log('task-agent', 'handed', { taskId: id, seat: card.seat ?? null, checklistId: card.checklistId ?? null, mode, projectId: project?.id ?? null, targetIsGit, taLand: card.taLand === true }); } catch { /* fail-soft */ }
|
|
499
608
|
if (childLlm) {
|
|
500
609
|
try { debug.log('task-agent', 'child-llm', { taskId: id, input: opts.childLlm, provider: childLlm.provider, model: childLlm.model, effort: childLlm.effort ?? null, mode }); } catch { /* fail-soft */ }
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K3S-SECRET-DB-LOCK-RETRY — kubectl 호출이 «일시 오류»로 거부되면 지수 백오프로 다시 친다.
|
|
3
|
+
*
|
|
4
|
+
* 근거: node-b k3d(k3s · sqlite 저장소)가 Pod Secret 생성 때
|
|
5
|
+
* `Error from server: error when creating "STDIN": rpc error: code = Unknown desc = database is locked`
|
|
6
|
+
* 로 거부했다(10-15 02:11 KST 전후 4건 · TC #4186). sqlite 쓰기 잠금 경합이라 잠시 뒤 같은 apply 는 선다.
|
|
7
|
+
*
|
|
8
|
+
* ⛔ 판정 문구는 «실측 근거가 있는 것»만 둔다 — 짐작으로 늘리면 진짜 거부(권한·스키마)를 백오프 동안 삼킨다.
|
|
9
|
+
* 재시도 소진 시에만 호출부의 기존 실패 경로로 마지막 결과를 그대로 돌려준다.
|
|
10
|
+
*/
|
|
11
|
+
import { debug } from '../../debug/log.js';
|
|
12
|
+
|
|
13
|
+
export type KubectlCallResult = { status: number | null; stdout: string; stderr: string };
|
|
14
|
+
|
|
15
|
+
/** 실측된 일시 오류 문구(stderr 만 · 부분 일치 · 대소문자 무시 — stdout 은 apply 결과라 판정에 안 쓴다). */
|
|
16
|
+
export const KUBECTL_TRANSIENT_PATTERNS: readonly RegExp[] = [/database is locked/i];
|
|
17
|
+
|
|
18
|
+
/** 재시도 사이 대기(ms) — 길이가 곧 재시도 상한(4회 · 합 7.5s). */
|
|
19
|
+
export const KUBECTL_TRANSIENT_BACKOFF_MS: readonly number[] = [500, 1_000, 2_000, 4_000];
|
|
20
|
+
|
|
21
|
+
export function kubectlTransientReason(result: KubectlCallResult): string | null {
|
|
22
|
+
if (result.status === 0) return null;
|
|
23
|
+
const hit = KUBECTL_TRANSIENT_PATTERNS.find((pattern) => pattern.test(result.stderr));
|
|
24
|
+
return hit ? hit.source : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 첫 결과 `first` 가 일시 오류일 때만 부른다(성공 경로에 await 를 더하지 않으려고 — 호출부의 마이크로태스크 순서를 지킨다).
|
|
29
|
+
* 다시 친 결과가 성공이거나 일시 오류가 아니면 즉시 돌려주고, 백오프를 다 써도 일시 오류면 마지막 결과를 돌려준다.
|
|
30
|
+
*/
|
|
31
|
+
export async function retryKubectlTransient(
|
|
32
|
+
run: () => KubectlCallResult,
|
|
33
|
+
first: KubectlCallResult,
|
|
34
|
+
opts: { sleep: (ms: number) => Promise<void>; category: string; data?: Record<string, unknown>; backoffMs?: readonly number[] },
|
|
35
|
+
): Promise<KubectlCallResult> {
|
|
36
|
+
const backoff = opts.backoffMs ?? KUBECTL_TRANSIENT_BACKOFF_MS;
|
|
37
|
+
let last = first;
|
|
38
|
+
let reason = kubectlTransientReason(last);
|
|
39
|
+
for (let i = 0; i < backoff.length && reason; i++) {
|
|
40
|
+
debug.log(opts.category, 'retry', { ...opts.data, attempt: i + 1, maxAttempts: backoff.length, delayMs: backoff[i], reason });
|
|
41
|
+
await opts.sleep(backoff[i]!);
|
|
42
|
+
last = run();
|
|
43
|
+
reason = kubectlTransientReason(last);
|
|
44
|
+
if (last.status === 0) {
|
|
45
|
+
debug.log(opts.category, 'retry-recovered', { ...opts.data, attempt: i + 1 });
|
|
46
|
+
return last;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (reason) debug.log(opts.category, 'retry-exhausted', { ...opts.data, attempts: backoff.length, reason, stderr: last.stderr.trim().slice(0, 300) }, { level: 'warn' });
|
|
50
|
+
return last;
|
|
51
|
+
}
|
|
@@ -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(); }
|