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
|
@@ -118,6 +118,8 @@ export interface EnhanceOpts {
|
|
|
118
118
|
* ⭐ 새 LLM 경로를 만들지 않는다 — 이 모듈이 이미 그 자리의 유일한 LLM 단계다.
|
|
119
119
|
*/
|
|
120
120
|
groundedFacts?: readonly string[];
|
|
121
|
+
/** Relevant prior-failure lessons for goal-authoring prompts only; never part of the original ask. */
|
|
122
|
+
authoringLessons?: string;
|
|
121
123
|
/** Clock seam for the first-token observation (ms epoch); defaults to `Date.now`. */
|
|
122
124
|
now?: () => number;
|
|
123
125
|
}
|
|
@@ -434,6 +436,9 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
434
436
|
'위 사실을 «옮겨 적지 말고», 그것이 보여 주는 상태(situation)와 문제(complication)를 써라.',
|
|
435
437
|
]
|
|
436
438
|
: []),
|
|
439
|
+
...(opts.authoringLessons?.trim()
|
|
440
|
+
? ['', '## 지난 실패에서 배운 것', opts.authoringLessons.trim(), '위 교훈은 현재 ask의 대상 경로와 범위에 맞을 때만 적용하고, 맞지 않으면 무시하라.']
|
|
441
|
+
: []),
|
|
437
442
|
].join('\n'),
|
|
438
443
|
},
|
|
439
444
|
];
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""Capture PTY state and retain the live descriptor for replay comparison."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import fcntl
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import re
|
|
9
|
+
import select
|
|
10
|
+
import struct
|
|
11
|
+
import tempfile
|
|
12
|
+
import termios
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
DEFAULT_SNAPSHOT_ID = "pty_dee629e3"
|
|
16
|
+
_SCHEMA = 1
|
|
17
|
+
_LIVE_FDS: dict[str, int] = {}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(eq=True)
|
|
21
|
+
class Snapshot:
|
|
22
|
+
snapshot_id: str
|
|
23
|
+
rows: int
|
|
24
|
+
cols: int
|
|
25
|
+
termios_attributes: list
|
|
26
|
+
output: str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(eq=True)
|
|
30
|
+
class ReplayState:
|
|
31
|
+
snapshot: Snapshot
|
|
32
|
+
live_rows: int
|
|
33
|
+
live_cols: int
|
|
34
|
+
live_termios_attributes: list
|
|
35
|
+
matches_live: bool
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _location(snapshot_id: str) -> Path:
|
|
39
|
+
if not isinstance(snapshot_id, str) or not re.fullmatch(r"[A-Za-z0-9_-]+", snapshot_id):
|
|
40
|
+
raise ValueError("invalid snapshot id")
|
|
41
|
+
directory = Path(os.environ.get("ELANOUS_PTY_SNAPSHOT_DIR", tempfile.gettempdir() + "/elanous-pty-snapshots"))
|
|
42
|
+
return directory / (snapshot_id + ".json")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _size(fd: int) -> tuple[int, int]:
|
|
46
|
+
rows, cols, _, _ = struct.unpack("HHHH", fcntl.ioctl(fd, termios.TIOCGWINSZ, b"\0" * 8))
|
|
47
|
+
return rows, cols
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _serialize_attrs(attrs: list) -> list:
|
|
51
|
+
return attrs[:6] + [[
|
|
52
|
+
{"bytes": entry.hex()} if isinstance(entry, bytes) else entry
|
|
53
|
+
for entry in attrs[6]
|
|
54
|
+
]]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _deserialize_attrs(value: object) -> list:
|
|
58
|
+
if not isinstance(value, list) or len(value) != 7 or any(
|
|
59
|
+
type(item) is not int for item in value[:6]
|
|
60
|
+
) or not isinstance(value[6], list):
|
|
61
|
+
raise ValueError("invalid termios attributes")
|
|
62
|
+
controls = []
|
|
63
|
+
for item in value[6]:
|
|
64
|
+
if type(item) is int and 0 <= item <= 255:
|
|
65
|
+
controls.append(item)
|
|
66
|
+
elif isinstance(item, dict) and set(item) == {"bytes"} and isinstance(item["bytes"], str):
|
|
67
|
+
try:
|
|
68
|
+
controls.append(bytes.fromhex(item["bytes"]))
|
|
69
|
+
except ValueError as error:
|
|
70
|
+
raise ValueError("invalid termios control byte") from error
|
|
71
|
+
else:
|
|
72
|
+
raise ValueError("invalid termios control byte")
|
|
73
|
+
return value[:6] + [controls]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def snapshot(pty_fd: int, snapshot_id: str = DEFAULT_SNAPSHOT_ID) -> Snapshot:
|
|
77
|
+
"""Drain currently available output from a PTY master and save its state."""
|
|
78
|
+
path = _location(snapshot_id)
|
|
79
|
+
rows, cols = _size(pty_fd)
|
|
80
|
+
attrs = termios.tcgetattr(pty_fd)
|
|
81
|
+
output = bytearray()
|
|
82
|
+
while select.select([pty_fd], [], [], 0)[0]:
|
|
83
|
+
chunk = os.read(pty_fd, 65536)
|
|
84
|
+
if not chunk:
|
|
85
|
+
break
|
|
86
|
+
output.extend(chunk)
|
|
87
|
+
captured = Snapshot(snapshot_id, rows, cols, attrs, output.decode("utf-8"))
|
|
88
|
+
payload = {
|
|
89
|
+
"schema": _SCHEMA,
|
|
90
|
+
"snapshot_id": snapshot_id,
|
|
91
|
+
"rows": rows,
|
|
92
|
+
"cols": cols,
|
|
93
|
+
"termios_attributes": _serialize_attrs(attrs),
|
|
94
|
+
"output": captured.output,
|
|
95
|
+
}
|
|
96
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", dir=path.parent, delete=False) as file:
|
|
98
|
+
temporary = Path(file.name)
|
|
99
|
+
try:
|
|
100
|
+
json.dump(payload, file, ensure_ascii=False)
|
|
101
|
+
except BaseException:
|
|
102
|
+
temporary.unlink(missing_ok=True)
|
|
103
|
+
raise
|
|
104
|
+
temporary.replace(path)
|
|
105
|
+
_LIVE_FDS[snapshot_id] = pty_fd
|
|
106
|
+
return captured
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def restore(snapshot_id: str = DEFAULT_SNAPSHOT_ID) -> ReplayState:
|
|
110
|
+
"""Load a validated snapshot and compare it with its live PTY."""
|
|
111
|
+
path = _location(snapshot_id)
|
|
112
|
+
try:
|
|
113
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
114
|
+
except (json.JSONDecodeError, UnicodeError) as error:
|
|
115
|
+
raise ValueError("invalid snapshot document") from error
|
|
116
|
+
if not isinstance(payload, dict) or set(payload) != {
|
|
117
|
+
"schema", "snapshot_id", "rows", "cols", "termios_attributes", "output"
|
|
118
|
+
} or type(payload["schema"]) is not int or payload["schema"] != _SCHEMA or payload["snapshot_id"] != snapshot_id or any(
|
|
119
|
+
type(payload[field]) is not int or not 0 <= payload[field] <= 65535 for field in ("rows", "cols")
|
|
120
|
+
) or not isinstance(payload["output"], str):
|
|
121
|
+
raise ValueError("snapshot schema or id mismatch")
|
|
122
|
+
attrs = _deserialize_attrs(payload["termios_attributes"])
|
|
123
|
+
saved = Snapshot(snapshot_id, payload["rows"], payload["cols"], attrs, payload["output"])
|
|
124
|
+
if snapshot_id not in _LIVE_FDS:
|
|
125
|
+
raise RuntimeError("no live PTY registered for snapshot")
|
|
126
|
+
fd = _LIVE_FDS[snapshot_id]
|
|
127
|
+
live_rows, live_cols = _size(fd)
|
|
128
|
+
live_attrs = termios.tcgetattr(fd)
|
|
129
|
+
return ReplayState(
|
|
130
|
+
saved, live_rows, live_cols, live_attrs,
|
|
131
|
+
(live_rows, live_cols, live_attrs) == (saved.rows, saved.cols, saved.termios_attributes),
|
|
132
|
+
)
|
|
@@ -15,7 +15,7 @@ import { encodeSgrMouse, mouseModeOffReason, type PtyMouseInput } from './pty-mo
|
|
|
15
15
|
import { startPtyRecording, stopPtyRecording } from './pty-recording.js';
|
|
16
16
|
import { withExternalKeyCommand } from '../input/external-input-queue.js';
|
|
17
17
|
|
|
18
|
-
const OWNER_PTY_CONTROL_ACTIONS = ['takeover', 'release', 'input-text', 'input-key', 'input-mouse', 'resize', 'snapshot', 'rename', 'terminate', 'capabilities', 'record-start', 'record-stop'] as const;
|
|
18
|
+
const OWNER_PTY_CONTROL_ACTIONS = ['takeover', 'release', 'input-text', 'input-key', 'input-mouse', 'resize', 'snapshot', 'rename', 'terminate', 'stop-turn', 'capabilities', 'record-start', 'record-stop'] as const;
|
|
19
19
|
export type PtyControlAction = typeof OWNER_PTY_CONTROL_ACTIONS[number];
|
|
20
20
|
type PtyControlStatus = 'success' | 'unknown-pty' | 'denied' | 'failed' | 'write-failed' | 'owner-unreachable';
|
|
21
21
|
|
|
@@ -42,7 +42,8 @@ export type PtyControlPayload =
|
|
|
42
42
|
| { readonly cols: number; readonly rows: number }
|
|
43
43
|
| { readonly ansi: boolean }
|
|
44
44
|
| { readonly nickname: string }
|
|
45
|
-
| { readonly cols: number; readonly rows: number; readonly title?: string }
|
|
45
|
+
| { readonly cols: number; readonly rows: number; readonly title?: string }
|
|
46
|
+
| { readonly force: true; readonly actorIdentity: string; readonly reason: string };
|
|
46
47
|
|
|
47
48
|
export interface PtyControlRequestOptions {
|
|
48
49
|
/** 요청자가 주장하는 쓰기 주체. `'agent'` 는 run-identity 일치를 요구한다(`resolveRemoteControlActor`). */
|
|
@@ -609,6 +610,19 @@ async function processPtyControlRequestsOnce(getHandle: (id: string) => PtyContr
|
|
|
609
610
|
else if (!isOwnerPtyControlAction(row.action)) result = { status: 'denied', reason: 'unsupported-action' };
|
|
610
611
|
else if (row.action === 'capabilities') result = { status: 'success', actions: OWNER_PTY_CONTROL_ACTIONS };
|
|
611
612
|
else if (row.action === 'terminate') result = await terminatePty(handle);
|
|
613
|
+
else if (row.action === 'stop-turn') {
|
|
614
|
+
const payload = parsePayload(row);
|
|
615
|
+
const targetRunId = getPtyManifest(row.pty_id)?.runId?.trim() ?? '';
|
|
616
|
+
const requesterRunId = row.requester_run_id?.trim() ?? '';
|
|
617
|
+
if (requested === null) result = { status: 'denied', reason: 'invalid-actor' };
|
|
618
|
+
else if (payload === null || typeof payload !== 'object' || Array.isArray(payload) || !('force' in payload) || payload.force !== true) result = { status: 'denied', reason: 'force-required' };
|
|
619
|
+
else if (!('actorIdentity' in payload) || typeof payload.actorIdentity !== 'string' || !payload.actorIdentity.trim()) result = { status: 'denied', reason: 'actor-identity-required' };
|
|
620
|
+
else if (!('reason' in payload) || typeof payload.reason !== 'string' || !payload.reason.trim()) result = { status: 'denied', reason: 'reason-required' };
|
|
621
|
+
else if (!requesterRunId || !targetRunId) result = { status: 'denied', reason: 'run-identity-unavailable' };
|
|
622
|
+
else if (requesterRunId === targetRunId) result = { status: 'denied', reason: 'self-turn-refused' };
|
|
623
|
+
else if (!handle.stopTurn) result = { status: 'denied', reason: 'force-stop-unsupported' };
|
|
624
|
+
else result = handle.stopTurn(true) ? { status: 'success' } : { status: 'denied', reason: 'no-active-turn' };
|
|
625
|
+
}
|
|
612
626
|
else if (row.action === 'record-start' || row.action === 'record-stop') {
|
|
613
627
|
if (requested === null) result = { status: 'denied', reason: 'invalid-actor' };
|
|
614
628
|
else if (row.action === 'record-stop') {
|
|
@@ -733,6 +747,19 @@ async function processPtyControlRequestsOnce(getHandle: (id: string) => PtyContr
|
|
|
733
747
|
result = { status: 'failed', reason: 'control-processing-error' };
|
|
734
748
|
debug.log('pty.takeover', 'control-processing-error', { id: row.pty_id, action: row.action, actor: requested ?? row.actor, error: (error as Error).message });
|
|
735
749
|
}
|
|
750
|
+
if (row.action === 'stop-turn') {
|
|
751
|
+
const payload = parsePayload(row);
|
|
752
|
+
debug.log('pty.turn', 'force-stop-settled', {
|
|
753
|
+
ptyId: row.pty_id,
|
|
754
|
+
actor: requested ?? row.actor ?? 'unknown',
|
|
755
|
+
actorIdentity: payload && 'actorIdentity' in payload && typeof payload.actorIdentity === 'string' ? payload.actorIdentity.trim() || null : null,
|
|
756
|
+
reason: payload && 'reason' in payload && typeof payload.reason === 'string' ? payload.reason.trim() || null : null,
|
|
757
|
+
requesterRunId: row.requester_run_id?.trim() || null,
|
|
758
|
+
targetRunId: getPtyManifest(row.pty_id)?.runId?.trim() || null,
|
|
759
|
+
outcome: result.status,
|
|
760
|
+
refusal: result.reason ?? null,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
736
763
|
d.run("UPDATE pty_control_requests SET status=?, result_json=?, updated_at=? WHERE request_id=? AND status='processing'", [result.status, JSON.stringify(result), Date.now(), row.request_id]);
|
|
737
764
|
debug.log('pty.arbiter', 'control-settled', { id: row.pty_id, action: row.action, actor: requested ?? row.actor, outcome: result.status, reason: result.reason });
|
|
738
765
|
}
|
|
@@ -75,7 +75,10 @@ export interface PtyManifestRow {
|
|
|
75
75
|
exitCode: number | null;
|
|
76
76
|
snapshot: string;
|
|
77
77
|
snapshotAt: number;
|
|
78
|
-
|
|
78
|
+
/** Cumulative output bytes recorded for this PTY. `undefined` = the row never recorded a total
|
|
79
|
+
* (legacy schema before `output_bytes_total`, or NULL) — that is *unknown*, not 0. A genuinely
|
|
80
|
+
* recorded zero from a fresh spawn stays 0. */
|
|
81
|
+
outputBytesTotal?: number;
|
|
79
82
|
lastControlAt?: number;
|
|
80
83
|
updatedAt: number;
|
|
81
84
|
frame: string;
|
|
@@ -101,6 +104,10 @@ export interface PtyManifestRow {
|
|
|
101
104
|
/** TUI 턴 상태 — TUI 가 턴 시작·끝에 스스로 적는다(화면 글자 추정 아님). 없으면 기록 안 하는 행/옛 판. */
|
|
102
105
|
turnState?: PtyTurnState;
|
|
103
106
|
turnAt?: number;
|
|
107
|
+
/** 마지막 진전 시각(epoch ms) — 스트림 텍스트·도구 시작/끝·상태 줄에서 갱신(SURVIVAL-PROGRESS-CLOCK). */
|
|
108
|
+
progressAt?: number;
|
|
109
|
+
/** Esc 로 턴 중단을 청한 시각(epoch ms) — 이후 busy 가 지속되면 abort-ignored 판정 재료. */
|
|
110
|
+
abortRequestedAt?: number;
|
|
104
111
|
/** 행 소유 프로세스가 «기동 때» 실은 코드 판 — 트리 HEAD(`codeSha`)와 다른 축이다. */
|
|
105
112
|
build?: PtyBuildIdentity;
|
|
106
113
|
}
|
|
@@ -125,6 +132,7 @@ let _dbFailed = false;
|
|
|
125
132
|
let _dbPathForTesting: string | null = null;
|
|
126
133
|
const _lastSnapshotAt = new Map<string, number>();
|
|
127
134
|
const _lastFrameAt = new Map<string, number>();
|
|
135
|
+
const _lastProgressAt = new Map<string, number>();
|
|
128
136
|
|
|
129
137
|
export function setPtyManifestDbPathForTesting(path: string | null): void {
|
|
130
138
|
_db?.close();
|
|
@@ -133,6 +141,7 @@ export function setPtyManifestDbPathForTesting(path: string | null): void {
|
|
|
133
141
|
_dbPathForTesting = path;
|
|
134
142
|
_lastSnapshotAt.clear();
|
|
135
143
|
_lastFrameAt.clear();
|
|
144
|
+
_lastProgressAt.clear();
|
|
136
145
|
}
|
|
137
146
|
|
|
138
147
|
function db(): Database | null {
|
|
@@ -169,6 +178,11 @@ function db(): Database | null {
|
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
export function migratePtyManifestSchema(d: Database): void {
|
|
181
|
+
// 이행 문장 전체를 한 트랜잭션에 묶는다 — 문장별 autocommit fsync(첫 열기 ~35회)를 없애
|
|
182
|
+
// 매니페스트 DB 를 처음 여는 비용을 크게 줄인다. 이미 트랜잭션 안이면 그대로 진행한다.
|
|
183
|
+
let ownsTxn = false;
|
|
184
|
+
try { d.run('BEGIN'); ownsTxn = true; } catch { /* caller transaction */ }
|
|
185
|
+
try {
|
|
172
186
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN nickname TEXT'); } catch { /* already exists */ }
|
|
173
187
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN purpose TEXT'); } catch { /* already exists */ }
|
|
174
188
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN seat TEXT'); } catch { /* already exists */ }
|
|
@@ -198,12 +212,19 @@ export function migratePtyManifestSchema(d: Database): void {
|
|
|
198
212
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN last_control_at INTEGER'); } catch { /* already exists */ }
|
|
199
213
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN turn_state TEXT'); } catch { /* already exists */ }
|
|
200
214
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN turn_at INTEGER'); } catch { /* already exists */ }
|
|
215
|
+
try { d.run('ALTER TABLE pty_manifest ADD COLUMN progress_at INTEGER'); } catch { /* already exists */ }
|
|
216
|
+
try { d.run('ALTER TABLE pty_manifest ADD COLUMN abort_requested_at INTEGER'); } catch { /* already exists */ }
|
|
201
217
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_version TEXT'); } catch { /* already exists */ }
|
|
202
218
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_sha TEXT'); } catch { /* already exists */ }
|
|
203
219
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_source TEXT'); } catch { /* already exists */ }
|
|
204
220
|
try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_code_root TEXT'); } catch { /* already exists */ }
|
|
205
221
|
try { d.run('ALTER TABLE pty_manifest DROP COLUMN chain_depth'); } catch { /* legacy schema has no duplicate column */ }
|
|
206
222
|
try { d.run('UPDATE pty_manifest SET closed_at=updated_at WHERE alive=0 AND closed_at=0'); } catch { /* fail-soft */ }
|
|
223
|
+
} finally {
|
|
224
|
+
if (ownsTxn) {
|
|
225
|
+
try { d.run('COMMIT'); } catch { try { d.run('ROLLBACK'); } catch { /* fail-soft */ } }
|
|
226
|
+
}
|
|
227
|
+
}
|
|
207
228
|
}
|
|
208
229
|
|
|
209
230
|
function codeShaForWorkdir(workdir: string | undefined): string {
|
|
@@ -287,6 +308,7 @@ export function upsertPtyManifest(row: {
|
|
|
287
308
|
// 행을 (다시) 세우면 snapshot·frame 칸이 비워진다 — 같은 프로세스의 쓰기 스로틀도 비워 다음 쓰기가 바로 닿게 한다.
|
|
288
309
|
_lastSnapshotAt.delete(row.id);
|
|
289
310
|
_lastFrameAt.delete(row.id);
|
|
311
|
+
_lastProgressAt.delete(row.id);
|
|
290
312
|
const d = db(); if (!d) return;
|
|
291
313
|
const runId = getHarnessRunId(process.env);
|
|
292
314
|
const runIdSource = getHarnessRunIdSource();
|
|
@@ -340,7 +362,7 @@ export function upsertPtyManifest(row: {
|
|
|
340
362
|
terminal_origin_reason=excluded.terminal_origin_reason, external_tool_name=excluded.external_tool_name,
|
|
341
363
|
started_at=excluded.started_at, alive=1, exit_code=NULL,
|
|
342
364
|
snapshot='', snapshot_at=0, frame='', frame_at=0, closed_at=0, updated_at=excluded.updated_at,
|
|
343
|
-
turn_state=NULL, turn_at=NULL, build_version=NULL, build_sha=NULL, build_source=NULL, build_code_root=NULL`,
|
|
365
|
+
turn_state=NULL, turn_at=NULL, progress_at=NULL, abort_requested_at=NULL, build_version=NULL, build_sha=NULL, build_source=NULL, build_code_root=NULL`,
|
|
344
366
|
values,
|
|
345
367
|
);
|
|
346
368
|
d.run('COMMIT');
|
|
@@ -420,11 +442,57 @@ export function updatePtyManifestNickname(id: string, nickname: string | undefin
|
|
|
420
442
|
} catch { /* fail-soft */ }
|
|
421
443
|
}
|
|
422
444
|
|
|
423
|
-
/**
|
|
445
|
+
/** Update the conversation currently shown by a TUI surface without replacing its manifest row. */
|
|
446
|
+
export function updatePtyManifestSession(id: string, sessionId: string, now: number = Date.now()): boolean {
|
|
447
|
+
try {
|
|
448
|
+
const d = db(); if (!d) return false;
|
|
449
|
+
const result = d.run('UPDATE pty_manifest SET session_id=?, updated_at=? WHERE id=? AND kind=\'tui\' AND session_id<>?', [sessionId, now, id, sessionId]);
|
|
450
|
+
return (result.changes ?? 0) > 0;
|
|
451
|
+
} catch {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** 턴 상태 기록 — 행이 없거나 db 를 못 열면 false(호출자가 관측을 남긴다). 새 busy 턴은 이전 Esc 청구를 비운다. */
|
|
424
457
|
export function updatePtyManifestTurn(id: string, turn: PtyTurnState, at: number): boolean {
|
|
425
458
|
try {
|
|
426
459
|
const d = db(); if (!d) return false;
|
|
427
|
-
|
|
460
|
+
const result = turn === 'busy'
|
|
461
|
+
? d.run('UPDATE pty_manifest SET turn_state=?, turn_at=?, progress_at=?, abort_requested_at=NULL WHERE id=?', [turn, at, at, id])
|
|
462
|
+
: d.run('UPDATE pty_manifest SET turn_state=?, turn_at=? WHERE id=?', [turn, at, id]);
|
|
463
|
+
if ((result.changes ?? 0) > 0 && turn === 'busy') _lastProgressAt.set(id, at);
|
|
464
|
+
return (result.changes ?? 0) > 0;
|
|
465
|
+
} catch {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** 진전 기록 스로틀 — 같은 행은 이만큼 안에 다시 쓰지 않는다. */
|
|
471
|
+
export const PTY_MANIFEST_PROGRESS_THROTTLE_MS = 5_000;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* 마지막 진전 시각 기록(SURVIVAL-PROGRESS-CLOCK). 같은 행을 5초 안에 다시 쓰면 생략하지만
|
|
475
|
+
* «실패가 아니다» — true 를 돌려 호출자의 실패 관측을 일으키지 않는다. 실패(0행·db 오류)만 false.
|
|
476
|
+
*/
|
|
477
|
+
export function updatePtyManifestProgress(id: string, at: number): boolean {
|
|
478
|
+
try {
|
|
479
|
+
const last = _lastProgressAt.get(id);
|
|
480
|
+
if (last !== undefined && at - last < PTY_MANIFEST_PROGRESS_THROTTLE_MS) return true;
|
|
481
|
+
const d = db(); if (!d) return false;
|
|
482
|
+
const result = d.run('UPDATE pty_manifest SET progress_at=?, updated_at=? WHERE id=?', [at, at, id]);
|
|
483
|
+
const ok = (result.changes ?? 0) > 0;
|
|
484
|
+
if (ok) _lastProgressAt.set(id, at);
|
|
485
|
+
return ok;
|
|
486
|
+
} catch {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** Esc 로 턴 중단을 청한 시각 기록 — busy 턴이 이 뒤로 계속되면 abort-ignored 판정 재료가 된다. */
|
|
492
|
+
export function updatePtyManifestAbortRequested(id: string, at: number): boolean {
|
|
493
|
+
try {
|
|
494
|
+
const d = db(); if (!d) return false;
|
|
495
|
+
return (d.run('UPDATE pty_manifest SET abort_requested_at=?, updated_at=? WHERE id=?', [at, at, id]).changes ?? 0) > 0;
|
|
428
496
|
} catch {
|
|
429
497
|
return false;
|
|
430
498
|
}
|
|
@@ -866,7 +934,7 @@ function mapRow(r: Record<string, unknown>): PtyManifestRow {
|
|
|
866
934
|
exitCode: r.exit_code === null || r.exit_code === undefined ? null : Number(r.exit_code),
|
|
867
935
|
snapshot: String(r.snapshot ?? ''),
|
|
868
936
|
snapshotAt: Number(r.snapshot_at ?? 0),
|
|
869
|
-
outputBytesTotal: Number(r.output_bytes_total
|
|
937
|
+
...(r.output_bytes_total === null || r.output_bytes_total === undefined ? {} : { outputBytesTotal: Number(r.output_bytes_total) }),
|
|
870
938
|
...(r.last_control_at === null || r.last_control_at === undefined ? {} : { lastControlAt: Number(r.last_control_at) }),
|
|
871
939
|
frame: String(r.frame ?? ''),
|
|
872
940
|
frameAt: Number(r.frame_at ?? 0),
|
|
@@ -889,6 +957,8 @@ function mapRow(r: Record<string, unknown>): PtyManifestRow {
|
|
|
889
957
|
closedAt: Number(r.closed_at ?? 0),
|
|
890
958
|
codeSha: String(r.code_sha ?? ''),
|
|
891
959
|
...(r.turn_state === 'busy' || r.turn_state === 'idle' ? { turnState: r.turn_state, turnAt: Number(r.turn_at ?? 0) } : {}),
|
|
960
|
+
...(r.progress_at === null || r.progress_at === undefined ? {} : { progressAt: Number(r.progress_at) }),
|
|
961
|
+
...(r.abort_requested_at === null || r.abort_requested_at === undefined ? {} : { abortRequestedAt: Number(r.abort_requested_at) }),
|
|
892
962
|
...(typeof r.build_sha === 'string' ? { build: mapBuild(r) } : {}),
|
|
893
963
|
updatedAt: Number(r.updated_at),
|
|
894
964
|
};
|
|
@@ -180,6 +180,8 @@ export interface PtyControlTarget {
|
|
|
180
180
|
isAlive(): boolean;
|
|
181
181
|
/** Registry-backed PTY targets expose termination; non-PTY control targets omit it. */
|
|
182
182
|
kill?(signal?: NodeJS.Signals): void;
|
|
183
|
+
/** TUI owners may expose an explicit, forceful cancellation of the active turn. */
|
|
184
|
+
stopTurn?(force: true): boolean;
|
|
183
185
|
canWrite(actor?: PtyWriteActor): boolean;
|
|
184
186
|
write(chars: string, actor?: PtyWriteActor): void;
|
|
185
187
|
resize(cols: number, rows: number): void;
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
versionedDashboardInstallDir,
|
|
28
28
|
} from './stale-install-check.js';
|
|
29
29
|
import {
|
|
30
|
-
updatePtyManifestBuild, updatePtyManifestTurn,
|
|
30
|
+
updatePtyManifestAbortRequested, updatePtyManifestBuild, updatePtyManifestProgress, updatePtyManifestTurn,
|
|
31
31
|
type PtyBuildIdentity, type PtyManifestRow, type PtyTurnState,
|
|
32
32
|
} from './pty-manifest.js';
|
|
33
33
|
|
|
@@ -231,6 +231,10 @@ export type PtyTurnView = PtyTurnState | 'unknown';
|
|
|
231
231
|
export interface PtyRunStateView {
|
|
232
232
|
readonly turn: PtyTurnView;
|
|
233
233
|
readonly turnAt?: number;
|
|
234
|
+
/** 마지막 진전 시각(SURVIVAL-PROGRESS-CLOCK) — 기록 없는 행·옛 판은 undefined. */
|
|
235
|
+
readonly progressAt?: number;
|
|
236
|
+
/** Esc 로 턴 중단을 청한 시각 — 이 뒤로 busy 가 지속되면 abort-ignored 판정 재료. */
|
|
237
|
+
readonly abortRequestedAt?: number;
|
|
234
238
|
readonly build: PtyBuildIdentity | null;
|
|
235
239
|
readonly installed: string | null;
|
|
236
240
|
readonly stale: boolean | null;
|
|
@@ -244,7 +248,7 @@ export interface DescribeRunStateDeps {
|
|
|
244
248
|
|
|
245
249
|
/** manifest 행 하나의 턴 ⊕ 판 ⊕ stale. 행이 없거나 죽었으면 턴은 unknown. */
|
|
246
250
|
export function describePtyRunState(
|
|
247
|
-
row: Pick<PtyManifestRow, 'alive' | 'startedAt' | 'kind' | 'turnState' | 'turnAt' | 'build'> | null,
|
|
251
|
+
row: Pick<PtyManifestRow, 'alive' | 'startedAt' | 'kind' | 'turnState' | 'turnAt' | 'progressAt' | 'abortRequestedAt' | 'build'> | null,
|
|
248
252
|
deps: DescribeRunStateDeps = {},
|
|
249
253
|
): PtyRunStateView {
|
|
250
254
|
let installed: InstalledRecord = {};
|
|
@@ -265,6 +269,8 @@ export function describePtyRunState(
|
|
|
265
269
|
const turnView = ptyTurnViewOfRow(row);
|
|
266
270
|
return {
|
|
267
271
|
...turnView,
|
|
272
|
+
...(row?.alive && row.progressAt !== undefined ? { progressAt: row.progressAt } : {}),
|
|
273
|
+
...(row?.alive && row.abortRequestedAt !== undefined ? { abortRequestedAt: row.abortRequestedAt } : {}),
|
|
268
274
|
build: build ?? null,
|
|
269
275
|
installed: installed.sha ?? null,
|
|
270
276
|
stale: staleness.stale,
|
|
@@ -446,6 +452,50 @@ export const spawnTuiRelaunch = (sessionId: string): Promise<void> => {
|
|
|
446
452
|
});
|
|
447
453
|
};
|
|
448
454
|
|
|
455
|
+
// ── SURVIVAL-PROGRESS-CLOCK — «마지막 진전 시각»로 느림·정체·Esc 무시를 가른다 ──
|
|
456
|
+
//
|
|
457
|
+
// `turnAt` 은 턴 값이 «바뀔 때만» 적히므로 busy 경과만으로는 «일하는 중»인지 «죽었다»인지를 못 가른다.
|
|
458
|
+
// 진전 신호(스트림 텍스트·도구 시작/끝·상태 줄)가 `progress_at` 를 계속 올리면 긴 턴도 «느리지만 가는 중»이
|
|
459
|
+
// 되고, 진전이 끊기면 «정체», Esc 청구 뒤에도 busy 가 지속되면 «Esc 무시»로 판정한다.
|
|
460
|
+
|
|
461
|
+
export const DEFAULT_TURN_STALL_MS = 12 * 60 * 1000;
|
|
462
|
+
export const DEFAULT_SLOW_TURN_MS = 20 * 60 * 1000;
|
|
463
|
+
export const DEFAULT_ABORT_IGNORE_MS = 30 * 1000;
|
|
464
|
+
|
|
465
|
+
export type TurnProgressJudgment = 'progressing' | 'slow' | 'stalled' | 'abort-ignored' | 'unknown';
|
|
466
|
+
|
|
467
|
+
export interface TurnProgressInput {
|
|
468
|
+
readonly turn: PtyTurnView;
|
|
469
|
+
readonly turnAt?: number;
|
|
470
|
+
readonly progressAt?: number;
|
|
471
|
+
readonly abortRequestedAt?: number;
|
|
472
|
+
readonly now: number;
|
|
473
|
+
/** 정체 임계 — 진전이 이만큼 끊기면 stalled. 기본 12분. */
|
|
474
|
+
readonly stallMs?: number;
|
|
475
|
+
/** 느린 턴 임계 — 턴 경과가 이만큼이면 slow. 기본 20분. */
|
|
476
|
+
readonly slowTurnMs?: number;
|
|
477
|
+
/** Esc 무시 임계 — 청구 뒤 이만큼 busy 면 abort-ignored. 기본 30초. */
|
|
478
|
+
readonly abortIgnoreMs?: number;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** 순수 판정: busy 턴의 진전·정체·Esc 무시를 임계로 가른다. 재료가 없으면 unknown(«괜찮다»가 아니다). */
|
|
482
|
+
export function judgeTurnProgress(input: TurnProgressInput): TurnProgressJudgment {
|
|
483
|
+
const { turn, turnAt, progressAt, abortRequestedAt, now } = input;
|
|
484
|
+
if (turn !== 'busy') return 'unknown';
|
|
485
|
+
if (!Number.isFinite(now)) return 'unknown';
|
|
486
|
+
// Esc 청구 뒤에도 busy 가 지속되면 무시 — 정체보다 구체적이므로 먼저 가른다.
|
|
487
|
+
if (abortRequestedAt !== undefined && Number.isFinite(abortRequestedAt)) {
|
|
488
|
+
if (now - abortRequestedAt >= (input.abortIgnoreMs ?? DEFAULT_ABORT_IGNORE_MS)) return 'abort-ignored';
|
|
489
|
+
}
|
|
490
|
+
// 진전 시각이 없으면 턴 시작(turnAt)이 진전의 0초다.
|
|
491
|
+
const since = progressAt !== undefined && Number.isFinite(progressAt) ? progressAt : turnAt;
|
|
492
|
+
if (since === undefined || !Number.isFinite(since)) return 'unknown';
|
|
493
|
+
const elapsed = Math.max(0, now - since);
|
|
494
|
+
if (elapsed >= (input.stallMs ?? DEFAULT_TURN_STALL_MS)) return 'stalled';
|
|
495
|
+
if (turnAt !== undefined && Number.isFinite(turnAt) && now - turnAt >= (input.slowTurnMs ?? DEFAULT_SLOW_TURN_MS)) return 'slow';
|
|
496
|
+
return 'progressing';
|
|
497
|
+
}
|
|
498
|
+
|
|
449
499
|
// ── 기록(TUI) ──
|
|
450
500
|
|
|
451
501
|
export interface TuiRunStateRecorderDeps {
|
|
@@ -453,6 +503,10 @@ export interface TuiRunStateRecorderDeps {
|
|
|
453
503
|
readonly build?: () => PtyBuildIdentity;
|
|
454
504
|
readonly writeBuild?: (id: string, build: PtyBuildIdentity) => boolean;
|
|
455
505
|
readonly writeTurn?: (id: string, turn: PtyTurnState, at: number) => boolean;
|
|
506
|
+
/** 진전 시각 기록 — 생략하면 `updatePtyManifestProgress`(같은 행 5초 스로틀). */
|
|
507
|
+
readonly writeProgress?: (id: string, at: number) => boolean;
|
|
508
|
+
/** Esc 청구 시각 기록 — 생략하면 `updatePtyManifestAbortRequested`. */
|
|
509
|
+
readonly writeAbortRequested?: (id: string, at: number) => boolean;
|
|
456
510
|
readonly log?: (event: string, data: Record<string, unknown>) => void;
|
|
457
511
|
/**
|
|
458
512
|
* herdr pane 신고기. 생략 시: `writeTurn` 을 주입하지 않은 기본 녹음기만
|
|
@@ -476,6 +530,8 @@ interface ActiveRecorder {
|
|
|
476
530
|
readonly surfaceId: string;
|
|
477
531
|
readonly now: () => number;
|
|
478
532
|
readonly writeTurn: (id: string, turn: PtyTurnState, at: number) => boolean;
|
|
533
|
+
readonly writeProgress: (id: string, at: number) => boolean;
|
|
534
|
+
readonly writeAbortRequested: (id: string, at: number) => boolean;
|
|
479
535
|
readonly log: (event: string, data: Record<string, unknown>) => void;
|
|
480
536
|
readonly herdr: HerdrAgentReporterLike | null;
|
|
481
537
|
/** manifest 에 실제로 적힌 마지막 턴. 실패면 안 바뀐다(재시도). */
|
|
@@ -495,6 +551,8 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
495
551
|
const now = deps.now ?? Date.now;
|
|
496
552
|
const log = deps.log ?? defaultLog;
|
|
497
553
|
const writeTurn = deps.writeTurn ?? updatePtyManifestTurn;
|
|
554
|
+
const writeProgress = deps.writeProgress ?? updatePtyManifestProgress;
|
|
555
|
+
const writeAbortRequested = deps.writeAbortRequested ?? updatePtyManifestAbortRequested;
|
|
498
556
|
// 기본 신고기는 기본 manifest 쓰기와 짝일 때만. writeTurn 주입(시험)은 herdr 를 안 만든다.
|
|
499
557
|
const herdr = deps.herdr !== undefined
|
|
500
558
|
? deps.herdr
|
|
@@ -508,7 +566,7 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
508
566
|
log(ok ? 'build-recorded' : 'build-write-failed', { ptyId: surfaceId, sha: build.sha, version: build.version, source: build.source });
|
|
509
567
|
}
|
|
510
568
|
// 기동 순서: 판 → manifest 초기 idle → herdr 신고. herdr start 가 idle 을 신고하므로 초기 idle 을 turn 으로 다시 안 보낸다.
|
|
511
|
-
const recorder: ActiveRecorder = { surfaceId, now, writeTurn, log, herdr, herdrLast: herdr ? 'idle' : undefined };
|
|
569
|
+
const recorder: ActiveRecorder = { surfaceId, now, writeTurn, writeProgress, writeAbortRequested, log, herdr, herdrLast: herdr ? 'idle' : undefined };
|
|
512
570
|
active = recorder;
|
|
513
571
|
writeTurnState(recorder, 'idle');
|
|
514
572
|
if (herdr) { try { herdr.start(); } catch { /* 신고 실패가 녹음기를 깨지 않는다 */ } }
|
|
@@ -614,6 +672,25 @@ export function reportTuiTurn(turn: PtyTurnState): void {
|
|
|
614
672
|
writeTurnState(active, turn);
|
|
615
673
|
}
|
|
616
674
|
|
|
675
|
+
/** 진전 신호(스트림 텍스트·도구 시작/끝·상태 줄)에서 부른다 — 마지막 진전 시각을 올린다. 녹음기가 없으면 아무것도 안 한다. */
|
|
676
|
+
export function reportTuiProgress(): void {
|
|
677
|
+
if (!active) return;
|
|
678
|
+
const at = active.now();
|
|
679
|
+
let ok = false;
|
|
680
|
+
try { ok = active.writeProgress(active.surfaceId, at); } catch { ok = false; }
|
|
681
|
+
// 실패(0행·예외)는 관측으로만 남긴다 — 진전 기록이 턴을 막지 않는다. 스로틀 생략(false 아님 실패만)은 조용히 지나간다.
|
|
682
|
+
if (!ok) active.log('progress-write-failed', { ptyId: active.surfaceId, at });
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/** Esc 게이트가 턴 중단을 청할 때 부른다 — 청구 시각을 남긴다(busy 가 지속되면 abort-ignored 판정 재료). */
|
|
686
|
+
export function reportTuiAbortRequested(): void {
|
|
687
|
+
if (!active) return;
|
|
688
|
+
const at = active.now();
|
|
689
|
+
let ok = false;
|
|
690
|
+
try { ok = active.writeAbortRequested(active.surfaceId, at); } catch { ok = false; }
|
|
691
|
+
if (!ok) active.log('abort-requested-write-failed', { ptyId: active.surfaceId, at });
|
|
692
|
+
}
|
|
693
|
+
|
|
617
694
|
function writeTurnState(recorder: ActiveRecorder, turn: PtyTurnState): void {
|
|
618
695
|
const at = recorder.now();
|
|
619
696
|
let ok = false;
|
|
@@ -11,11 +11,13 @@ interface GateHostClaim {
|
|
|
11
11
|
hosts: string[];
|
|
12
12
|
pid: number;
|
|
13
13
|
pidStartedAt: number | null;
|
|
14
|
+
/** Wall-clock claim time. Claims written before this field existed stay readable (optional on read). */
|
|
15
|
+
reservedAt?: number;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export type GateHostReservation =
|
|
17
19
|
| { status: 'free' }
|
|
18
|
-
| { status: 'reserved' | 'unknown'; reason: string; runId?: string };
|
|
20
|
+
| { status: 'reserved' | 'unknown'; reason: string; runId?: string; reservedAt?: number };
|
|
19
21
|
|
|
20
22
|
const hostName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
21
23
|
const claimsDir = (root: string) => join(root, 'release', 'gate-host-reservations');
|
|
@@ -44,7 +46,7 @@ export function reserveReleaseGateHosts(root: string, runId: string, hosts: read
|
|
|
44
46
|
const token = randomUUID();
|
|
45
47
|
const pidStartedAt = psProcessStartMs(process.pid);
|
|
46
48
|
if (pidStartedAt === null) throw new Error('release gate owner start time unmeasured');
|
|
47
|
-
const claim: GateHostClaim = { token, runId, hosts: unique, pid: process.pid, pidStartedAt };
|
|
49
|
+
const claim: GateHostClaim = { token, runId, hosts: unique, pid: process.pid, pidStartedAt, reservedAt: Date.now() };
|
|
48
50
|
const path = join(dir, `${token}.json`);
|
|
49
51
|
const temp = join(dir, `.${token}.tmp`);
|
|
50
52
|
try {
|
|
@@ -82,7 +84,9 @@ export function inspectReleaseGateHost(root: string, host: string): GateHostRese
|
|
|
82
84
|
|| !Number.isSafeInteger(claim.pid) || claim.pid <= 0 || typeof claim.token !== 'string'
|
|
83
85
|
|| typeof claim.runId !== 'string' || !claim.runId
|
|
84
86
|
|| (claim.pidStartedAt !== null && (!Number.isSafeInteger(claim.pidStartedAt)
|
|
85
|
-
|| claim.pidStartedAt <= 0 || claim.pidStartedAt > Date.now()))
|
|
87
|
+
|| claim.pidStartedAt <= 0 || claim.pidStartedAt > Date.now()))
|
|
88
|
+
|| (claim.reservedAt !== undefined && (!Number.isSafeInteger(claim.reservedAt)
|
|
89
|
+
|| claim.reservedAt <= 0 || claim.reservedAt > Date.now()))) throw new Error('invalid claim');
|
|
86
90
|
} catch (error) { return { status: 'unknown', reason: `reservation unreadable: ${name}: ${String(error)}` }; }
|
|
87
91
|
const live = claimAlive(claim);
|
|
88
92
|
if (live === 'dead') {
|
|
@@ -91,7 +95,12 @@ export function inspectReleaseGateHost(root: string, host: string): GateHostRese
|
|
|
91
95
|
continue;
|
|
92
96
|
}
|
|
93
97
|
if (!claim.hosts.includes(host) && !claim.hosts.includes('*')) continue;
|
|
94
|
-
return {
|
|
98
|
+
return {
|
|
99
|
+
status: live === 'unknown' ? 'unknown' : 'reserved',
|
|
100
|
+
reason: `release gate ${claim.runId} holds ${host}`,
|
|
101
|
+
runId: claim.runId,
|
|
102
|
+
...(claim.reservedAt !== undefined ? { reservedAt: claim.reservedAt } : {}),
|
|
103
|
+
};
|
|
95
104
|
}
|
|
96
105
|
return { status: 'free' };
|
|
97
106
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// One append-only observation per gate shard transition. The live board is a projection, not evidence for reuse.
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
5
|
+
|
|
6
|
+
export interface GateShardLedgerRow {
|
|
7
|
+
v: 1;
|
|
8
|
+
version: string;
|
|
9
|
+
phase: 'cut' | 'baseline';
|
|
10
|
+
shardId: string;
|
|
11
|
+
files: string[];
|
|
12
|
+
host: string | null;
|
|
13
|
+
executor: 'pod' | 'host';
|
|
14
|
+
imageDigest: string | null;
|
|
15
|
+
commit: string;
|
|
16
|
+
envFingerprint: string;
|
|
17
|
+
startedAt: string | null;
|
|
18
|
+
endedAt: string | null;
|
|
19
|
+
observedAt: string;
|
|
20
|
+
state: 'pending' | 'running' | 'done' | 'retry' | 'timeout' | 'failed';
|
|
21
|
+
rc: number | null;
|
|
22
|
+
pass: number | null;
|
|
23
|
+
fail: number | null;
|
|
24
|
+
errors: number | null;
|
|
25
|
+
ran: number | null;
|
|
26
|
+
failureIds: string[] | null;
|
|
27
|
+
errorIds: string[] | null;
|
|
28
|
+
attribution: 'complete' | 'unmeasured';
|
|
29
|
+
logPath: string | null;
|
|
30
|
+
junitPath: string | null;
|
|
31
|
+
stopReason: string | null;
|
|
32
|
+
attemptId: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function gateShardLedgerPath(version: string, root = releaseLedgerRoot()): string {
|
|
36
|
+
if (!/^\d+\.\d+\.\d+(?:[-.][A-Za-z0-9.-]+)?$/.test(version)) throw new Error('invalid release version');
|
|
37
|
+
return join(root, 'release', version, 'gate-logs', 'shard-ledger.jsonl');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Each newline is a complete event, so an observer can read while the gate is running. */
|
|
41
|
+
export function appendGateShardLedger(path: string, row: GateShardLedgerRow): void {
|
|
42
|
+
if (!/^[a-f0-9]{40}$/i.test(row.commit) || !/^[a-f0-9]{64}$/i.test(row.envFingerprint)) throw new Error('invalid shard ledger identity');
|
|
43
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(row.shardId) || row.files.some((file) => file.startsWith('/') || file.split('/').includes('..'))) throw new Error('invalid shard ledger path');
|
|
44
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
45
|
+
appendFileSync(path, `${JSON.stringify(row)}\n`, { mode: 0o600 });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function readGateShardLedger(path: string): { rows: GateShardLedgerRow[]; malformed: number } | null {
|
|
49
|
+
if (!existsSync(path)) return null;
|
|
50
|
+
const rows: GateShardLedgerRow[] = [];
|
|
51
|
+
let malformed = 0;
|
|
52
|
+
for (const line of readFileSync(path, 'utf8').split('\n')) {
|
|
53
|
+
if (!line.trim()) continue;
|
|
54
|
+
try {
|
|
55
|
+
const row = JSON.parse(line) as GateShardLedgerRow;
|
|
56
|
+
if (row.v !== 1 || typeof row.shardId !== 'string' || !Array.isArray(row.files) || typeof row.observedAt !== 'string') throw new Error('invalid row');
|
|
57
|
+
rows.push(row);
|
|
58
|
+
} catch { malformed++; }
|
|
59
|
+
}
|
|
60
|
+
return { rows, malformed };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The newest event for each phase/shard. Preserve every attempt in the underlying ledger. */
|
|
64
|
+
export function latestGateShardLedger(rows: readonly GateShardLedgerRow[]): GateShardLedgerRow[] {
|
|
65
|
+
const latest = new Map<string, GateShardLedgerRow>();
|
|
66
|
+
for (const row of rows) latest.set(`${row.phase}:${row.shardId}`, row);
|
|
67
|
+
return [...latest.values()].sort((a, b) => a.phase.localeCompare(b.phase) || a.shardId.localeCompare(b.shardId, undefined, { numeric: true }));
|
|
68
|
+
}
|