elanous 0.2.37 → 0.2.40
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/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 1060.014f1f01a17aec26.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 1281.d81877e35b9068f4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +286 -0
- package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +90 -0
- package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{3578.4e9f9948a9a6f2f4.js → 2047.8f23e210995d4548.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 2066.a77257c8c350770a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 2177.df8547f9d7215c4e.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 2226.2cf61ec781827219.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 2522.f2766b76d22c8bdf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +226 -0
- package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +27 -0
- package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2318-450e75d07605b8fe.js → 2774-719820e3f5b2a3eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4725-34bed25720cc326b.js → 2829-734fe8bf2eee7347.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3746-f80a78f220bf37b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +24 -0
- package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → 3b355b3d.6f73c98bf6f9c749.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +36 -0
- package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 409c787b.e48c5bec8ec10456.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +287 -0
- package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4351.0f37a6db2b34d50b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 470.51a72a2348306455.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 4769.9fd582071301f382.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 4864a2ca.1c1c280a7772c5e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +74 -0
- package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 5383.bdfa5d886e39a826.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5436.fdf6fa8ae3e9588d.js +64 -0
- package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +62 -0
- package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +94 -0
- package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 6051-0ae955eedb10adb9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 6257.c0037b8949239f5e.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +32 -0
- package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 6749.0744ce6eb08d40e9.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +148 -0
- package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +93 -0
- package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 8272-025653884f9645d2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 8357.1aaa713b052a78b1.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4313.76f232c304a15bde.js → 9175.2de5209a5ce6f68a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → 9189505a.980427ac048c8c60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +79 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-3337c6a1328c2674.js → page-4edb8df90f4537ce.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-1e5da297557d2354.js → page-fca2e59a81744d9e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-ac2c1e6169cfce57.js → page-139d722de1dcd6c1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-c1c80e345fa9d6f5.js → page-ccde99f07aaf71f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b84cad00.594027ebe0531fe2.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → ca3702f8.2913182e73889fa2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.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/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
- package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
- package/graphs/demo/persona-marketer/recipes.yaml +19 -0
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/graphs/video/explainer-line.yaml +4 -1
- package/package.json +1 -1
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/brand/check.ts +13 -4
- package/scripts/dead-code/report.ts +169 -0
- package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +39 -0
- package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/lib/morning-report-options.ts +3 -4
- package/scripts/lib/tui-regress-evidence.ts +56 -0
- package/scripts/morning-report.ts +5 -1
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +77 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- package/scripts/release-loop/export-check-node.ts +21 -3
- package/scripts/release-loop/gate-node.ts +527 -60
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
- package/scripts/release-loop/gate-shard-receipts.ts +89 -0
- package/scripts/release-loop/gate-wall.ts +5 -5
- package/scripts/release-loop/preflight.ts +6 -2
- package/scripts/release-loop/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +317 -13
- package/scripts/release-loop/resume.ts +61 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +35 -5
- package/scripts/release-story/draft.ts +1 -1
- package/scripts/research-bench/README.md +53 -0
- package/scripts/research-bench/questions.json +66 -0
- package/scripts/research-bench/rubric.md +33 -0
- package/scripts/research-bench/run.ts +523 -0
- package/scripts/tui-regress.ts +85 -10
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/core-turn-bridge.ts +14 -1
- package/src/agent/autonomous-tools.ts +10 -3
- package/src/agent/monad-agent-turn.ts +4 -1
- package/src/agent/registry.ts +26 -2
- package/src/agent/run-context.ts +1 -1
- package/src/agent/shared-app-tools.ts +1 -1
- package/src/agent/surface-ux/build.ts +12 -3
- package/src/agent/surface-ux/types.ts +1 -1
- package/src/agent/task-notification.ts +78 -7
- package/src/agent/types.ts +3 -0
- package/src/agent-mission/driver.ts +29 -3
- package/src/agent-mission/mission-cli.ts +2 -1
- package/src/agent-substrate/review-context-pack.ts +365 -0
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +419 -42
- package/src/ask-user-question/index.ts +6 -0
- package/src/ask-user-question/inline-resolver.ts +49 -0
- package/src/auto-research/question-ladder-contract.ts +156 -0
- package/src/auto-research/research-turn.ts +467 -0
- package/src/autopilot/agent-loop.ts +1 -1
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/autopilot/pty-control-loop.ts +8 -1
- package/src/boot/daemon-tools/index.ts +4 -3
- package/src/boot/daemon-tools/self-implement.ts +270 -2
- package/src/boot/daemon-tools/types.ts +2 -0
- package/src/bots/screen-probe.ts +1 -1
- package/src/budget/llm-cost.ts +44 -5
- package/src/budget/unified-usage.ts +17 -1
- package/src/capture/tui-self-report.ts +24 -2
- package/src/chat/index.ts +34 -7
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/agent-cli.ts +43 -8
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +70 -13
- package/src/cli/lesson-cli.ts +86 -10
- package/src/cli/log-event-names.ts +1 -0
- package/src/cli/pod-cli.ts +17 -2
- package/src/cli/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +125 -12
- package/src/cli/release-checklist-read-cli.ts +5 -2
- package/src/cli/release-cli.ts +99 -15
- package/src/cli/repo-cli.ts +2 -1
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +1 -1
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +98 -32
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/context-bus/context-now.ts +86 -2
- package/src/control-plane/ledger.ts +21 -4
- package/src/core-turn/run-core-turn.ts +51 -3
- package/src/core-turn/run-goal-loop.ts +152 -8
- package/src/core-turn/types.ts +12 -0
- package/src/dashboard/chat/acp-chat.ts +2 -2
- package/src/dashboard/classic-sigquit.ts +16 -0
- package/src/dashboard/index.ts +339 -44
- package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
- package/src/dashboard/input/chat-main-slash-command.ts +7 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
- package/src/dashboard/input/external-input-host.ts +2 -0
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/sidetab-runtime.ts +228 -0
- package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +22 -8
- package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
- package/src/dashboard/term-slash-runtime.ts +18 -18
- package/src/dashboard/turn-preamble.ts +30 -4
- package/src/domains/guardian-tick.ts +9 -0
- package/src/domains/knowledge.ts +1 -1
- package/src/esc-abort-gate.ts +33 -1
- package/src/execution-loop/launch-gate.ts +206 -1
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-cli.ts +6 -4
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/runner.ts +48 -11
- package/src/graph-wizard/generate.ts +16 -7
- package/src/graph-wizard/mission-compose.ts +201 -0
- package/src/grok/agent-search.ts +8 -2
- package/src/grok/credential.ts +112 -36
- package/src/grounding/ref-index.ts +11 -0
- package/src/grounding/ref-vector.ts +61 -0
- package/src/grounding/sources-cli.ts +2 -2
- package/src/grounding/sources.ts +15 -1
- package/src/harness/harness-cli-command.ts +38 -9
- package/src/harness/harness-pod-dispatch.ts +7 -1
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +60 -16
- package/src/input/external-input-queue.ts +10 -0
- package/src/intake-plane/collect-telegram-saved.ts +90 -6
- package/src/intake-plane/intake-to-tasks.ts +246 -3
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/lessons/friction-ledger.ts +154 -0
- package/src/live-supply/collector.ts +149 -0
- package/src/live-supply/probes.ts +52 -0
- package/src/live-supply/snapshot.ts +40 -0
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm-tool-schema.ts +20 -0
- package/src/llm.ts +486 -61
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +14 -3
- package/src/maturity/feature-maturity.ts +1 -0
- package/src/nexus/api/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -1
- package/src/nexus/api/harness-api.ts +2 -1
- package/src/nexus/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -6
- package/src/patents/ledger.ts +18 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +5 -0
- package/src/pty/snapshot.py +132 -0
- package/src/pty-shell/pty-control-ipc.ts +29 -2
- package/src/pty-shell/pty-manifest.ts +75 -5
- package/src/pty-shell/registry.ts +2 -0
- package/src/pty-shell/tui-run-state.ts +80 -3
- package/src/release-loop/gate-host-reservation.ts +13 -4
- package/src/release-loop/gate-shard-ledger.ts +68 -0
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/merged-pr-checklist.ts +25 -2
- package/src/release-loop/rehearsal-shard-plan.ts +6 -1
- package/src/release-loop/rehearsal.ts +28 -1
- package/src/repl/index.ts +10 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +197 -0
- package/src/research/gap-followup.ts +249 -0
- package/src/research/lenses/counter-evidence.ts +100 -0
- package/src/research/lenses/working-backwards.ts +89 -0
- package/src/research/output-router.ts +127 -0
- package/src/research/plugin-discovery.ts +242 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +45 -7
- package/src/research-bridge/types.ts +2 -0
- package/src/self-dev/ask-launch-flow.ts +34 -106
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/dev-cli.ts +2 -0
- package/src/self-dev/dev-pipeline.ts +8 -4
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +29 -16
- package/src/self-dev/graph-journey-route.ts +10 -2
- package/src/self-dev/launch-preflight-text.ts +2 -2
- package/src/self-dev/launch-preflight.ts +38 -7
- package/src/self-dev/orchestrate-cli.ts +1 -0
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/run-supervisor.ts +41 -7
- package/src/self-dev/shard-run.ts +260 -3
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/device-first.ts +8 -2
- package/src/self-implement/doctor-visit.ts +100 -57
- package/src/self-implement/gate-artifacts.ts +5 -2
- package/src/self-implement/gate-baseline.ts +119 -13
- package/src/self-implement/gate-cli.ts +466 -93
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-receipt-registry.ts +180 -0
- package/src/self-implement/gate-remote.ts +147 -22
- package/src/self-implement/goal-author-clarification.ts +178 -24
- package/src/self-implement/goal-author-decompose.ts +24 -15
- package/src/self-implement/goal-author.ts +82 -7
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +38 -4
- package/src/self-implement/host-regate.ts +120 -45
- package/src/self-implement/impl-findings-feedback.ts +188 -0
- package/src/self-implement/knowhow-pack.ts +301 -9
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +147 -0
- package/src/self-implement/orchestrator.ts +137 -16
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- package/src/self-implement/run-ledger.ts +304 -8
- package/src/self-implement/run-stop.ts +12 -0
- package/src/self-implement/seams.ts +39 -13
- package/src/self-implement/self-implement-cli.ts +30 -4
- package/src/session/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +92 -15
- package/src/session/index.ts +2 -0
- package/src/session-runtime/index.ts +9 -22
- package/src/session-runtime/provider-circuit.ts +140 -0
- package/src/shell-runner/file-engine.ts +1 -0
- package/src/shell-runner/types.ts +4 -0
- package/src/sidetab-core/model.ts +176 -0
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/schedule-wakeup.ts +24 -7
- package/src/skills/tools/shell.ts +51 -5
- package/src/status/bar.ts +3 -3
- package/src/steward/directive-audit.ts +354 -0
- package/src/storage/file-lock.ts +17 -4
- package/src/surface/child-process.ts +31 -0
- package/src/surface/tui-stderr-owner.ts +48 -0
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/cover.ts +30 -12
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/judge.ts +56 -0
- package/src/task-agent/parent-host.ts +59 -12
- package/src/task-agent/postland-card.ts +35 -2
- package/src/task-agent/rejudge-on-head.ts +46 -2
- package/src/task-agent/repair-cycle.ts +68 -9
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/task-hand.ts +226 -33
- package/src/task-agent/tier-split.ts +142 -24
- package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
- package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +57 -5
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
- package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
- package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +310 -79
- package/src/task-orchestrator/surfaces/self-implement.ts +33 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tool-runtime/skill-exec-runtime.ts +95 -5
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/entry.ts +483 -32
- package/src/tui/inline-choice.ts +188 -0
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +2 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +3 -23
- package/src/tui/slash/term-next.ts +2 -1
- package/src/tui/slash/term.ts +12 -1
- package/src/tui-client/dashboard-session.ts +7 -1
- package/src/tui-client/local-chat-turn.ts +29 -8
- package/src/user-config.ts +42 -3
- package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
- package/src/ux-sim/fake-land-queue.ts +88 -0
- package/src/ux-sim/fake-llm.ts +11 -5
- package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
- package/src/ux-sim/goal-interim-trace.ts +24 -0
- package/src/ux-sim/next-tui-seat-scenarios.ts +61 -14
- package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/explainer.ts +54 -2
- package/src/web-search/grok.ts +32 -6
- package/src/web-search/index.ts +8 -7
- package/src/workflow-runtime/node-catalog.ts +53 -4
- package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +0 -62
- package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +0 -32
- package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +0 -148
- package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +0 -27
- package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3199.6a1a9b0e6cd01dc6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +0 -36
- package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +0 -90
- package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +0 -287
- package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +0 -1
- package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5952.294fc574a8625184.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +0 -149
- package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +0 -41
- package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +0 -1
- package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +0 -1
- package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7c5ed21f-f286708e57cf88f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8080-40d781e7704d3671.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +0 -77
- package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +0 -1
- package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +0 -286
- package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +0 -79
- package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +0 -94
- package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +0 -1
- package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +0 -64
- package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +0 -1
- package/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
|
@@ -33,6 +33,7 @@ import { mintRunId, normalizeRunId } from '../../harness/harness-space.js';
|
|
|
33
33
|
import { TA_LAND_ENV } from '../../task-agent/task-hand.js';
|
|
34
34
|
import { appendRunLedgerEntry, loadRunLedger, runLedgerDir, runLedgerPath, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
|
|
35
35
|
import { recordRunStop } from '../../self-implement/run-stop.js';
|
|
36
|
+
import { gateFailureReceipt, gateFailureReceiptLines } from '../../self-implement/gate-failure-signature.js';
|
|
36
37
|
import { runSuffixKey } from '../../self-implement/salvage-branches.js';
|
|
37
38
|
import type { GoalExecutionRecord } from '../../self-implement/orchestrator.js';
|
|
38
39
|
import { hostRepositoryUnavailable, runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
|
|
@@ -46,7 +47,7 @@ import { executeSiWarmTransport, type SiWarmFixedRunner,
|
|
|
46
47
|
type SiWarmPodIdentity } from './pod-si-warm-transport.js';
|
|
47
48
|
|
|
48
49
|
export const POD_CONTROL_INBOX_DIR = '/tmp/elanous-control.inbox';
|
|
49
|
-
/** Pod Job 수명 상한(`activeDeadlineSeconds`) —
|
|
50
|
+
/** Pod Job 수명 상한(`activeDeadlineSeconds`) — 2026-09-26 대표 지시로 90분 → 180분(90분에 `DeadlineExceeded` 로 죽은 런 둘). */
|
|
50
51
|
/** Newest pod log bytes returned when the export passes the 5MB artifact limit (headroom under it). */
|
|
51
52
|
export const POD_LOGS_KEEP_BYTES = 4_500_000;
|
|
52
53
|
|
|
@@ -60,6 +61,34 @@ export const POD_RESULT_FLATTEN = `ELANOUS_CHILD_RC="$rc" bun -e ' const fs=requ
|
|
|
60
61
|
|
|
61
62
|
export const POD_JOB_DEADLINE_SECONDS = 10_800;
|
|
62
63
|
|
|
64
|
+
/** Record the source-stage IO marker emitted by podSourceScript. */
|
|
65
|
+
export function recordPodSourceIoSummary(logs: string, job: string, runId: string | null | undefined,
|
|
66
|
+
runIdSource: 'explicit-child-id' | 'pod-launch-child-run-id',
|
|
67
|
+
log: typeof debug.log = (category, event, data, options) => debug.log(category, event, data, options),
|
|
68
|
+
hostOriginCalls: number | null = 0): void {
|
|
69
|
+
const ioSummary = /^ELANOUS_POD_SOURCE_IO (\{[^\r\n]+\})\r?$/m.exec(logs)?.[1];
|
|
70
|
+
if (!ioSummary) return;
|
|
71
|
+
try {
|
|
72
|
+
const measured = JSON.parse(ioSummary) as Record<string, unknown>;
|
|
73
|
+
log('pod.source', 'io-summary', { job, runId, runIdSource, ...measured, hostOriginCalls });
|
|
74
|
+
} catch (error) {
|
|
75
|
+
log('pod.source', 'io-summary-invalid', { job, runId, runIdSource, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Select a timestamp for a DeadlineExceeded observation without making detector time look like Job completion.
|
|
80
|
+
* `podFinishedAt` must come from readPodTermination for the same verified Job uid. */
|
|
81
|
+
export function podJobFinishedTiming(input: { jobCreatedAt: string | null; jobCompletedAt: string | null;
|
|
82
|
+
podFinishedAt: string | null; observedAt: string }): { finishedAt: string; finishedAtSource: 'job-completion' | 'pod-termination' | 'observed-at'; elapsedMs: number | null } {
|
|
83
|
+
const valid = (value: string | null): value is string => typeof value === 'string' && Number.isFinite(Date.parse(value));
|
|
84
|
+
const selected = valid(input.jobCompletedAt) ? { finishedAt: input.jobCompletedAt, finishedAtSource: 'job-completion' as const }
|
|
85
|
+
: valid(input.podFinishedAt) ? { finishedAt: input.podFinishedAt, finishedAtSource: 'pod-termination' as const }
|
|
86
|
+
: { finishedAt: input.observedAt, finishedAtSource: 'observed-at' as const };
|
|
87
|
+
const elapsedMs = valid(input.jobCreatedAt) && Number.isFinite(Date.parse(selected.finishedAt))
|
|
88
|
+
? Math.max(0, Date.parse(selected.finishedAt) - Date.parse(input.jobCreatedAt)) : null;
|
|
89
|
+
return { ...selected, elapsedMs };
|
|
90
|
+
}
|
|
91
|
+
|
|
63
92
|
/** 자식 컨테이너 «요청» — 🩸 2026-09-27: limits 만 두면 k8s 가 requests=limits(cpu 4)로 잡아, 32코어 노드에
|
|
64
93
|
* «자리 요청»이 88% 차서 잡이 Pending 인데 실사용은 14%였다(풀 25 자리 중 ~8 만 떴다). 상한(limits)은 그대로 두고
|
|
65
94
|
* 예약만 실사용에 맞춘다. */
|
|
@@ -86,20 +115,21 @@ import { enterJourneyNode, exitJourneyNode, passJourneyNode } from '../../self-d
|
|
|
86
115
|
import { routeJourneyEdge } from '../../self-dev/graph-journey-route.js';
|
|
87
116
|
import { selectLiveDetail } from '../../live/detail-switch.js';
|
|
88
117
|
import { authStorePath } from '../../oauth/store.js';
|
|
89
|
-
import { grokAuthFilePath, isGrokSubscriptionExpiring, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
|
|
118
|
+
import { grokAuthFilePath, isGrokSubscriptionExpiring, readSelectedGrokScope, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
|
|
90
119
|
import { defaultGrokModel } from '../../grok/models.js';
|
|
91
120
|
import { resolveHostId } from '../../platform/host-id.js';
|
|
92
121
|
import { BUDGET_SNAPSHOT_ENV, encodeBudgetSnapshot, harnessLaunchBudgetDecision, type BudgetSnapshot } from '../../execution-loop/launch-gate.js';
|
|
93
122
|
import type { ReadBudgetInputsDeps } from '../../self-implement/budget-gate.js';
|
|
94
123
|
import { envLiteral } from '../../platform/env-literal.js';
|
|
95
124
|
import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
|
|
96
|
-
import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
|
|
125
|
+
import { parseSelfImplementJson, type SelfImplementDisposition, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
|
|
97
126
|
import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
|
|
98
127
|
import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
|
|
99
128
|
import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
|
|
100
129
|
import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
|
|
101
130
|
import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
|
|
102
131
|
import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
|
|
132
|
+
import { worktreeAddTimeoutSec } from '../../git-fs/worktree.js';
|
|
103
133
|
import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
|
|
104
134
|
import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
|
|
105
135
|
import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
|
|
@@ -107,7 +137,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
|
|
|
107
137
|
import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
|
|
108
138
|
import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
|
|
109
139
|
import { inferProviderFromModel } from '../../llm.js';
|
|
110
|
-
import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
|
|
140
|
+
import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
|
|
111
141
|
import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
|
|
112
142
|
import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
|
|
113
143
|
import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
|
|
@@ -199,7 +229,7 @@ export interface PodSpawnOptions {
|
|
|
199
229
|
warmPodRequest?: WarmPodRequestHook;
|
|
200
230
|
/** SI-SEED-DEFAULT — resolves a default source's branch tip for the mirror seed (test seam · default
|
|
201
231
|
* {@link resolveDefaultSourceHead}; none with an injected kubectl unless given). */
|
|
202
|
-
resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string }>;
|
|
232
|
+
resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string; originCalls?: number }>;
|
|
203
233
|
/** 설정 읽기(시험 주입). kubectl 주입 시험에서는 기본 사용자 설정을 읽지 않는다. */
|
|
204
234
|
configHostMirror?: () => string | undefined;
|
|
205
235
|
/** AUTHOR-POD2 host config seam; Pod itself has no host config. */
|
|
@@ -511,7 +541,7 @@ export function hostCredentials(account: string, storePath: string = authStorePa
|
|
|
511
541
|
* (POD_GROK_MIN_JOB_SECONDS) plus a margin left, and that launch's `activeDeadlineSeconds` is cut to the token's
|
|
512
542
|
* remaining life minus the margin (`fitPodDeadlineToGrok`) — so a long run ends as a classified DeadlineExceeded
|
|
513
543
|
* instead of a silent mid-run 401. With the host credential relay (pod.groundingUrl) the Pod renews mid-run and
|
|
514
|
-
* nothing is cut. 90 min = the Job cap before
|
|
544
|
+
* nothing is cut. 90 min = the Job cap before the 09-26 decision raised it (only two runs had reached it). */
|
|
515
545
|
export const POD_GROK_MIN_JOB_SECONDS = 90 * 60;
|
|
516
546
|
/** Slack between the fitted Job end and the token expiry (clock skew · Pod scheduling). */
|
|
517
547
|
export const POD_GROK_EXPIRY_MARGIN_MS = 15 * 60_000;
|
|
@@ -526,15 +556,6 @@ export function formatGrokRemaining(ms: number | null): string {
|
|
|
526
556
|
return m >= 60 ? `${Math.floor(m / 60)}h${String(m % 60).padStart(2, '0')}m` : `${m}m`;
|
|
527
557
|
}
|
|
528
558
|
|
|
529
|
-
/** Latest `expires_at` among scopes that carry an access key (the token the Pod would get). */
|
|
530
|
-
function grokSubscriptionExpiresAtMs(home?: string): number | null {
|
|
531
|
-
try {
|
|
532
|
-
const scopes = JSON.parse(readFileSync(grokAuthFilePath(home), 'utf8')) as Record<string, { key?: unknown; expires_at?: unknown }>;
|
|
533
|
-
const all = Object.values(scopes).flatMap((s) => (s && typeof s.key === 'string' && s.key && typeof s.expires_at === 'string' && Number.isFinite(Date.parse(s.expires_at)) ? [Date.parse(s.expires_at)] : []));
|
|
534
|
-
return all.length ? Math.max(...all) : null;
|
|
535
|
-
} catch { return null; }
|
|
536
|
-
}
|
|
537
|
-
|
|
538
559
|
/** POD-GROK-VALIDITY-FIT — this launch's Job deadline for a refresh-less grok subscription copy.
|
|
539
560
|
* · relay (the Pod can renew from the host) or unknown expiry → the requested deadline as is.
|
|
540
561
|
* · otherwise → min(requested, remaining − margin); below the minimum Job (time passed since the credential check)
|
|
@@ -574,38 +595,46 @@ export function podGhLoginRetryBackoffMs(job: string): number {
|
|
|
574
595
|
export function hostGrokCredentials(opts: {
|
|
575
596
|
home?: string; env?: NodeJS.ProcessEnv; apiKeyOptIn?: boolean; ghToken?: () => string;
|
|
576
597
|
/** Test seams — the host refresh (read-only `grok models`) and the expiry probe. */
|
|
577
|
-
refresh?: () => void; isExpiring?: () => boolean;
|
|
598
|
+
refresh?: () => void; isExpiring?: () => boolean; grokPath?: string;
|
|
578
599
|
/** Required remaining token life (default POD_GROK_MIN_VALIDITY_MS) — a caller whose Job is not fitted passes its own deadline. */
|
|
579
600
|
minValidityMs?: number; now?: () => number;
|
|
580
601
|
} = {}): { grokAuth?: string; grokApiKey?: string; ghToken: string } {
|
|
581
602
|
let credential = resolveGrokCredential({ home: opts.home, env: opts.env });
|
|
582
603
|
if (credential?.kind === 'subscription') {
|
|
604
|
+
const initialScope = readSelectedGrokScope(opts.home);
|
|
605
|
+
if (!initialScope) throw new Error('grok: 선택된 구독 scope 없음 — 발사를 거부');
|
|
583
606
|
const minValidityMs = opts.minValidityMs ?? POD_GROK_MIN_VALIDITY_MS;
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
|
|
607
|
+
const clock = opts.now ?? Date.now;
|
|
608
|
+
const initialExpiry = initialScope.expiresAt ? Date.parse(initialScope.expiresAt) : NaN;
|
|
609
|
+
const expiring = opts.isExpiring ? opts.isExpiring()
|
|
610
|
+
: !Number.isFinite(initialExpiry) || initialExpiry - clock() < minValidityMs;
|
|
611
|
+
if (expiring) {
|
|
612
|
+
if (!initialScope.hasRefreshToken) {
|
|
613
|
+
throw new Error('grok: 선택된 구독 scope에 refresh token 없음 — 다른 계정으로 대체하지 않고 발사를 거부');
|
|
592
614
|
}
|
|
593
|
-
|
|
594
|
-
|
|
615
|
+
try {
|
|
616
|
+
if (opts.refresh) opts.refresh();
|
|
617
|
+
else refreshGrokSubscriptionToken({ home: opts.home, requireRefreshToken: true,
|
|
618
|
+
requiredValidityMs: minValidityMs, nowMs: clock(), ...(opts.grokPath ? { grokPath: opts.grokPath } : {}) });
|
|
619
|
+
} catch { /* Final snapshot below is the launch decision. */ }
|
|
595
620
|
}
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
...(typeof scope.user_id === 'string' ? { user_id: scope.user_id } : {}),
|
|
606
|
-
};
|
|
621
|
+
const selected = readSelectedGrokScope(opts.home);
|
|
622
|
+
if (!selected || selected.scopeName !== initialScope.scopeName) {
|
|
623
|
+
throw new Error('grok: 자격 확인 중 선택된 구독 scope가 사라졌거나 바뀜 — 발사를 거부');
|
|
624
|
+
}
|
|
625
|
+
const selectedExpiry = selected.expiresAt ? Date.parse(selected.expiresAt) : NaN;
|
|
626
|
+
if (!Number.isFinite(selectedExpiry) || selectedExpiry - clock() < minValidityMs) {
|
|
627
|
+
const remainingMs = Number.isFinite(selectedExpiry) ? selectedExpiry - clock() : null;
|
|
628
|
+
try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: selected.expiresAt }); } catch { /* fail-soft */ }
|
|
629
|
+
throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
|
|
607
630
|
}
|
|
608
|
-
|
|
631
|
+
const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {
|
|
632
|
+
[selected.scopeName]: {
|
|
633
|
+
key: selected.key,
|
|
634
|
+
...(selected.expiresAt ? { expires_at: selected.expiresAt } : {}),
|
|
635
|
+
...(selected.userId ? { user_id: selected.userId } : {}),
|
|
636
|
+
},
|
|
637
|
+
};
|
|
609
638
|
return { grokAuth: JSON.stringify(redacted), ghToken: (opts.ghToken ?? defaultGhToken)() };
|
|
610
639
|
}
|
|
611
640
|
if (credential?.kind === 'api_key' && opts.apiKeyOptIn === true) {
|
|
@@ -959,7 +988,7 @@ export function podRunLabels(o: { runId?: string; parentRunId?: string }): Recor
|
|
|
959
988
|
return { ...(run ? { 'elanous.run': run } : {}), ...(child ? { 'elanous.child-run': child } : {}) };
|
|
960
989
|
}
|
|
961
990
|
|
|
962
|
-
/** Pod 메모리 «등급» —
|
|
991
|
+
/** Pod 메모리 «등급» — 09-27 결정: PWA Pod 골이 16Gi 에서 OOM 으로 죽는다 ⇒ «high» 등급을 옵션으로 고른다.
|
|
963
992
|
* 등급 = `standard`(`ELANOUS_POD_MEMORY` 또는 16Gi) · `high`(`ELANOUS_POD_MEMORY_HIGH` 또는 32Gi · standard 보다 작아지지 않는다).
|
|
964
993
|
* 고르는 순서(앞이 이긴다): ① 발사 옵션 `--pod-memory <등급>`(→ `ELANOUS_POD_MEMORY_TIER`) ② 조각 문면 `Pod 메모리: lite|standard|high` ③ 조각의 `apps/pwa/` ④ 부모의 명시 메모리 줄·PWA 경로 ⑤ 실측 권고 ⑥ 권고 없는 research/document 는 lite ⑦ standard.
|
|
965
994
|
* node-b 노드 할당 가능 약 251Gi. */
|
|
@@ -1192,7 +1221,30 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
|
|
|
1192
1221
|
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`;
|
|
1193
1222
|
}
|
|
1194
1223
|
|
|
1195
|
-
|
|
1224
|
+
/** Leave enough time for the Pod wrapper to print its result and push a salvage branch before Kubernetes kills the Job. */
|
|
1225
|
+
export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job: string; runId?: string; prNumber?: number }): string {
|
|
1226
|
+
const leadSeconds = Math.max(1, Math.min(600, Math.floor(input.deadlineSeconds / 10)));
|
|
1227
|
+
const waitSeconds = Math.max(1, input.deadlineSeconds - leadSeconds);
|
|
1228
|
+
const job = /^[A-Za-z0-9_.:-]+$/.test(input.job) ? input.job : 'unknown-job';
|
|
1229
|
+
const runId = input.runId && /^[A-Za-z0-9_.:-]+$/.test(input.runId) ? input.runId : 'unknown-run';
|
|
1230
|
+
const pr = input.prNumber && Number.isSafeInteger(input.prNumber) && input.prNumber > 0 ? String(input.prNumber) : 'unknown';
|
|
1231
|
+
const jsonPr = pr === 'unknown' ? 'null' : pr;
|
|
1232
|
+
return `printf 'clone\\n' > /tmp/si.stage
|
|
1233
|
+
(sleep ${waitSeconds}; [ -f /tmp/si.finished ] && exit 0
|
|
1234
|
+
stage=$(cat /tmp/si.stage 2>/dev/null || true); case "$stage" in clone|setup|run) ;; *) stage=unknown;; esac
|
|
1235
|
+
branch=$(git -C repo branch --show-current 2>/dev/null || true); case "$branch" in ''|*[!A-Za-z0-9_./-]*) branch=unknown;; esac
|
|
1236
|
+
[ -f /tmp/si.finished ] && exit 0
|
|
1237
|
+
si_target=$(cat /tmp/si.pid 2>/dev/null || true)
|
|
1238
|
+
case "$si_target" in ''|*[!0-9]*) ;; *) kill -0 "$si_target" 2>/dev/null || exit 0;; esac
|
|
1239
|
+
printf 'ELANOUS_POD_DEADLINE_RESULT ${job} ${runId} stop-cause=deadline stage=%s pr=${pr} branch=%s\\n' "$stage" "$branch" | tee /tmp/si.deadline-marker
|
|
1240
|
+
printf '{"stage":"deadline","ok":false,"error":"Pod deadline preemption","stopCause":"deadline","prNumber":${jsonPr},"branch":"%s"}\\n' "$branch" > /tmp/si.deadline-result
|
|
1241
|
+
case "$si_target" in ''|*[!0-9]*) ;; *) kill -TERM "$si_target" 2>/dev/null || true;; esac
|
|
1242
|
+
) & si_deadline_watch_pid=$!`;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
export const POD_DEADLINE_AFTER_WAIT = `if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then printf '\\n' >> /tmp/si.out; cat /tmp/si.deadline-result >> /tmp/si.out; rc=124; fi`;
|
|
1246
|
+
|
|
1247
|
+
export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; boundPrNumber?: number; /** 레지스트리 이미지면 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; /** Codex Job may use the same named Secret only for an explicitly admitted ZAI fallback. */ zaiFallback?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' }; configSnapshotHash?: string; /** TA-POD-WARMBOOT-PARITY — the child's final line (podResultMarkerShellLine), just before `exit $rc`. */ resultMarkerLine?: string; /** POD-LAUNCH-PROVENANCE — the shared provenance set (labels ⊕ annotations ⊕ child env) for this si-task Job. */ provenance?: PodProvenanceMetadata }): Record<string, unknown> {
|
|
1196
1248
|
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'))) {
|
|
1197
1249
|
throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
|
|
1198
1250
|
}
|
|
@@ -1223,7 +1275,10 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1223
1275
|
const script = [
|
|
1224
1276
|
'set -u',
|
|
1225
1277
|
...(o.fallbackChain ? [
|
|
1226
|
-
|
|
1278
|
+
...(o.configSnapshotHash ? [
|
|
1279
|
+
'bun -e \'import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; const e = JSON.parse(readFileSync("/creds/config-snapshot.json", "utf8")); const c = JSON.parse(readFileSync("/creds/llm-fallback-config.json", "utf8")); const h = createHash("sha256").update(JSON.stringify({ version: e.version, keys: e.keys, sources: e.sources })).digest("hex"); if (h !== e.hash || JSON.stringify(c) !== JSON.stringify(e.keys)) process.exit(1);\' || exit 6',
|
|
1280
|
+
] : []),
|
|
1281
|
+
'mkdir -p "$HOME/.elanous" && { [ -e "$HOME/.elanous/config.json" ] || [ -L "$HOME/.elanous/config.json" ] || install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json"; } || exit 6',
|
|
1227
1282
|
`echo "ELANOUS_POD_FALLBACK_CHAIN source=${o.fallbackChain.source} steps=${o.fallbackChain.steps.join(',')}"`,
|
|
1228
1283
|
] : []),
|
|
1229
1284
|
openGatewayModel
|
|
@@ -1252,9 +1307,11 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1252
1307
|
// SI-POD-STAGE-MARKERS — Pod 시계 단계 표지(`ELANOUS_POD_STAGE <stage> <start|end> <epoch초>`): 호스트가 Job 로그에서 읽어
|
|
1253
1308
|
// pod.lifecycle stages 의 clone · mirror · run 을 채운다. 실패한 단계는 끝 표지가 없다(→ missing · 지어내지 않는다).
|
|
1254
1309
|
// clone 끝 = podSourceScript 전체가 끝난 뒤(갈래마다 마지막 줄이 `ELANOUS_POD_SOURCE` 또는 `cd repo` — 둘 다 소스 받기의 일부).
|
|
1310
|
+
podDeadlineWatchdogScript({ deadlineSeconds: o.deadlineSeconds, job: o.name, runId: o.runId, prNumber: o.boundPrNumber }),
|
|
1255
1311
|
siTaskPodStageShell('clone', 'start'),
|
|
1256
1312
|
podSourceScript(o.source ?? { kind: 'default' }, o.repoUrl, undefined, { stageMarkers: true }),
|
|
1257
1313
|
siTaskPodStageShell('clone', 'end'),
|
|
1314
|
+
`printf 'setup\\n' > /tmp/si.stage`,
|
|
1258
1315
|
// This image already contains runtime dependencies; there is no child install command.
|
|
1259
1316
|
// Record that fact before the main command, without treating clone completion as install completion.
|
|
1260
1317
|
`printf 'ELANOUS_POD_DEPS skipped %s image-prepared-no-install\\n' "$(date +%s)" || true`,
|
|
@@ -1278,14 +1335,15 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1278
1335
|
// 마지막 줄 JSON 이 «맨 끝»이어야 한다(parseSelfImplementJson) — rollup 은 그 앞에.
|
|
1279
1336
|
// ⛔ `--author-grade` 는 Pod 안 `elanous`(이미지에 깔린 판)가 모를 수 있어 넘기지 않는다 — 10-06 «unknown option» 즉사(#24445 되돌림).
|
|
1280
1337
|
// AUTHOR-LITE2-POD — 등급은 환경변수 `ELANOUS_AUTHOR_GRADE` 로 싣는다(옛 Pod elanous 는 모르는 환경변수를 무시하고 full 로 돈다).
|
|
1338
|
+
`printf 'run\\n' > /tmp/si.stage`,
|
|
1281
1339
|
siTaskPodStageShell('run', 'start'),
|
|
1282
1340
|
o.repairCommitOnly
|
|
1283
|
-
? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi`
|
|
1341
|
+
? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi; ${POD_DEADLINE_AFTER_WAIT}`
|
|
1284
1342
|
: o.authorSentence
|
|
1285
|
-
? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
|
|
1343
|
+
? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
|
|
1286
1344
|
: goalPath
|
|
1287
|
-
? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`
|
|
1288
|
-
: `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`,
|
|
1345
|
+
? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`
|
|
1346
|
+
: `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`,
|
|
1289
1347
|
'cat /tmp/si.out',
|
|
1290
1348
|
...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
|
|
1291
1349
|
...(o.repairCommitOnly ? [] : [podSalvageScript()]),
|
|
@@ -1352,7 +1410,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1352
1410
|
'[ -n "${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true',
|
|
1353
1411
|
'wait "$mem_sampler_pid" 2>/dev/null || true',
|
|
1354
1412
|
'[ -n "${usage_partial_pid:-}" ] && wait "$usage_partial_pid" 2>/dev/null || true',
|
|
1413
|
+
'if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then rc=124; fi',
|
|
1355
1414
|
'tail -n 1 /tmp/si.out',
|
|
1415
|
+
'touch /tmp/si.finished; kill "$si_deadline_watch_pid" 2>/dev/null || true; [ -f /tmp/si.deadline-marker ] && cat /tmp/si.deadline-marker || true',
|
|
1356
1416
|
// TA-POD-WARMBOOT-PARITY: the last line says «the child is done» so the host need not wait for the Job condition.
|
|
1357
1417
|
...(o.resultMarkerLine ? [o.resultMarkerLine] : []),
|
|
1358
1418
|
'exit $rc',
|
|
@@ -1361,7 +1421,7 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1361
1421
|
apiVersion: 'batch/v1',
|
|
1362
1422
|
kind: 'Job',
|
|
1363
1423
|
metadata: { name: o.name, namespace: o.namespace, labels: { 'elanous.substrate': 'pod', 'elanous.job': o.name, ...podRunLabels(o), ...(o.workIdentity ? podWorkLabels(o.workIdentity) : {}), ...(o.zai || o.zaiFallback ? { [ZAI_POD_EGRESS_LABEL]: 'true' } : {}), ...o.provenance?.labels },
|
|
1364
|
-
...((o.execution || o.hostLeaseAdmitted || o.provenance) ? { annotations: { ...o.provenance?.annotations, ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
|
|
1424
|
+
...((o.execution || o.hostLeaseAdmitted || o.provenance || o.configSnapshotHash) ? { annotations: { ...o.provenance?.annotations, ...(o.configSnapshotHash ? { 'elanous.config-snapshot-sha256': o.configSnapshotHash } : {}), ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
|
|
1365
1425
|
spec: {
|
|
1366
1426
|
backoffLimit: 0,
|
|
1367
1427
|
ttlSecondsAfterFinished: POD_JOB_TTL_AFTER_FINISHED_SECONDS,
|
|
@@ -1388,6 +1448,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1388
1448
|
? [{ name: 'ELANOUS_TASK_BOUND_PR', value: String(o.boundPrNumber) }] : []),
|
|
1389
1449
|
...(o.workIdentity?.slotId ? [{ name: 'ELANOUS_POD_SLOT_ID', value: o.workIdentity.slotId }] : []),
|
|
1390
1450
|
{ name: 'ELANOUS_SUBSTRATE', value: 'pod' },
|
|
1451
|
+
// POD-INPLACE-WORKTREE: explicit host opt-in only; one Job runs one implementation child.
|
|
1452
|
+
{ name: 'ELANOUS_POD_SINGLE_CHILD', value: '1' },
|
|
1453
|
+
{ name: 'ELANOUS_POD_INPLACE_WORKTREE', value: process.env.ELANOUS_POD_INPLACE_WORKTREE === '1' ? '1' : '0' },
|
|
1391
1454
|
...Object.entries(controlInboxEnv(POD_CONTROL_INBOX_DIR)).map(([name, value]) => ({ name, value })),
|
|
1392
1455
|
// ⭐ 런 출처(🅣 RFC run-origin §A3 · #20457/#20468 칸 이름) — Pod 는 자기 elanous_id 를 쓰지 않고 «띄운 감독기»의 hostId 를 물려받는다.
|
|
1393
1456
|
{ name: 'ELANOUS_POD_NAME', valueFrom: { fieldRef: { fieldPath: 'metadata.name' } } },
|
|
@@ -1910,6 +1973,35 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1910
1973
|
try {
|
|
1911
1974
|
// Every attempt, including an OOM retry, must acquire a pool slot before applying a Job.
|
|
1912
1975
|
const stallMs = options.launchStallMs ?? (getUserConfig().harness?.launchStallMinutes ?? 15) * 60_000;
|
|
1976
|
+
const slotNow = options.now ?? Date.now;
|
|
1977
|
+
let slotAttemptNumber = 0;
|
|
1978
|
+
let lastSlotReasonCode: string | undefined;
|
|
1979
|
+
let lastSlotAttempt: { observationKey: string; requestedAtMs: number; requestedAt: string } | undefined;
|
|
1980
|
+
const slotReasonCode = (reason: string | null | undefined): string => {
|
|
1981
|
+
if (!reason) return 'not-measured-yet';
|
|
1982
|
+
if (/no free slot/iu.test(reason)) return 'no-free-slot';
|
|
1983
|
+
if (/memory/iu.test(reason)) return 'memory-capacity';
|
|
1984
|
+
if (/capacity|lease/iu.test(reason)) return 'capacity';
|
|
1985
|
+
return 'pool-slot-unavailable';
|
|
1986
|
+
};
|
|
1987
|
+
const recordSlotObservation = (attempt: { observationKey: string; requestedAtMs: number; requestedAt: string },
|
|
1988
|
+
outcome: 'requested' | 'queued' | 'admitted' | 'rejected', reasonCode: string): void => {
|
|
1989
|
+
const pool = options.pool;
|
|
1990
|
+
let occupants: Record<string, number> | null = null;
|
|
1991
|
+
try { occupants = pool ? pool.snapshot() : null; } catch { /* observation must not change scheduling */ }
|
|
1992
|
+
const poolCapacity = pool?.members?.reduce((total, member) => total + Math.max(0, member.capacity), 0) ?? null;
|
|
1993
|
+
const data = {
|
|
1994
|
+
observationKey: attempt.observationKey, runId: childRunId, host: resolveHostId(env),
|
|
1995
|
+
requestedAt: attempt.requestedAt, waitedMs: Math.max(0, slotNow() - attempt.requestedAtMs),
|
|
1996
|
+
queued: outcome === 'queued', poolCapacity, occupants, reasonCode, parentId: ledgerRunId, outcome,
|
|
1997
|
+
};
|
|
1998
|
+
debug.log('pod.slot', outcome, data, { level: outcome === 'admitted' || outcome === 'requested' ? 'info' : 'warn' });
|
|
1999
|
+
try {
|
|
2000
|
+
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-observation', data }, ledgerDir);
|
|
2001
|
+
if (outcome === 'rejected') appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-incident', data }, ledgerDir);
|
|
2002
|
+
}
|
|
2003
|
+
catch (error) { debug.log('pod.slot', 'ledger-unavailable', { ...data, writeError: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
2004
|
+
};
|
|
1913
2005
|
// LAUNCH-STALL (10-06): a stage that waits past the cap says so once — today Pods sat 22 min to 5 h with no event.
|
|
1914
2006
|
const stalledStages = new Set<string>();
|
|
1915
2007
|
// pool-slot reason = what THIS launch saw on its last empty tryAcquire; admission reason = the pool-wide lease measurement (one pool, one reading).
|
|
@@ -1947,25 +2039,42 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1947
2039
|
};
|
|
1948
2040
|
const acquireSlot = async (): Promise<PodPoolMember | null> => {
|
|
1949
2041
|
if (!options.pool) return null;
|
|
2042
|
+
// Each actual acquisition is a separate observation, including the OOM retry in this
|
|
2043
|
+
// same child run. The ordinal keeps keys distinct even with a fixed test clock.
|
|
2044
|
+
const requestedAtMs = slotNow();
|
|
2045
|
+
const attempt = { observationKey: `${childRunId}:pod-slot:${requestedAtMs}:${++slotAttemptNumber}`,
|
|
2046
|
+
requestedAtMs, requestedAt: new Date(requestedAtMs).toISOString() };
|
|
2047
|
+
let firstSlotReasonCode: string | undefined;
|
|
2048
|
+
let slotQueuedRecorded = false;
|
|
1950
2049
|
const stop = watchStall('pool-slot');
|
|
1951
2050
|
// MINIH-MODE (0.2.37): the location is declared by the launch env — absent/unknown keeps the configured
|
|
1952
2051
|
// capacities, so this launch path behaves exactly as before unless the declaration is there.
|
|
1953
2052
|
const minihLocation = minihLocationFrom(env.ELANOUS_MINIH_LOCATION);
|
|
1954
2053
|
try {
|
|
2054
|
+
recordSlotObservation(attempt, 'requested', 'pending');
|
|
1955
2055
|
for (;;) {
|
|
1956
2056
|
if (input.signal?.aborted) return null;
|
|
1957
2057
|
// The reason comes back inside this call, so a concurrent launch cannot overwrite it.
|
|
1958
2058
|
const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
|
|
1959
|
-
const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
|
|
2059
|
+
const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
|
|
2060
|
+
stageReason['pool-slot'] = reason;
|
|
2061
|
+
firstSlotReasonCode ??= slotReasonCode(reason);
|
|
2062
|
+
},
|
|
1960
2063
|
{ kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
|
|
1961
2064
|
if (acquired) {
|
|
2065
|
+
recordSlotObservation(attempt, 'admitted', firstSlotReasonCode ?? 'admitted');
|
|
1962
2066
|
debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
|
|
1963
2067
|
if (lastPlacement) console.warn(`[pod] 배치: ${lastPlacement.reason}`);
|
|
1964
2068
|
return acquired;
|
|
1965
2069
|
}
|
|
2070
|
+
firstSlotReasonCode ??= slotReasonCode(stageReason['pool-slot']);
|
|
2071
|
+
if (!slotQueuedRecorded) {
|
|
2072
|
+
slotQueuedRecorded = true;
|
|
2073
|
+
recordSlotObservation(attempt, 'queued', firstSlotReasonCode);
|
|
2074
|
+
}
|
|
1966
2075
|
await sleep(options.pollMs ?? 15_000);
|
|
1967
2076
|
}
|
|
1968
|
-
} finally { stop(); }
|
|
2077
|
+
} finally { lastSlotReasonCode = firstSlotReasonCode; lastSlotAttempt = attempt; stop(); }
|
|
1969
2078
|
};
|
|
1970
2079
|
const acquireAdmission = async (): Promise<boolean> => {
|
|
1971
2080
|
if (!options.pool || typeof options.pool.acquireAdmission !== 'function') return true;
|
|
@@ -2001,8 +2110,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2001
2110
|
let member: PodPoolMember | null;
|
|
2002
2111
|
try { member = await acquireSlot(); } catch (error) { podAdmitError(error); throw error; }
|
|
2003
2112
|
if (options.pool && !member) {
|
|
2113
|
+
if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted');
|
|
2004
2114
|
exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'refused', data: { spaceId: input.spaceId, reason: 'no-slot' } });
|
|
2005
|
-
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened' } };
|
|
2115
|
+
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
|
|
2006
2116
|
}
|
|
2007
2117
|
exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'admitted', data: { spaceId: input.spaceId, ...(member ? { context: member.context } : {}) } });
|
|
2008
2118
|
const currentContext = member ? null : baseKubectl(['config', 'current-context']);
|
|
@@ -2030,6 +2140,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2030
2140
|
const cleanupSecret = () => { kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']); };
|
|
2031
2141
|
let repairResultAnnounced = false;
|
|
2032
2142
|
let repairArtifactReady = false;
|
|
2143
|
+
let hostOriginCalls: number | null = 0;
|
|
2144
|
+
let sourceBaseSha: string | undefined;
|
|
2033
2145
|
const collectFullLogs = (unavailableEvent: string, replace?: ReadonlySet<string>, onEvent?: (event: string, data: Record<string, unknown>) => void, childId?: string): { status: 'ok' | 'unavailable' | 'incomplete'; childLedgerIncomplete: boolean; samples: ReturnType<typeof parseMemSamples> } => {
|
|
2034
2146
|
let full: ReturnType<Kubectl>;
|
|
2035
2147
|
try {
|
|
@@ -2046,6 +2158,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2046
2158
|
const imageSkip = /^ELANOUS_POD_SOURCE_IMAGE_SKIP ([^\r\n]+)\r?$/m.exec(full.stdout)?.[1];
|
|
2047
2159
|
const delta = /^ELANOUS_POD_SOURCE_DELTA (mirror|origin)\r?$/m.exec(full.stdout)?.[1];
|
|
2048
2160
|
if (via) debug.log('self-implement.pod', 'source-via', { job: name, via, ...(mirrorSkip ? { mirrorSkip } : {}), ...(imageSkip ? { imageSkip } : {}), ...(delta ? { delta } : {}) });
|
|
2161
|
+
recordPodSourceIoSummary(full.stdout, name, childId ?? childRunId, childId ? 'explicit-child-id' : 'pod-launch-child-run-id',
|
|
2162
|
+
(category, event, data, logOptions) => debug.log(category, event, data, logOptions), hostOriginCalls);
|
|
2049
2163
|
let ledgerIncomplete = false;
|
|
2050
2164
|
let childLedgerIncomplete = false;
|
|
2051
2165
|
let artifactIncomplete = false;
|
|
@@ -2323,20 +2437,43 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2323
2437
|
}
|
|
2324
2438
|
const now = options.now ?? Date.now;
|
|
2325
2439
|
const issueVerifiedAppCredential = async (fresh = false): Promise<{ token: string; expiresAt: number } | null> => {
|
|
2326
|
-
if (!repository)
|
|
2440
|
+
if (!repository) {
|
|
2441
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, reason: 'repository-unavailable', fresh });
|
|
2442
|
+
return null;
|
|
2443
|
+
}
|
|
2327
2444
|
// This is the same repository-scoped, contents+pull_requests installation request on launch and refresh.
|
|
2328
|
-
|
|
2329
|
-
|
|
2445
|
+
let candidate: ReturnType<NonNullable<typeof options.githubInstallation>>;
|
|
2446
|
+
try { candidate = (options.githubInstallation ?? ((repo, o) => coalescedInstallationCredential({ repository: repo.split('/')[1]! }, { fresh: o?.fresh })))(repository, { fresh }); }
|
|
2447
|
+
catch {
|
|
2448
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-threw', fresh });
|
|
2449
|
+
return null;
|
|
2450
|
+
}
|
|
2451
|
+
if (!candidate?.token) {
|
|
2452
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-unavailable', fresh });
|
|
2453
|
+
return null;
|
|
2454
|
+
}
|
|
2330
2455
|
const expiry = candidate.expires_at ?? ('expiresAt' in candidate ? candidate.expiresAt : undefined);
|
|
2331
2456
|
const expiresAt = typeof expiry === 'number' ? expiry : Date.parse(expiry ?? '');
|
|
2332
|
-
if (!Number.isFinite(expiresAt) || expiresAt <= now())
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2457
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= now()) {
|
|
2458
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: Number.isFinite(expiresAt) ? 'expired' : 'expiry-unavailable', expiresAt: Number.isFinite(expiresAt) ? new Date(expiresAt).toISOString() : null, fresh });
|
|
2459
|
+
return null;
|
|
2460
|
+
}
|
|
2461
|
+
let available: Awaited<ReturnType<NonNullable<typeof options.githubRepositories>>>;
|
|
2462
|
+
try { available = await (options.githubRepositories ?? installationRepositories)(candidate.token); }
|
|
2463
|
+
catch {
|
|
2464
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verification-threw', expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2465
|
+
return null;
|
|
2466
|
+
}
|
|
2467
|
+
if (available?.length !== 1 || available[0]?.toLowerCase() !== repository.toLowerCase()) {
|
|
2468
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'repository-verification-failed', availableCount: available?.length ?? null, expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2469
|
+
return null;
|
|
2470
|
+
}
|
|
2471
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verified', expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2472
|
+
return { token: candidate.token, expiresAt };
|
|
2336
2473
|
};
|
|
2337
2474
|
let appCredential: Awaited<ReturnType<typeof issueVerifiedAppCredential>> = null;
|
|
2338
2475
|
try { appCredential = await issueVerifiedAppCredential(ghLoginRetried); }
|
|
2339
|
-
catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, reason: 'mint-or-verification-
|
|
2476
|
+
catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, repository, reason: 'mint-or-verification-threw' }); }
|
|
2340
2477
|
// PODCRED1: a short token is still shipped — the host renews it in the Pod on the first live poll — but it is
|
|
2341
2478
|
// observed, so an exit-7 burst can be checked against the remaining life the Pods actually started with.
|
|
2342
2479
|
if (appCredential && appCredential.expiresAt - now() < POD_APP_TOKEN_MIN_START_MS) {
|
|
@@ -2352,6 +2489,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2352
2489
|
// The host polling loop is a refresh path even when the Pod cannot reach the relay.
|
|
2353
2490
|
const hostRefresh = Boolean(appCredential);
|
|
2354
2491
|
const podGhToken = hostRefresh ? appCredential!.token : creds.ghToken;
|
|
2492
|
+
debug.log('self-implement.pod', 'github-credential-source', { job: name, repository, source: hostRefresh ? 'verified-app' : 'human-fallback', expiresAt: hostRefresh ? new Date(appCredential!.expiresAt).toISOString() : null });
|
|
2355
2493
|
const githubPassKeys = hostRefresh ? passKeys.filter((key) => !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key)) : passKeys;
|
|
2356
2494
|
let ghTokenExpiresAt = hostRefresh ? appCredential!.expiresAt : null;
|
|
2357
2495
|
const requestedGoalDoc = env.ELANOUS_POD_GOAL_DOC;
|
|
@@ -2483,6 +2621,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2483
2621
|
if (!zaiFallbackSpec) fallbackSteps = fallbackSteps.filter(step => step !== 'zai');
|
|
2484
2622
|
}
|
|
2485
2623
|
const fallbackChain = { steps: fallbackSteps, source: normalizedFallback.usedDefault ? 'default' as const : 'host' as const };
|
|
2624
|
+
const { buildPodConfigSnapshot } = await import('./pod-config-snapshot.js');
|
|
2625
|
+
const configSnapshot = buildPodConfigSnapshot(hostConfig, {
|
|
2626
|
+
steps: fallbackChain.steps, overage: zaiOverage,
|
|
2627
|
+
worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200,
|
|
2628
|
+
});
|
|
2629
|
+
debug.log('self-implement.pod', 'config-snapshot', { job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount });
|
|
2486
2630
|
debug.log('self-implement.pod', 'fallback-chain-carried', {
|
|
2487
2631
|
job: name, source: fallbackChain.source, steps: fallbackChain.steps,
|
|
2488
2632
|
...(normalizedFallback.dropped.length ? { droppedCount: normalizedFallback.dropped.length } : {}),
|
|
@@ -2501,7 +2645,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2501
2645
|
? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
|
|
2502
2646
|
: { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
|
|
2503
2647
|
'gh-token': podGhToken, feature: input.feature,
|
|
2504
|
-
'llm-fallback-config.json':
|
|
2648
|
+
'llm-fallback-config.json': configSnapshot.configJson,
|
|
2649
|
+
'config-snapshot.json': configSnapshot.envelopeJson,
|
|
2505
2650
|
...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
|
|
2506
2651
|
...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
|
|
2507
2652
|
...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
|
|
@@ -2515,7 +2660,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2515
2660
|
if (missing.length) debug.log('self-implement.pod', 'pass-env-missing', { job: name, missing }, { level: 'warn' });
|
|
2516
2661
|
// ☸️ 재개(P3 · 2026-09-26): 같은 이름의 Job 이 이미 있으면 «지우지 않고» 붙는다 — 호스트가 끊긴 동안에도 원격은 계속 돌았다.
|
|
2517
2662
|
// 🩸 종전엔 여기서 delete 부터 해서, 재개가 원격에서 멀쩡히 돌던 Job 을 죽였다. 실패로 끝난 Job 만 지우고 다시 만든다.
|
|
2518
|
-
// ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 ·
|
|
2663
|
+
// ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 · 2026-09-26) — 라벨 판정은 로컬 이미지 이름으로 한다.
|
|
2519
2664
|
const jobImage = member?.imageRef ?? image;
|
|
2520
2665
|
// A pool member may pull a different image than the host's local one.
|
|
2521
2666
|
// The local Docker label cannot prove that member image's commit.
|
|
@@ -2697,12 +2842,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2697
2842
|
slotId: env.ELANOUS_POD_SLOT_ID,
|
|
2698
2843
|
work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
|
|
2699
2844
|
};
|
|
2700
|
-
// TA-POD-WARMBOOT-PARITY shadow only:
|
|
2701
|
-
//
|
|
2845
|
+
// TA-POD-WARMBOOT-PARITY shadow only: read injected evidence, then keep the fresh-Job path.
|
|
2846
|
+
// This boundary must not open host configuration or credential files for a warm decision.
|
|
2702
2847
|
if (workIdentity.taskCard) {
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2848
|
+
let stage: 'config' | 'evidence' | 'decision' = 'config';
|
|
2849
|
+
try {
|
|
2850
|
+
const config = options.warmReuseConfig?.();
|
|
2851
|
+
stage = 'evidence';
|
|
2852
|
+
const evidence = options.warmReuseEvidence?.();
|
|
2853
|
+
stage = 'decision';
|
|
2854
|
+
const decision = decideWarmReuse('ta', config, evidence);
|
|
2855
|
+
debug.log('pod.warm', 'ta-shadow-observation', { ...decision, execution: 'fresh-job' });
|
|
2856
|
+
} catch {
|
|
2857
|
+
debug.log('pod.warm', 'ta-shadow-unavailable', { spaceId: input.spaceId,
|
|
2858
|
+
reason: stage === 'decision' ? 'warm-decision-failed' : `injected-${stage}-failed`, execution: 'fresh-job' }, { level: 'warn' });
|
|
2859
|
+
}
|
|
2706
2860
|
}
|
|
2707
2861
|
// TA-POD-WARMBOOT-PARITY (GATE-WARM-BOOT parity · #27805): a commit-pinned source on a pool host — put that commit into
|
|
2708
2862
|
// the host mirror first (once per host·commit in this process) so podSourceScript finds it instead of fetching
|
|
@@ -2721,12 +2875,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2721
2875
|
else if (seedSource.kind !== 'default') seedSkip = `source-${seedSource.kind}`;
|
|
2722
2876
|
else {
|
|
2723
2877
|
const resolveHead = options.resolveSourceHead ?? (options.kubectl ? undefined : resolveDefaultSourceHead);
|
|
2724
|
-
let head: { sha?: string; reason?: string } | undefined;
|
|
2878
|
+
let head: { sha?: string; reason?: string; originCalls?: number } | undefined;
|
|
2725
2879
|
try { head = resolveHead ? await resolveHead({ repoUrl, ...(seedSource.base ? { base: seedSource.base } : {}), cwd: seedCwd }) : undefined; }
|
|
2726
2880
|
catch { head = { reason: 'resolve-threw' }; }
|
|
2727
2881
|
if (!resolveHead) seedSkip = 'no-head-resolver';
|
|
2728
|
-
else if (head
|
|
2729
|
-
|
|
2882
|
+
else if (head) hostOriginCalls = typeof head.originCalls === 'number' && Number.isSafeInteger(head.originCalls) && head.originCalls >= 0 ? head.originCalls : null;
|
|
2883
|
+
if (head?.sha && /^[0-9a-f]{40}$/.test(head.sha)) { seedCommit = head.sha; sourceBaseSha = head.sha; }
|
|
2884
|
+
else if (resolveHead) seedSkip = `default-head-${head?.reason ?? 'unresolved'}`;
|
|
2730
2885
|
}
|
|
2731
2886
|
if (seedMirror && seedCommit && member?.sshHost) {
|
|
2732
2887
|
const seedHost = member.sshHost;
|
|
@@ -2737,7 +2892,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2737
2892
|
} catch (error) {
|
|
2738
2893
|
seed = { host: seedHost, ok: false, ms: 0, detail: String(error).slice(0, 300) };
|
|
2739
2894
|
}
|
|
2740
|
-
debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
|
|
2895
|
+
debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ...(sourceBaseSha ? { sourceBaseSha } : {}), ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
|
|
2741
2896
|
} else {
|
|
2742
2897
|
debug.log('self-implement.pod', 'mirror-seed-skipped', { job: name, reason: seedSkip ?? 'unknown', sourceKind: seedSource.kind, ...(member?.sshHost ? { host: member.sshHost } : {}) });
|
|
2743
2898
|
}
|
|
@@ -2772,7 +2927,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2772
2927
|
cleanupSecret();
|
|
2773
2928
|
return { exitCode: 1, output: '', error: { code: 'pod-provenance', message } };
|
|
2774
2929
|
}
|
|
2775
|
-
const job = podJobManifest({ provenance, name, namespace, fallbackChain, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(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: jobImageCommit, ...(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 } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
|
|
2930
|
+
const job = podJobManifest({ provenance, name, namespace, fallbackChain, configSnapshotHash: configSnapshot.hash, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...((seedSource.kind === 'default' && sourceBaseSha) ? { source: { ...seedSource, baseSha: sourceBaseSha } } : options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(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: jobImageCommit, ...(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 } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
|
|
2776
2931
|
const carriedBranch = goalDoc ? 'goal-doc' as const : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'author' as const : undefined;
|
|
2777
2932
|
const carriedChildLlm = carriedBranch ? podDelegatedChildLlm(jobArgs) : undefined;
|
|
2778
2933
|
jobApplyStartedAt = Date.now();
|
|
@@ -2780,6 +2935,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2780
2935
|
zaiPendingApply.delete(name); // apply 뒤엔 Job 라벨이 센다(성공) · 실패면 셀 것이 없다
|
|
2781
2936
|
if (a.status !== 0) { cleanupSecret(); return { exitCode: 1, output: a.stderr, error: { code: 'pod-apply', message: a.stderr.trim() } }; }
|
|
2782
2937
|
releaseAdmission?.applied?.(name, context, namespace);
|
|
2938
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-config-snapshot', data: {
|
|
2939
|
+
job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount,
|
|
2940
|
+
} }, ledgerDir); } catch (error) {
|
|
2941
|
+
debug.log('self-implement.pod', 'config-snapshot-ledger-unavailable', {
|
|
2942
|
+
job: name, reason: error instanceof Error ? error.message : String(error),
|
|
2943
|
+
}, { level: 'warn' });
|
|
2944
|
+
}
|
|
2783
2945
|
const imageFacts = { job: name, childRunId: liveChildRunId, image: jobImage, imageCommit: jobImageCommit, context };
|
|
2784
2946
|
// POD-LAUNCH-PROVENANCE — append-only «started» row: who · why · when, on the parent's existing run ledger.
|
|
2785
2947
|
const startedRow = { job: name, run: launchRunId, attempt: oomRetried ? 2 : 1, provenance: provenanceRowFromAnnotations(provenance.annotations) };
|
|
@@ -2859,11 +3021,36 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2859
3021
|
debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(openrouterCredentialRequired ? { openrouterKeyPresent: passEnv.includes('OPENROUTER_API_KEY') } : {}), ...(openGateway ? { openGatewayKeyPresent: passEnv.includes('OPENGATEWAY_API_KEY') } : {}), ...(anthropic ? { anthropicKeyPresent: passEnv.includes('ANTHROPIC_API_KEY') } : {}), ...(bedrockSpec ? { bedrockSecret: bedrockSpec.secretName, bedrockSecretKeys: bedrockSpec.keys, bedrockRegionFrom: bedrockSpec.region.from } : {}), ...(zaiRoute ? { zaiRoute, ...(zaiSpec ? { zaiSecret: zaiSpec.secretName } : {}) } : {}), extraArgs: options.extraArgs ?? [], ...(options.armEnv?.ELANOUS_ARM_ID ? { armId: options.armEnv.ELANOUS_ARM_ID } : {}) });
|
|
2860
3022
|
let state: 'complete' | 'failed' | 'aborted' = 'failed';
|
|
2861
3023
|
let failedReason = '';
|
|
3024
|
+
let deadlineJobCreatedAt: string | null = null;
|
|
3025
|
+
let deadlineJobCompletedAt: string | null = null;
|
|
2862
3026
|
let containerReason: string | null = null;
|
|
2863
3027
|
let containerExitCode: number | null = null;
|
|
2864
3028
|
// JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
|
|
2865
3029
|
// Observation only: failedReason · containerReason · containerExitCode keep driving the classification.
|
|
2866
3030
|
let podTermination: PodTermination | null = null;
|
|
3031
|
+
const refreshPodTermination = async (): Promise<void> => {
|
|
3032
|
+
if (state !== 'failed' || !podTermination || (podTermination.podLookup === 'terminated'
|
|
3033
|
+
&& podTermination.containerReason !== 'unknown' && podTermination.exitCode !== 'unknown'
|
|
3034
|
+
&& podTermination.finishedAt !== 'unknown')) return;
|
|
3035
|
+
// The result marker and the Job Failed condition can precede container termination status.
|
|
3036
|
+
// Re-read this launch's Pod once; keep the verdict's Job facts even if the Job has since been GC'd.
|
|
3037
|
+
await sleep(1_000);
|
|
3038
|
+
const retry = readPodTermination({ kubectl, namespace, job: name, path: podTermination.path,
|
|
3039
|
+
jobUid: lifecycleJobUid, jobRead: null });
|
|
3040
|
+
const observed = retry.podLookup === 'unavailable' ? podTermination : retry;
|
|
3041
|
+
const complete = observed.podLookup === 'terminated' && observed.containerReason !== 'unknown'
|
|
3042
|
+
&& observed.exitCode !== 'unknown' && observed.finishedAt !== 'unknown';
|
|
3043
|
+
const collectionFailureReason: PodTermination['collectionFailureReason'] | undefined = complete ? undefined
|
|
3044
|
+
: retry.podLookup === 'unavailable' ? 'pod-read-unavailable-after-retry'
|
|
3045
|
+
: retry.podLookup === 'absent' ? 'pod-absent-after-retry'
|
|
3046
|
+
: retry.podLookup === 'running' || retry.podLookup === 'pending' ? 'pod-still-running-after-retry'
|
|
3047
|
+
: retry.podLookup === 'terminated' ? 'terminated-fields-missing-after-retry'
|
|
3048
|
+
: 'pod-state-unknown-after-retry';
|
|
3049
|
+
podTermination = { ...podTermination, observedAt: retry.observedAt,
|
|
3050
|
+
podLookup: observed.podLookup, containerReason: observed.containerReason, exitCode: observed.exitCode,
|
|
3051
|
+
finishedAt: observed.finishedAt, oomKilled: observed.oomKilled, collectionAttempts: 2,
|
|
3052
|
+
...(collectionFailureReason ? { collectionFailureReason } : {}) };
|
|
3053
|
+
};
|
|
2867
3054
|
// METER-POD-ROLLUP-GAP — abort 때 Job 삭제 «전»에 거둔 로그 사본(삭제 뒤엔 PARTIAL 줄도 못 읽는다).
|
|
2868
3055
|
let abortLogs = '';
|
|
2869
3056
|
// ⭐ 런 «도중» 원장 증분 회수 — 호스트 슈퍼바이저가 Pod 걸음을 실시간으로 본다(🅣 요청 · 힐 루프 runtime 성형의 전제).
|
|
@@ -2950,7 +3137,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2950
3137
|
let jobReadError: unknown;
|
|
2951
3138
|
try { jobRead = kubectl(['-n', namespace, 'get', 'job', name, '-o', `jsonpath=${POD_TERMINATION_JOB_JSONPATH}`]); }
|
|
2952
3139
|
catch (error) { jobReadError = error; }
|
|
2953
|
-
|
|
3140
|
+
const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
|
|
3141
|
+
failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
|
|
3142
|
+
if (jobRead?.status === 0) {
|
|
3143
|
+
const [, , , createdText, completedText] = jobRead.stdout.replace(/\r?\n$/, '').split('\t');
|
|
3144
|
+
deadlineJobCreatedAt = createdText && Number.isFinite(Date.parse(createdText)) ? createdText : null;
|
|
3145
|
+
deadlineJobCompletedAt = completedText && Number.isFinite(Date.parse(completedText)) ? completedText : null;
|
|
3146
|
+
}
|
|
2954
3147
|
// One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
|
|
2955
3148
|
let podsRead: { status: number | null; stdout: string } | null = null;
|
|
2956
3149
|
try {
|
|
@@ -2973,6 +3166,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2973
3166
|
captureFailedJob(liveChildRunId);
|
|
2974
3167
|
if (jobReadError !== undefined) {
|
|
2975
3168
|
// Today's outcome stays (the throw ends the spawn as pod-error); the capture is in the ledger first.
|
|
3169
|
+
await refreshPodTermination();
|
|
2976
3170
|
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence: null, childRunId: liveChildRunId, job: name, podTermination } }, ledgerDir); }
|
|
2977
3171
|
catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
2978
3172
|
debug.log('self-implement.pod', 'pod-termination-captured', { job: name, podTermination, jobReadThrew: true }, { level: 'warn' });
|
|
@@ -3058,6 +3252,14 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3058
3252
|
if (!logs && abortLogs) logs = abortLogs;
|
|
3059
3253
|
// TA-POD-WARMBOOT-PARITY: the marker line is not child output — remove it so the last-line result parse sees the same bytes.
|
|
3060
3254
|
if (markerWait && markerToken && logs) logs = markerWait.stripPodResultMarker(logs, markerToken);
|
|
3255
|
+
const deadlineMarker = podDeadlineResultMarker(logs, name, liveChildRunId);
|
|
3256
|
+
if (deadlineMarker && state !== 'aborted' && state !== 'complete') {
|
|
3257
|
+
state = 'failed';
|
|
3258
|
+
failedReason = 'DeadlineExceeded';
|
|
3259
|
+
debug.log('self-implement.pod', 'deadline-result-marker', { job: name, childRunId: liveChildRunId, ...deadlineMarker });
|
|
3260
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-deadline-result', data: { job: name, childRunId: liveChildRunId, stopCause: 'deadline', ...deadlineMarker } }, ledgerDir); }
|
|
3261
|
+
catch { /* A full ledger must not hide the Pod's terminal marker. */ }
|
|
3262
|
+
}
|
|
3061
3263
|
let ledgerReason = '';
|
|
3062
3264
|
let ledgerCollected = false;
|
|
3063
3265
|
const collection = collectFullLogs('ledger-collect-incomplete', follower.owned ? new Set([liveChildRunId]) : undefined, (event, data) => {
|
|
@@ -3117,7 +3319,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3117
3319
|
continue;
|
|
3118
3320
|
}
|
|
3119
3321
|
// Pod 안 경로는 호스트에서 쓸 수 없다.
|
|
3120
|
-
let disposition = parsed ? { ...parsed, worktreePath: undefined } :
|
|
3322
|
+
let disposition: SelfImplementDisposition | undefined = parsed ? { ...parsed, worktreePath: undefined } : deadlineMarker
|
|
3323
|
+
? { stage: 'deadline', ok: false, ...(deadlineMarker.pr ? { prNumber: deadlineMarker.pr } : {}), ...(deadlineMarker.branch ? { branch: deadlineMarker.branch } : {}) }
|
|
3324
|
+
: undefined;
|
|
3121
3325
|
if (options.repairCommitOnly && state === 'complete' && !repairArtifactReady) {
|
|
3122
3326
|
disposition = { ...disposition, worktreePath: undefined, ok: false, stage: 'repair-artifact-missing', detail: 'Pod repair result or bundle was not collected' };
|
|
3123
3327
|
}
|
|
@@ -3261,8 +3465,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3261
3465
|
// the terminal result line can be followed by the useful stderr that explains the actual exit.
|
|
3262
3466
|
let noResultLogEvidence: Record<string, unknown> | null = null;
|
|
3263
3467
|
const shouldCaptureFailureLog = state === 'failed' && !oomKilled && failedReason !== 'DeadlineExceeded';
|
|
3264
|
-
|
|
3265
|
-
|
|
3468
|
+
const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
|
|
3469
|
+
if (shouldCaptureFailureLog || missingStage) {
|
|
3266
3470
|
const logRead = readPodNoResultLogTail({ run: kubectl, namespace, job: name, maxLines: POD_NO_RESULT_LOG_TAIL_LINES });
|
|
3267
3471
|
if ('tail' in logRead) {
|
|
3268
3472
|
noResultLogEvidence = missingStage
|
|
@@ -3272,11 +3476,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3272
3476
|
job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail,
|
|
3273
3477
|
}, { compact: { stringMax: 500 } });
|
|
3274
3478
|
} else {
|
|
3479
|
+
const unavailable = `log-unavailable: ${logRead.unavailable}`;
|
|
3275
3480
|
noResultLogEvidence = missingStage
|
|
3276
|
-
? { stderr:
|
|
3481
|
+
? { stderr: unavailable }
|
|
3277
3482
|
: { podLogUnavailable: logRead.unavailable };
|
|
3278
3483
|
debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
|
|
3279
|
-
job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
|
|
3484
|
+
job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
|
|
3485
|
+
logUnavailable: missingStage ? unavailable : logRead.unavailable,
|
|
3280
3486
|
}, { level: 'warn' });
|
|
3281
3487
|
}
|
|
3282
3488
|
}
|
|
@@ -3284,6 +3490,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3284
3490
|
if (noResultDiagnostic && !noResultDiagnostic.includes('stage=unknown')) {
|
|
3285
3491
|
debug.log('self-implement.pod', 'no-result-ledger-diagnostic', { job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic }, { compact: { stringMax: 500 } });
|
|
3286
3492
|
}
|
|
3493
|
+
// The marker can precede the container status by several seconds. Read the Pod after
|
|
3494
|
+
// collecting the child logs, before the first terminal evidence row is emitted.
|
|
3495
|
+
await refreshPodTermination();
|
|
3287
3496
|
// POD-LAUNCH-PROVENANCE — append-only «finished» row paired with its started row on job·run.
|
|
3288
3497
|
// Keyed on launchRunId like the started row; a reattached Job's inherited child run rides along as childRun.
|
|
3289
3498
|
// exitCode stays null when the container's code was not read (never filled in as 0).
|
|
@@ -3359,7 +3568,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3359
3568
|
if (unfitRetry) return unfitRetry;
|
|
3360
3569
|
if (!await acquireAdmission()) return admissionFailure();
|
|
3361
3570
|
member = await acquireSlot();
|
|
3362
|
-
if (options.pool && !member)
|
|
3571
|
+
if (options.pool && !member) {
|
|
3572
|
+
if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted');
|
|
3573
|
+
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
|
|
3574
|
+
}
|
|
3363
3575
|
if (member) context = member.context;
|
|
3364
3576
|
if (input.signal?.aborted) return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before OOM retry' } };
|
|
3365
3577
|
continue;
|
|
@@ -3428,6 +3640,17 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3428
3640
|
const deadlineExceeded = state === 'failed' && failedReason === 'DeadlineExceeded';
|
|
3429
3641
|
const deadlineSeconds = jobDeadlineSeconds;
|
|
3430
3642
|
if (deadlineExceeded) {
|
|
3643
|
+
const jobCreatedAt = deadlineJobCreatedAt;
|
|
3644
|
+
const timing = podJobFinishedTiming({ jobCreatedAt, jobCompletedAt: deadlineJobCompletedAt,
|
|
3645
|
+
podFinishedAt: typeof podTermination?.finishedAt === 'string' && Number.isFinite(Date.parse(podTermination.finishedAt))
|
|
3646
|
+
? podTermination.finishedAt : null,
|
|
3647
|
+
observedAt: new Date((options.now ?? Date.now)()).toISOString() });
|
|
3648
|
+
const lastStage = deadlineMarker?.stage ?? disposition?.stage ?? null;
|
|
3649
|
+
debug.log('pod.job', 'finished', {
|
|
3650
|
+
job: name, jobCreatedAt, finishedAt: timing.finishedAt, finishedAtSource: timing.finishedAtSource,
|
|
3651
|
+
elapsedMs: timing.elapsedMs,
|
|
3652
|
+
deadlineSec: deadlineSeconds, tier: oomRetried ? retryTier : memoryTier, lastStage,
|
|
3653
|
+
});
|
|
3431
3654
|
debug.log('self-implement.pod', 'deadline-exceeded', {
|
|
3432
3655
|
job: name,
|
|
3433
3656
|
deadlineSeconds,
|
|
@@ -3455,6 +3678,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3455
3678
|
const salvageOutcome = /^ELANOUS_POD_SALVAGE \S+ \S+$/m.test(logs) ? 'pushed' : logs.includes('ELANOUS_POD_SALVAGE_NONE') ? 'none' : 'unknown';
|
|
3456
3679
|
passJourneyNode('salvage', { provenance: 'self-implement-pod', outcome: salvageOutcome, data: { job: name } });
|
|
3457
3680
|
}
|
|
3681
|
+
const repairGateReceipt = disposition?.stage === 'gate-failed' ? gateFailureReceipt(disposition.gate) : null;
|
|
3682
|
+
if (repairGateReceipt) {
|
|
3683
|
+
for (const line of gateFailureReceiptLines(repairGateReceipt)) console.log(line);
|
|
3684
|
+
debug.log('self-implement.pod', 'gate-failure-receipt', { job: name, childRunId: liveChildRunId,
|
|
3685
|
+
signature: repairGateReceipt.signature, tests: repairGateReceipt.tests });
|
|
3686
|
+
}
|
|
3458
3687
|
return {
|
|
3459
3688
|
exitCode: podExitCode,
|
|
3460
3689
|
output: tail,
|
|
@@ -3610,7 +3839,9 @@ export function podNoResultLogTailLines(source: string, maxLines: number = POD_N
|
|
|
3610
3839
|
let chars = 0;
|
|
3611
3840
|
for (const line of lines.slice(-Math.max(0, maxLines)).reverse()) {
|
|
3612
3841
|
if (chars >= POD_NO_RESULT_LOG_TAIL_MAX_CHARS) break;
|
|
3613
|
-
const
|
|
3842
|
+
const redacted = redactSecretText(line);
|
|
3843
|
+
const limit = Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars);
|
|
3844
|
+
const bounded = redacted.length > limit ? `${redacted.slice(0, limit)}…[truncated]` : redacted;
|
|
3614
3845
|
if (!bounded) continue;
|
|
3615
3846
|
result.push(bounded);
|
|
3616
3847
|
chars += bounded.length;
|
|
@@ -3632,7 +3863,7 @@ export function readPodNoResultLogTail(args: {
|
|
|
3632
3863
|
}): PodNoResultLogRead {
|
|
3633
3864
|
const maxLines = args.maxLines ?? POD_NO_RESULT_LOG_TAIL_LINES;
|
|
3634
3865
|
try {
|
|
3635
|
-
const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, `--tail=${maxLines}`]);
|
|
3866
|
+
const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, '-c', 'child', `--tail=${maxLines}`]);
|
|
3636
3867
|
if (result.status !== 0) {
|
|
3637
3868
|
const reason = boundedPodLogText(result.stderr || result.stdout || '', POD_NO_RESULT_LOG_REASON_MAX_CHARS);
|
|
3638
3869
|
return { unavailable: reason || `kubectl logs exit ${result.status}` };
|
|
@@ -3928,7 +4159,7 @@ export async function rebuildLocalPodImageOnce(deps: {
|
|
|
3928
4159
|
});
|
|
3929
4160
|
});
|
|
3930
4161
|
});
|
|
3931
|
-
const result = await build('docker
|
|
4162
|
+
const result = await build(['docker', 'harness', 'build.sh'].join(sep));
|
|
3932
4163
|
if (result.status !== 0) {
|
|
3933
4164
|
return { image, action: 'failed', error: `--substrate pod: 이미지 굽기 실패 rc=${result.status}${result.error ? ` (${(result.error as NodeJS.ErrnoException).code ?? result.error.message})` : ''}: ${(result.stdout + result.stderr).slice(-400)}` };
|
|
3934
4165
|
}
|