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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import type { SelfImplementGateResult } from './orchestrator.js';
|
|
3
|
+
|
|
4
|
+
export interface GateFailureReceipt {
|
|
5
|
+
signature: `sha256:${string}`;
|
|
6
|
+
tests: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Only measured, introduced, non-timeout test failures are stable enough to stop a repeated repair. */
|
|
10
|
+
export function gateFailureReceipt(gate: SelfImplementGateResult | undefined): GateFailureReceipt | null {
|
|
11
|
+
if (!gate || gate.passed || gate.testStepExecuted !== true || !gate.baselineFailures
|
|
12
|
+
|| !gate.reflectGateFacts || gate.reflectGateFacts.unknown !== 0
|
|
13
|
+
|| (gate.reflectGateFacts.timedOut ?? 0) > 0 || (gate.reflectGateFacts.rerunNotRun ?? 0) > 0
|
|
14
|
+
|| (gate.reflectGateFacts.mayVaryNonTimeout ?? 0) > 0) return null;
|
|
15
|
+
const introduced = gate.baselineFailures.filter((failure) => failure.attribution === 'introduced');
|
|
16
|
+
if (!introduced.length || introduced.length !== gate.reflectGateFacts.introduced) return null;
|
|
17
|
+
const normalized: Array<{ file: string; name: string; kind: string }> = [];
|
|
18
|
+
for (const failure of introduced) {
|
|
19
|
+
const file = failure.file?.replace(/\\/g, '/').trim();
|
|
20
|
+
const name = failure.name.normalize('NFC').replace(/\s+/g, ' ').trim();
|
|
21
|
+
if (!file || file.startsWith('/') || /^[A-Za-z]:\//.test(file) || file.split('/').includes('..')
|
|
22
|
+
|| !name || /[\r\n]/.test(name)
|
|
23
|
+
|| failure.timeoutRegression || /\btimed out\b|\btimeout\b/i.test(failure.diagnostic ?? '')) return null;
|
|
24
|
+
const diagnostic = failure.diagnostic ?? '';
|
|
25
|
+
const kind = /module not found|cannot find module|ERR_MODULE_NOT_FOUND/i.test(diagnostic) ? 'module-load'
|
|
26
|
+
: /expect\(|AssertionError|Expected:/i.test(diagnostic) ? 'assertion'
|
|
27
|
+
: /\berror:/i.test(diagnostic) ? 'runtime-error' : 'test-failure';
|
|
28
|
+
normalized.push({ file, name, kind });
|
|
29
|
+
}
|
|
30
|
+
normalized.sort((a, b) => {
|
|
31
|
+
const left = JSON.stringify(a);
|
|
32
|
+
const right = JSON.stringify(b);
|
|
33
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
34
|
+
});
|
|
35
|
+
const unique = [...new Map(normalized.map((entry) => [JSON.stringify(entry), entry])).values()];
|
|
36
|
+
if (unique.length !== introduced.length) return null;
|
|
37
|
+
const signature = `sha256:${createHash('sha256').update(JSON.stringify(unique)).digest('hex')}` as const;
|
|
38
|
+
return { signature, tests: unique.map(({ file, name, kind }) => `${file} > ${name} (${kind})`) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The worker reads these exact lines from harness stdout and persists the receipt. */
|
|
42
|
+
export function gateFailureReceiptLines(receipt: GateFailureReceipt): string[] {
|
|
43
|
+
return [`GATE_FAILURE_SIGNATURE=${receipt.signature}`, `GATE_FAILURE_TESTS=${JSON.stringify(receipt.tests)}`];
|
|
44
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GATE-ONCE-PER-HEAD (0.2.40 첫 조각 · OP 10-27 23:0x 지시) — host-regate 통과 영수증의 지속 등록부.
|
|
3
|
+
*
|
|
4
|
+
* S: 같은 PR head 의 자식 gate 뒤 host-regate 와 착지 게이트가 같은 시험을 다시 실행해 Pod 와 호스트 자원을 소모한다.
|
|
5
|
+
* C: 통과 사실이 어디에도 남지 않아 매 호출이 전 검사를 다시 돌릴 수밖에 없다.
|
|
6
|
+
* Q: 정확히 같은 통합 입력과 측정 범위에 대해 이미 통과한 게이트만 승계할 수 있는가?
|
|
7
|
+
* A: 통과 영수증을 이 등록부에 원자적으로 기록하고, runHostRegate 가 재검증·통합 후보 구성 뒤 현재 key 와
|
|
8
|
+
* 일치하는 통과 영수증만 승계한다. 불일치·결손·불완전·실패/측정불가 영수증은 원래 검사를 실행한다.
|
|
9
|
+
*
|
|
10
|
+
* 원본 영수증 없이 통과 판정 금지: 승계는 저장된 영수증 행 하나를 통해서만 일어나고, 그 행의 key 는
|
|
11
|
+
* 행 스스로의 필드에서 다시 계산되어야 한다(gateReceiptSelfKey). key 가 필드와 맞지 않는 행은 저장도
|
|
12
|
+
* 승계도 거절한다.
|
|
13
|
+
*
|
|
14
|
+
* 원자성: saveGateReceipts 는 임시 파일에 온전히 쓴 뒤 rename(2) 로 바꾼다 — 부분 쓰기는 관측될 수 없다.
|
|
15
|
+
* 프로세스끼리의 동시 저장은 각자 온전한 등록부를 남긴다(늦은 쪽이 이긴다). 잃은 영수증은 다음 호출을
|
|
16
|
+
* 원래 검사로 되돌릴 뿐, 잘못된 통과를 만들지 않는다 — 실패 방향으로 열린다.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
19
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { basename, dirname, join } from 'node:path';
|
|
21
|
+
import { gateTestBaseline } from '../../scripts/lib/gate-test-env.js';
|
|
22
|
+
|
|
23
|
+
export const GATE_RECEIPT_SCHEMA = 1;
|
|
24
|
+
export type GateReceiptVerdict = 'passed' | 'failed' | 'unmeasured';
|
|
25
|
+
|
|
26
|
+
const SHA40 = /^[0-9a-f]{40}$/i;
|
|
27
|
+
const SHA256 = /^[0-9a-f]{64}$/i;
|
|
28
|
+
|
|
29
|
+
/** 한 번의 host-regate 측정을 정체 짓는 입력. 판정(verdict)은 identity 가 아니라 key 계산에 들어간다. */
|
|
30
|
+
export interface GateReceiptIdentity {
|
|
31
|
+
/** 40자 PR head SHA */
|
|
32
|
+
headCommit: string;
|
|
33
|
+
/** 40자 실제 측정 base SHA — PR 에 기록된 baseRefOid 가 아니라 얹어 잰 끝 */
|
|
34
|
+
baseCommit: string;
|
|
35
|
+
/** 검사를 실행한 Bun 식별값(bun --version) */
|
|
36
|
+
bunVersion: string;
|
|
37
|
+
/** 검사가 설치·실행한 lockfile 의 SHA-256(bun.lock/bun.lockb 바이트) — 없으면 'absent' */
|
|
38
|
+
lockfileHash: string;
|
|
39
|
+
/** 정규화된 radius 파일 집합(병합 후보 기준 변경 파일 — 중복 제거·정렬) */
|
|
40
|
+
radiusFiles: readonly string[];
|
|
41
|
+
/** 이 영수증이 통과한 검사 토큰(종류 ⊕ 측정 범위 — 중복 제거·정렬) */
|
|
42
|
+
checks: readonly string[];
|
|
43
|
+
/** 실행 환경 지문(gateEnvFingerprint) */
|
|
44
|
+
envFingerprint: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface GateReceipt extends GateReceiptIdentity {
|
|
48
|
+
schema: typeof GATE_RECEIPT_SCHEMA;
|
|
49
|
+
key: string;
|
|
50
|
+
verdict: GateReceiptVerdict;
|
|
51
|
+
savedAt: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type GateReceiptRegistry = Record<string, GateReceipt>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 검사 종류·판정·환경까지 포함한 정준 직렬화의 SHA-256. 같은 측정·같은 판정만 같은 key 를 받는다.
|
|
58
|
+
* head/base 는 40자 hex 여야 한다 — 그보다 못한 입력으로 영수증을 만들 수 없게 문을 닫는다.
|
|
59
|
+
*/
|
|
60
|
+
export function computeReceiptKey(identity: GateReceiptIdentity, verdict: GateReceiptVerdict): string {
|
|
61
|
+
if (!SHA40.test(identity.headCommit)) throw new Error('gate receipt head SHA is not 40 hex characters');
|
|
62
|
+
if (!SHA40.test(identity.baseCommit)) throw new Error('gate receipt base SHA is not 40 hex characters');
|
|
63
|
+
const canonical = JSON.stringify({
|
|
64
|
+
schema: GATE_RECEIPT_SCHEMA,
|
|
65
|
+
head: identity.headCommit.toLowerCase(),
|
|
66
|
+
base: identity.baseCommit.toLowerCase(),
|
|
67
|
+
bun: identity.bunVersion,
|
|
68
|
+
lockfile: identity.lockfileHash,
|
|
69
|
+
radius: [...new Set(identity.radiusFiles)].sort(),
|
|
70
|
+
checks: [...new Set(identity.checks)].sort(),
|
|
71
|
+
env: identity.envFingerprint,
|
|
72
|
+
verdict,
|
|
73
|
+
});
|
|
74
|
+
return createHash('sha256').update(canonical).digest('hex');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** 행의 key 를 행 스스로의 필드에서 다시 계산한다 — 위조·불일치 행은 저장된 key 와 어긋난다. */
|
|
78
|
+
export function gateReceiptSelfKey(receipt: GateReceipt): string {
|
|
79
|
+
return computeReceiptKey(receipt, receipt.verdict);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isGateReceipt(value: unknown): value is GateReceipt {
|
|
83
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
84
|
+
const row = value as Partial<GateReceipt>;
|
|
85
|
+
return row.schema === GATE_RECEIPT_SCHEMA && typeof row.key === 'string' && SHA256.test(row.key)
|
|
86
|
+
&& (row.verdict === 'passed' || row.verdict === 'failed' || row.verdict === 'unmeasured')
|
|
87
|
+
&& SHA40.test(row.headCommit ?? '') && SHA40.test(row.baseCommit ?? '')
|
|
88
|
+
&& typeof row.bunVersion === 'string' && typeof row.lockfileHash === 'string'
|
|
89
|
+
&& Array.isArray(row.radiusFiles) && row.radiusFiles.every((file) => typeof file === 'string')
|
|
90
|
+
&& Array.isArray(row.checks) && row.checks.every((check) => typeof check === 'string')
|
|
91
|
+
&& typeof row.envFingerprint === 'string' && typeof row.savedAt === 'string';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 결손·손상 파일은 빈 등록부로 복구한다 — 못 읽은 영수증은 «없다» 로 취급해 원래 검사를 실행한다.
|
|
96
|
+
* 모양이 어긋나거나 행의 key 가 맵 키와 다른 행은 버린다.
|
|
97
|
+
*/
|
|
98
|
+
export function loadGateReceipts(path: string): GateReceiptRegistry {
|
|
99
|
+
let raw: string;
|
|
100
|
+
try { raw = readFileSync(path, 'utf8'); }
|
|
101
|
+
catch { return {}; }
|
|
102
|
+
let parsed: unknown;
|
|
103
|
+
try { parsed = JSON.parse(raw); }
|
|
104
|
+
catch { return {}; }
|
|
105
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {};
|
|
106
|
+
const registry: GateReceiptRegistry = {};
|
|
107
|
+
for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {
|
|
108
|
+
if (!isGateReceipt(value) || value.key !== key) continue;
|
|
109
|
+
registry[key] = value;
|
|
110
|
+
}
|
|
111
|
+
return registry;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** write-then-rename 원자적 기록 — 부분 쓰기 노출 금지. 임시 파일은 같은 디렉터리에 무작위 이름으로 둔다. */
|
|
115
|
+
export function saveGateReceipts(path: string, registry: GateReceiptRegistry): void {
|
|
116
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
117
|
+
const tmp = join(dirname(path), `.${basename(path)}.${process.pid}.${randomUUID()}.tmp`);
|
|
118
|
+
writeFileSync(tmp, `${JSON.stringify(registry, null, 2)}\n`);
|
|
119
|
+
try { renameSync(tmp, path); }
|
|
120
|
+
catch (error) {
|
|
121
|
+
try { unlinkSync(tmp); } catch { /* 최선의 정리 — 원래 오류를 지운다 */ }
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** 통과 영수증을 지속 등록부에 원자적으로 병합 기록한다. key 가 필드와 맞지 않는 행은 쓰기 단계에서 거절한다. */
|
|
127
|
+
export function saveGateReceipt(path: string, receipt: GateReceipt): void {
|
|
128
|
+
if (gateReceiptSelfKey(receipt) !== receipt.key) throw new Error('gate receipt key does not match its own fields');
|
|
129
|
+
const registry = loadGateReceipts(path);
|
|
130
|
+
registry[receipt.key] = receipt;
|
|
131
|
+
saveGateReceipts(path, registry);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 승계 거절 사유. 불일치(head/base/env/Bun·lockfile/radius)·결손·불완전(현재 측정 범위 미커버)·
|
|
136
|
+
* 실패/측정불가 판정을 가려 한 줄로 남긴다 — debug.log 의 decline 이유가 된다.
|
|
137
|
+
*/
|
|
138
|
+
export function describeGateReceiptDecline(probe: GateReceiptIdentity, registry: GateReceiptRegistry): string {
|
|
139
|
+
const receipts = Object.values(registry);
|
|
140
|
+
if (!receipts.length) return 'gate receipt registry empty';
|
|
141
|
+
const sameHeadBase = receipts.filter((receipt) => receipt.headCommit.toLowerCase() === probe.headCommit.toLowerCase()
|
|
142
|
+
&& receipt.baseCommit.toLowerCase() === probe.baseCommit.toLowerCase());
|
|
143
|
+
if (!sameHeadBase.length) return `no receipt for head ${probe.headCommit.slice(0, 12)} base ${probe.baseCommit.slice(0, 12)}`;
|
|
144
|
+
for (const receipt of sameHeadBase) {
|
|
145
|
+
const differs: string[] = [];
|
|
146
|
+
if (receipt.verdict !== 'passed') differs.push(`verdict=${receipt.verdict}`);
|
|
147
|
+
if (receipt.envFingerprint !== probe.envFingerprint) differs.push('env fingerprint differs');
|
|
148
|
+
if (receipt.bunVersion !== probe.bunVersion || receipt.lockfileHash !== probe.lockfileHash) differs.push('bun/lockfile differs');
|
|
149
|
+
if ([...new Set(receipt.radiusFiles)].sort().join('\n') !== [...new Set(probe.radiusFiles)].sort().join('\n')) differs.push('changed-file radius differs');
|
|
150
|
+
const current = [...new Set(probe.checks)].sort();
|
|
151
|
+
const stored = [...new Set(receipt.checks)].sort();
|
|
152
|
+
if (stored.join('\n') !== current.join('\n')) {
|
|
153
|
+
const missing = current.filter((check) => !stored.includes(check));
|
|
154
|
+
differs.push(missing.length && stored.every((check) => current.includes(check))
|
|
155
|
+
? `receipt does not cover: ${missing.join(',')}`
|
|
156
|
+
: `receipt checks differ (stored ${stored.join(',')})`);
|
|
157
|
+
}
|
|
158
|
+
if (differs.length) return `receipt ${receipt.key.slice(0, 12)} ${differs.join(' · ')}`;
|
|
159
|
+
}
|
|
160
|
+
return 'no stored receipt matches this measurement key';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** 실행 환경 지문: 플랫폼 ⊕ 게이트 시험 baseline(TZ·locale·fake-LLM 스위치)의 정준 직렬화 SHA-256. */
|
|
164
|
+
export function gateEnvFingerprint(env: NodeJS.ProcessEnv): string {
|
|
165
|
+
const baseline = gateTestBaseline(env);
|
|
166
|
+
const canonical = JSON.stringify({
|
|
167
|
+
platform: process.platform,
|
|
168
|
+
env: Object.fromEntries(Object.entries(baseline).sort(([a], [b]) => a.localeCompare(b))),
|
|
169
|
+
});
|
|
170
|
+
return createHash('sha256').update(canonical).digest('hex');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** 후보 워크트리가 실제로 설치·실행한 lockfile 의 SHA-256. 둘 다 없으면 'absent'. */
|
|
174
|
+
export function gateLockfileHash(worktree: string): string {
|
|
175
|
+
for (const name of ['bun.lock', 'bun.lockb']) {
|
|
176
|
+
if (!existsSync(join(worktree, name))) continue;
|
|
177
|
+
return createHash('sha256').update(readFileSync(join(worktree, name))).digest('hex');
|
|
178
|
+
}
|
|
179
|
+
return 'absent';
|
|
180
|
+
}
|
|
@@ -94,16 +94,20 @@ export function remoteSelfGateArgv(input: {
|
|
|
94
94
|
changed?: boolean;
|
|
95
95
|
base?: string;
|
|
96
96
|
shards?: number;
|
|
97
|
+
shardConcurrency?: number;
|
|
97
98
|
fixedShardDistribution?: boolean;
|
|
98
99
|
includeImporters?: boolean;
|
|
100
|
+
noInherit?: boolean;
|
|
99
101
|
artifactDir?: string;
|
|
100
102
|
}, sha: (ref: string) => string): string[] {
|
|
101
103
|
const shards = input.shards ?? (input.includeImporters ? 2 : undefined);
|
|
102
104
|
return ['bun', 'bin/elanous.mjs', 'self', 'gate', '--local', ...(input.changed ? ['--changed'] : []),
|
|
103
105
|
...(input.base ? ['--base', input.base === 'origin/main' ? input.base : sha(input.base)] : []),
|
|
104
106
|
...(shards !== undefined ? ['--shards', String(shards)] : []),
|
|
107
|
+
...(input.shardConcurrency !== undefined ? ['--shard-concurrency', String(input.shardConcurrency)] : []),
|
|
105
108
|
...(input.fixedShardDistribution ? ['--fixed-shard-distribution'] : []),
|
|
106
109
|
...(input.includeImporters ? ['--include-importers'] : []),
|
|
110
|
+
...(input.noInherit ? ['--no-inherit'] : []),
|
|
107
111
|
...(input.artifactDir ? ['--artifact-dir', input.artifactDir] : [])];
|
|
108
112
|
}
|
|
109
113
|
|
|
@@ -129,6 +133,8 @@ export function decideGateDispatch(input: { flags: Pick<GateRemoteFlags, 'remote
|
|
|
129
133
|
|
|
130
134
|
export const SLOT_DIR = '/tmp/elanous-gate-remote-slots';
|
|
131
135
|
const BUSY = '__GATE_REMOTE_BUSY';
|
|
136
|
+
const HEARTBEAT = '__GATE_REMOTE_HEARTBEAT=';
|
|
137
|
+
const REMOTE_RUN_LIMIT_SECONDS = 105 * 60;
|
|
132
138
|
|
|
133
139
|
/** Shell lines that run "$W/run.sh" under the first free of `cap` slot locks, or print the busy marker and exit 98.
|
|
134
140
|
* run.sh must create "$W/started" first: that is how a lock refusal is told apart from the run's own exit code. */
|
|
@@ -136,14 +142,14 @@ export type SlotLockTool = 'flock' | 'lockf';
|
|
|
136
142
|
const SLOT_LOCK = { flock: 'flock -n', lockf: 'lockf -k -s -t 0' } as const;
|
|
137
143
|
|
|
138
144
|
/** `tools` is the preference order (default: Linux flock, then BSD/macOS lockf); a test can pin one path. */
|
|
139
|
-
function hostSlotScriptWithSlot(cap: number, dir: string, tools: readonly SlotLockTool[], passSlot: boolean): string[] {
|
|
145
|
+
function hostSlotScriptWithSlot(cap: number, dir: string, tools: readonly SlotLockTool[], passSlot: boolean, supervised = false): string[] {
|
|
140
146
|
const n = Math.min(MAX_HOST_CAP, Math.max(1, Math.floor(cap)));
|
|
141
147
|
const pick = tools.map((tool, i) => `${i ? 'elif' : 'if'} command -v ${tool} >/dev/null 2>&1; then GL="${SLOT_LOCK[tool]}"; `).join('');
|
|
142
148
|
return [
|
|
143
149
|
`GS=${quote(dir)}; mkdir -p "$GS" || infra slots`,
|
|
144
150
|
`${pick}else infra lock-tool; fi`,
|
|
145
151
|
'load1() { if [ -r /proc/loadavg ]; then awk \'NR==1 {print $1}\' /proc/loadavg; elif command -v sysctl >/dev/null 2>&1; then sysctl -n vm.loadavg 2>/dev/null | awk \'{gsub(/[{}]/, ""); print $1}\'; else echo unknown; fi; }',
|
|
146
|
-
`n=1; while [ $n -le ${n} ]; do $GL "$GS/slot$n" ${passSlot ? 'env GATE_REMOTE_SLOT="$n" ' : ''}sh "$W
|
|
152
|
+
`n=1; while [ $n -le ${n} ]; do $GL "$GS/slot$n" ${passSlot ? 'env GATE_REMOTE_SLOT="$n" ' : ''}sh "$W/${supervised ? 'supervise.sh' : 'run.sh'}"; s=$?; ${supervised ? '[ -f "$W/supervisor-timeout" ] && infra run-timeout; [ -f "$W/supervisor-infra" ] && infra supervisor-lost; ' : ''}[ -f "$W/started" ] && exit $s; n=$((n+1)); done`,
|
|
147
153
|
`echo "${BUSY}=$((n-1));load1=$(load1)" >&2; exit 98`,
|
|
148
154
|
];
|
|
149
155
|
}
|
|
@@ -152,6 +158,53 @@ export function hostSlotScript(cap: number, dir = SLOT_DIR, tools: readonly Slot
|
|
|
152
158
|
return hostSlotScriptWithSlot(cap, dir, tools, false);
|
|
153
159
|
}
|
|
154
160
|
|
|
161
|
+
/** A slot holder owns exactly one new process group. On a lost SSH shell or wall limit it signals only that group,
|
|
162
|
+
* after checking its unreaped direct child's PGID. The heartbeat also detects a severed SSH output pipe while
|
|
163
|
+
* a silent test is running; runOnRemote removes only these transport lines from the tool's stderr. */
|
|
164
|
+
export function remoteSupervisorScript(limitSeconds = REMOTE_RUN_LIMIT_SECONDS): string {
|
|
165
|
+
const limit = Number.isSafeInteger(limitSeconds) && limitSeconds > 0 ? limitSeconds : REMOTE_RUN_LIMIT_SECONDS;
|
|
166
|
+
return [
|
|
167
|
+
'#!/bin/sh',
|
|
168
|
+
'child=',
|
|
169
|
+
'ready=0',
|
|
170
|
+
'owned_group() {',
|
|
171
|
+
' [ -n "$child" ] && kill -0 "$child" 2>/dev/null && [ "$(ps -p "$child" -o pgid= 2>/dev/null | tr -d " ")" = "$child" ] || return 1',
|
|
172
|
+
'}',
|
|
173
|
+
'reap() {',
|
|
174
|
+
// Our direct child stays unreaped until the caller waits, so its PID/PGID cannot be reused here.
|
|
175
|
+
' [ "$ready" -eq 1 ] && owned_group || return 0',
|
|
176
|
+
' kill -TERM -- "-$child" 2>/dev/null || kill -TERM "-$child" 2>/dev/null || :',
|
|
177
|
+
' sleep 2',
|
|
178
|
+
// The leader remains our unreaped child until the caller waits, so its PGID cannot be reused here. A TERM-ignoring
|
|
179
|
+
// grandchild may outlive the leader; rechecking only the leader would miss that member of the same owned group.
|
|
180
|
+
' kill -KILL -- "-$child" 2>/dev/null || kill -KILL "-$child" 2>/dev/null || :',
|
|
181
|
+
'}',
|
|
182
|
+
'trap \'reap\' HUP INT TERM EXIT',
|
|
183
|
+
'perl -MPOSIX -e \'POSIX::setpgid(0,0) == 0 or die "setpgid: $!"; exec @ARGV\' sh "$W/run.sh" &',
|
|
184
|
+
'child=$!',
|
|
185
|
+
// Set this only after spawning the worker so the worker keeps its normal SIGPIPE behavior.
|
|
186
|
+
'trap \'\' PIPE',
|
|
187
|
+
// The SSH parent can disappear before the child has called setpgid. Wait briefly for the ownership proof first.
|
|
188
|
+
'ready=0; attempt=0',
|
|
189
|
+
'while [ "$attempt" -lt 20 ] && kill -0 "$child" 2>/dev/null; do',
|
|
190
|
+
' if owned_group; then ready=1; break; fi',
|
|
191
|
+
' attempt=$((attempt+1)); sleep 1',
|
|
192
|
+
'done',
|
|
193
|
+
'if [ "$ready" -eq 0 ] && kill -0 "$child" 2>/dev/null; then kill -TERM "$child" 2>/dev/null || :; wait "$child" 2>/dev/null || :; : > "$W/supervisor-infra"; exit 125; fi',
|
|
194
|
+
'started=$(date +%s)',
|
|
195
|
+
'while kill -0 "$child" 2>/dev/null; do',
|
|
196
|
+
' if [ "$(($(date +%s) - started))" -ge ' + limit + ' ]; then reap; wait "$child" 2>/dev/null || :; : > "$W/supervisor-timeout"; exit 124; fi',
|
|
197
|
+
' if ! kill -0 "$GATE_REMOTE_SSH_SHELL" 2>/dev/null; then reap; wait "$child" 2>/dev/null || :; : > "$W/supervisor-infra"; exit 125; fi',
|
|
198
|
+
' if ! printf "\\n' + HEARTBEAT + '%s\\n" "$W" >&2; then reap; wait "$child" 2>/dev/null || :; : > "$W/supervisor-infra"; exit 125; fi',
|
|
199
|
+
' sleep 5',
|
|
200
|
+
'done',
|
|
201
|
+
'wait "$child"; rc=$?',
|
|
202
|
+
'trap - HUP INT TERM EXIT',
|
|
203
|
+
'exit "$rc"',
|
|
204
|
+
'',
|
|
205
|
+
].join('\n');
|
|
206
|
+
}
|
|
207
|
+
|
|
155
208
|
// ── remote execution ───────────────────────────────────────────────
|
|
156
209
|
|
|
157
210
|
export interface ExecResult { rc: number | null; stdout: string; stderr: string; error?: string }
|
|
@@ -215,7 +268,7 @@ export interface PayloadFile { env: string; content: string }
|
|
|
215
268
|
export type RemoteArgv = string[] | ((sha: (ref: string) => string) => string[]);
|
|
216
269
|
|
|
217
270
|
/** Build the remote shell script (exported for tests). Every setup failure ends in an INFRA marker, the tool's rc in an RC marker. */
|
|
218
|
-
export function remoteScript(input: { mirror: string; commit: string; fetchShas: string[]; mainSha?: string; argv: string[]; installPwa: boolean; stableCheckout?: boolean; payloadFiles?: PayloadFile[]; hostCap?: number; slotDir?: string }): string {
|
|
271
|
+
export function remoteScript(input: { mirror: string; commit: string; fetchShas: string[]; mainSha?: string; argv: string[]; installPwa: boolean; stableCheckout?: boolean; payloadFiles?: PayloadFile[]; hostCap?: number; slotDir?: string; runLimitSeconds?: number }): string {
|
|
219
272
|
const mirror = input.mirror.startsWith('~/') ? `"$HOME"/${quote(input.mirror.slice(2))}` : quote(input.mirror);
|
|
220
273
|
const fetches = input.fetchShas.map((sha) => `refs/elanous/gate/${sha}:refs/elanous/gate/${sha}`).join(' ');
|
|
221
274
|
const payloads = (input.payloadFiles ?? []).filter((file) => /^[A-Z_][A-Z0-9_]*$/.test(file.env));
|
|
@@ -278,11 +331,16 @@ export function remoteScript(input: { mirror: string; commit: string; fetchShas:
|
|
|
278
331
|
'W=$(mktemp -d /var/tmp/elanous-gate-remote-XXXXXXXX) || infra mktemp',
|
|
279
332
|
'export W',
|
|
280
333
|
'trap \'rm -rf "$W"\' EXIT',
|
|
334
|
+
'command -v perl >/dev/null 2>&1 && command -v ps >/dev/null 2>&1 || infra supervisor-tool',
|
|
335
|
+
'GATE_REMOTE_SSH_SHELL=$$; export GATE_REMOTE_SSH_SHELL',
|
|
281
336
|
...payloadLines,
|
|
282
337
|
`cat > "$W/run.sh" <<'${RUN}' || infra run-script`,
|
|
283
338
|
...work,
|
|
284
339
|
RUN,
|
|
285
|
-
|
|
340
|
+
'cat > "$W/supervise.sh" <<\'__GATE_REMOTE_SUPERVISE__\' || infra supervise-script',
|
|
341
|
+
remoteSupervisorScript(input.runLimitSeconds),
|
|
342
|
+
'__GATE_REMOTE_SUPERVISE__',
|
|
343
|
+
...hostSlotScriptWithSlot(input.hostCap ?? GATE_REMOTE_DEFAULTS.hostCap, input.slotDir ?? SLOT_DIR, ['flock', 'lockf'], !!input.stableCheckout, true),
|
|
286
344
|
'}',
|
|
287
345
|
'',
|
|
288
346
|
].join('\n');
|
|
@@ -338,11 +396,22 @@ export function runOnRemote(opts: RemoteRunOptions, runner: GateRemoteRunner = r
|
|
|
338
396
|
env: { ...process.env, GIT_SSH_COMMAND: 'ssh -o BatchMode=yes -o ConnectTimeout=10', GIT_TERMINAL_PROMPT: '0' },
|
|
339
397
|
});
|
|
340
398
|
if (push.rc !== 0 || push.error) return { kind: 'infra', stage: 'push', rc: push.rc, stderr: push.stderr || push.error || '', reason: `push-failed rc=${push.rc}: ${(push.stderr || push.error || '').trim().split('\n').slice(-2).join(' | ')}` };
|
|
341
|
-
const
|
|
342
|
-
const
|
|
399
|
+
const sshTimeoutMs = opts.timeoutMs ?? 120 * 60_000;
|
|
400
|
+
const script = remoteScript({ mirror: opts.mirror, commit, fetchShas: shas, mainSha, argv, installPwa: opts.installPwa ?? false, stableCheckout: opts.stableCheckout, payloadFiles: opts.payloadFiles, hostCap: opts.hostCap, slotDir: opts.slotDir,
|
|
401
|
+
runLimitSeconds: Math.min(REMOTE_RUN_LIMIT_SECONDS, Math.max(1, Math.floor((sshTimeoutMs - 30_000) / 1000))) });
|
|
402
|
+
const run = runner.ssh(opts.host, script, sshTimeoutMs);
|
|
343
403
|
// The script prints "\n<marker><rc>\n": everything before that leading newline is the tool's own stderr, byte for byte.
|
|
344
404
|
const stdoutBytes = Buffer.from(run.stdout);
|
|
345
|
-
const
|
|
405
|
+
const rawStderr = Buffer.from(run.stderr);
|
|
406
|
+
// Transport heartbeats may arrive after the RC marker when a short run races the supervisor's final poll.
|
|
407
|
+
// Strip only complete, run-scoped heartbeat lines as bytes so arbitrary tool stderr stays byte-identical.
|
|
408
|
+
const heartbeatLine = /\n__GATE_REMOTE_HEARTBEAT=\/var\/tmp\/elanous-gate-remote-[A-Za-z0-9]+\n/g;
|
|
409
|
+
const heartbeatRanges = [...rawStderr.toString('latin1').matchAll(heartbeatLine)].map((match) => [match.index!, match.index! + match[0].length] as const);
|
|
410
|
+
let previous = 0;
|
|
411
|
+
const kept: Buffer[] = [];
|
|
412
|
+
for (const [from, to] of heartbeatRanges) { kept.push(rawStderr.subarray(previous, from)); previous = to; }
|
|
413
|
+
kept.push(rawStderr.subarray(previous));
|
|
414
|
+
const stderrBytes = Buffer.concat(kept);
|
|
346
415
|
const stderrText = stderrBytes.toString('utf8');
|
|
347
416
|
const marker = stderrBytes.lastIndexOf(Buffer.from(`\n${RC}`));
|
|
348
417
|
// Busy (98) and setup failure (97) are the script's own exits, each with its marker as the last stderr line. A completed
|
|
@@ -448,6 +517,11 @@ export interface DispatchOptions {
|
|
|
448
517
|
reportRemoteHost?: boolean;
|
|
449
518
|
/** Release gate host reservations shared by self gate and changed typecheck. */
|
|
450
519
|
reservationRoot?: string;
|
|
520
|
+
/** Self gate only: hosts to try when the first host holds a release reservation (default: `host-e-wsl` for
|
|
521
|
+
* `node-b`, the same alternative the unmeasured hint names — a reservation is never a local fallback). */
|
|
522
|
+
reservationAltHosts?: string[];
|
|
523
|
+
/** Self gate only: bounded wait for the reservation release, in seconds (default: `settings.slotWaitSeconds`). */
|
|
524
|
+
reservationWaitSeconds?: number;
|
|
451
525
|
runLocal: () => number | Promise<number>;
|
|
452
526
|
/** Called once with the final remote outcome (never on a local decision), before its output passes through or the
|
|
453
527
|
* local fallback runs — e.g. `self gate --artifact-dir` fetches (ran) or removes (infra) the host-side artifact dir.
|
|
@@ -467,6 +541,26 @@ export interface DispatchDeps {
|
|
|
467
541
|
write?: { out: (data: string | Uint8Array) => void; err: (data: string | Uint8Array) => void };
|
|
468
542
|
}
|
|
469
543
|
|
|
544
|
+
/** Hosts a reserved self gate may fall back to: an explicit list wins, otherwise `node-b` (the only host the old
|
|
545
|
+
* unmeasured hint named an alternative for) falls back to `host-e-wsl`. Invalid or duplicate entries are dropped. */
|
|
546
|
+
export function gateReservationAlternateHosts(reservedHost: string, explicit?: string[]): string[] {
|
|
547
|
+
const candidates = explicit ?? (reservedHost === 'node-b' ? ['host-e-wsl'] : []);
|
|
548
|
+
const seen = new Set<string>([reservedHost]);
|
|
549
|
+
const hosts: string[] = [];
|
|
550
|
+
for (const candidate of candidates) {
|
|
551
|
+
if (!candidate || seen.has(candidate) || !isValidGateHost(candidate)) continue;
|
|
552
|
+
seen.add(candidate);
|
|
553
|
+
hosts.push(candidate);
|
|
554
|
+
}
|
|
555
|
+
return hosts;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Reservation diagnostics stamp — ISO 시각 printed next to the claim owner (runId). Claims written before
|
|
559
|
+
* `reservedAt` existed fall back to the gate's own observation time. */
|
|
560
|
+
export function formatReservationStamp(ms: number): string {
|
|
561
|
+
return new Date(ms).toISOString();
|
|
562
|
+
}
|
|
563
|
+
|
|
470
564
|
async function loadSettings(): Promise<GateRemoteSettings> {
|
|
471
565
|
try {
|
|
472
566
|
const { getUserConfig } = await import('../user-config.js');
|
|
@@ -496,26 +590,59 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
496
590
|
return opts.runLocal();
|
|
497
591
|
}
|
|
498
592
|
let host = decision.host!;
|
|
593
|
+
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
594
|
+
const now = deps.now ?? Date.now;
|
|
499
595
|
const reservationRoot = opts.tool === 'self-gate' || opts.tool === 'ci-typecheck-changed'
|
|
500
596
|
? opts.reservationRoot ?? (deps.runner ? undefined : gateHostReservationRoot()) : undefined;
|
|
501
597
|
if (reservationRoot) {
|
|
502
598
|
const reservationHost = host.split('@').at(-1)!;
|
|
503
599
|
const first = inspectReleaseGateHost(reservationRoot, reservationHost);
|
|
504
600
|
if (first.status !== 'free') {
|
|
505
|
-
//
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
601
|
+
// A reserved host is never a reason to run this check locally (반증: 예약 상태에서 --local 무거운 시험 금지).
|
|
602
|
+
// Self gate first tries another remote host, then waits bounded for the release, then ends unmeasured with
|
|
603
|
+
// the owner and the observation stamp.
|
|
604
|
+
const observedAt = formatReservationStamp(now());
|
|
605
|
+
const owner = first.runId || 'unknown';
|
|
606
|
+
// Owner (runId) plus 시각: the claim's own reservedAt when recorded, else the moment this gate observed it.
|
|
607
|
+
const stamp = first.reservedAt !== undefined
|
|
608
|
+
? `reserved-at=${formatReservationStamp(first.reservedAt)}`
|
|
609
|
+
: `observed-at=${observedAt}`;
|
|
610
|
+
const alternates = opts.tool === 'self-gate'
|
|
611
|
+
? gateReservationAlternateHosts(reservationHost, opts.reservationAltHosts) : [];
|
|
612
|
+
const alternate = alternates.find((candidate) => inspectReleaseGateHost(reservationRoot, candidate).status === 'free');
|
|
613
|
+
if (alternate) {
|
|
614
|
+
const rerouted = host.includes('@') ? `${host.slice(0, host.lastIndexOf('@'))}@${alternate}` : alternate;
|
|
615
|
+
debug.log('gate.remote', 'host-reserved-reroute', { tool: opts.tool, from: host, to: rerouted, owner, reason: first.reason, reservedAt: first.reservedAt, observedAt });
|
|
616
|
+
write.err(`[gate.remote] host-reserved: ${host} (${first.reason}) owner=${owner} ${stamp} — rerouting to ${rerouted}\n`);
|
|
617
|
+
host = rerouted;
|
|
512
618
|
} else {
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
619
|
+
const waitSeconds = opts.tool === 'self-gate' ? opts.reservationWaitSeconds ?? settings.slotWaitSeconds : 0;
|
|
620
|
+
const waitStart = now();
|
|
621
|
+
const deadline = waitStart + Math.max(0, waitSeconds) * 1000;
|
|
622
|
+
let latest = inspectReleaseGateHost(reservationRoot, reservationHost);
|
|
623
|
+
while (waitSeconds > 0 && latest.status !== 'free') {
|
|
624
|
+
const left = deadline - now();
|
|
625
|
+
if (left <= 0) break;
|
|
626
|
+
write.err(`[gate.remote] waiting for host-reserved release on ${host} — owner=${owner} ${stamp} elapsed=${Math.floor(Math.max(0, now() - waitStart) / 1000)}s/${waitSeconds}s\n`);
|
|
627
|
+
const before = now();
|
|
628
|
+
await sleep(Math.min(15_000, left));
|
|
629
|
+
if (now() <= before) break; // a frozen test clock must not spin past the bound
|
|
630
|
+
latest = inspectReleaseGateHost(reservationRoot, reservationHost);
|
|
631
|
+
}
|
|
632
|
+
const waitedMs = Math.max(0, now() - waitStart);
|
|
633
|
+
if (latest.status === 'free') {
|
|
634
|
+
debug.log('gate.remote', 'host-reserved-released', { tool: opts.tool, host, owner, waitedMs });
|
|
635
|
+
write.err(`[gate.remote] host-reserved released on ${host} after ${Math.floor(waitedMs / 1000)}s — proceeding remotely\n`);
|
|
636
|
+
} else {
|
|
637
|
+
const reason = `host-reserved: ${host} (${latest.reason})`;
|
|
638
|
+
const manualAlternative = reservationHost === 'node-b'
|
|
639
|
+
? '; if available, non-PWA checks may explicitly select --remote host-e-wsl' : '';
|
|
640
|
+
debug.log('gate.remote', 'host-reserved-unmeasured', { host, reason, owner, reservedAt: latest.reservedAt ?? first.reservedAt, observedAt, waitedMs, alternates: alternates.length });
|
|
641
|
+
write.err(opts.tool === 'self-gate'
|
|
642
|
+
? `[gate.remote] remote unmeasured on ${host} (stage=host-reserved, rc=unknown) — ${reason}; owner=${owner} ${stamp} waited=${Math.floor(waitedMs / 1000)}s${manualAlternative}\n`
|
|
643
|
+
: `[gate.remote] remote unmeasured — ${reason}\n`);
|
|
644
|
+
return 1;
|
|
645
|
+
}
|
|
519
646
|
}
|
|
520
647
|
}
|
|
521
648
|
}
|
|
@@ -533,8 +660,6 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
533
660
|
};
|
|
534
661
|
if (opts.localOnlyReason) return fallback(opts.localOnlyReason, { stage: 'reproducibility', rc: null });
|
|
535
662
|
const hostCap = gateRemoteHostCap(settings, host);
|
|
536
|
-
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
537
|
-
const now = deps.now ?? Date.now;
|
|
538
663
|
const deadline = now() + settings.slotWaitSeconds * 1000;
|
|
539
664
|
let waitStartedAt: number | undefined;
|
|
540
665
|
const logWait = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('gate.remote', event, data));
|