elanous 0.2.37 → 0.2.38
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 → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4937-28d437999b77c9dd.js → 1923-5c1695332240246a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +1 -0
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{3199.6a1a9b0e6cd01dc6.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3124-561f7f037943cde2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/{6877-84d47b7e85d0c41e.js → 3341-f09b9efbd7a82f70.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 3528.e4b8ab70d339f965.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{4036.d54e55e1ebf5acdc.js → 4804.6012b5cd33c22792.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{757-4fbaf50942b8c424.js → 5255-1b60d50eabe9f057.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 5638.107314dc479e2f37.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6493.27ad77de7aac7966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1224.2ceca6c180d5130b.js → 7000.28157393caaf5343.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{2479-fe7e188bd9402d14.js → 7311-60a7ea80d23c7521.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5952.294fc574a8625184.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-5c112c6d7c33656e.js → page-c348a3959c5b5fc6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-88a1edbff62eaf1d.js → page-d1d1210f99f620ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{page-b9af2ac1c4737ce8.js → page-7f569e533ddeecba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-fb9e639c107f5f72.js → page-a9d9a3e66459c1e0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → bb6987f9.3647e1a23b0e3217.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/de8b930d.d94c0f42acf807fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/package.json +1 -1
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/brand/check.ts +13 -4
- 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/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -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/gate-node.ts +161 -25
- 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/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +297 -8
- package/scripts/release-loop/resume.ts +13 -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 +29 -4
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/core-turn-bridge.ts +6 -1
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +195 -27
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/bots/screen-probe.ts +1 -1
- package/src/capture/tui-self-report.ts +10 -2
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- 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 +58 -5
- package/src/cli/release-checklist-read-cli.ts +5 -2
- package/src/cli/release-cli.ts +47 -9
- 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 +62 -23
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/context-bus/context-now.ts +86 -2
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/types.ts +3 -0
- package/src/dashboard/index.ts +18 -17
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- package/src/domains/guardian-tick.ts +9 -0
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/runner.ts +17 -2
- package/src/grok/credential.ts +107 -36
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +44 -14
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm-tool-schema.ts +20 -0
- package/src/llm.ts +81 -11
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +6 -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/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-shell/pty-manifest.ts +16 -2
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +10 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +29 -16
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-run.ts +260 -3
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +25 -0
- package/src/self-implement/gate-artifacts.ts +2 -2
- package/src/self-implement/gate-baseline.ts +44 -9
- package/src/self-implement/gate-cli.ts +151 -86
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +2 -0
- package/src/self-implement/goal-author.ts +74 -3
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +38 -4
- package/src/self-implement/knowhow-pack.ts +120 -7
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +55 -12
- 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 +258 -0
- package/src/self-implement/seams.ts +33 -10
- package/src/self-implement/self-implement-cli.ts +26 -2
- 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 +3 -0
- package/src/session/index.ts +2 -0
- package/src/session-runtime/index.ts +9 -22
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- package/src/storage/file-lock.ts +17 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/parent-host.ts +59 -12
- package/src/task-agent/repair-cycle.ts +67 -8
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/task-hand.ts +98 -10
- package/src/task-agent/tier-split.ts +37 -3
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
- package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +126 -48
- 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/tui/chat/background-job-status.ts +8 -2
- package/src/tui/entry.ts +469 -31
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -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-client/local-chat-turn.ts +29 -8
- package/src/user-config.ts +11 -2
- package/src/ux-sim/fake-llm.ts +11 -5
- package/src/ux-sim/next-tui-seat-scenarios.ts +53 -1
- package/src/version/packed-revision.json +1 -1
- 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/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/2318-450e75d07605b8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.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/3212.12179fd3eee8cef1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3578.4e9f9948a9a6f2f4.js +0 -2
- 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/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/4313.76f232c304a15bde.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/4725-34bed25720cc326b.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/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/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/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/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/layout-09788e1aa9a87db6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-3337c6a1328c2674.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/morning/page-1e5da297557d2354.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/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/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/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/term/page-ac2c1e6169cfce57.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/workspace/page-c1c80e345fa9d6f5.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 → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
package/src/storage/file-lock.ts
CHANGED
|
@@ -70,13 +70,26 @@ export function acquireLockSync(lockPath: string, opts: LockOpts = {}): ReleaseL
|
|
|
70
70
|
for (let attempt = 0; attempt < maxTries; attempt += 1) {
|
|
71
71
|
try {
|
|
72
72
|
const fd = openSync(lockPath, 'wx');
|
|
73
|
-
try {
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
try {
|
|
74
|
+
writeSync(fd, `${process.pid}\n`);
|
|
75
|
+
} catch (writeErr) {
|
|
76
|
+
// 보유자 PID 를 못 쓰면 holderIsDead·onWait 독자 계약이 깨진다 — 방금 'wx' 로 만든 파일을 정리하고 올린다.
|
|
77
|
+
try { closeSync(fd); } catch { /* ignore */ }
|
|
78
|
+
try { unlinkSync(lockPath); } catch { /* ignore */ }
|
|
79
|
+
throw writeErr;
|
|
80
|
+
}
|
|
81
|
+
// ⭐ 소유 증명은 파일 «내용»이 아니라 «정체»다 — 내용은 보유자 PID 한 줄 계약(test/storage-file-lock ·
|
|
82
|
+
// goal-author supersession 잠금)이라 구분 토큰을 심을 수 없고, rm+즉시 재생성은 inode 번호를
|
|
83
|
+
// 재사용하므로 inode 만으로는 교체를 못 가린다(실측). dev·ino·mtimeNs 셋이 같을 때만 우리가 만든
|
|
84
|
+
// 그 파일로 본다 — 재사용된 inode 도 새 mtime 을 가지므로 교체 자물쇠는 mtimeNs 에서 갈린다.
|
|
85
|
+
const acquired = fstatSync(fd, { bigint: true });
|
|
76
86
|
closeSync(fd);
|
|
77
87
|
return () => {
|
|
78
88
|
try {
|
|
79
|
-
|
|
89
|
+
const current = statSync(lockPath, { bigint: true });
|
|
90
|
+
if (current.dev === acquired.dev && current.ino === acquired.ino && current.mtimeNs === acquired.mtimeNs) {
|
|
91
|
+
unlinkSync(lockPath);
|
|
92
|
+
}
|
|
80
93
|
} catch { /* stale recovery or replacement won the path */ }
|
|
81
94
|
};
|
|
82
95
|
} catch (err) {
|
|
@@ -3,7 +3,7 @@ import { randomBytes } from 'node:crypto';
|
|
|
3
3
|
import { loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../self-implement/run-ledger.js';
|
|
4
4
|
import { remoteLedgerMirrorDir } from './parent-host.js';
|
|
5
5
|
import { prodInstanceRoot } from '../instance/resolve.js';
|
|
6
|
-
import { cardPrNumber, updateTaskCard, type TaskCard } from './task-hand.js';
|
|
6
|
+
import { cardPrNumber, updateTaskCard, updateTaskCardsAtomically, type TaskCard } from './task-hand.js';
|
|
7
7
|
|
|
8
8
|
export interface AdoptPrView {
|
|
9
9
|
number: number; url: string; state: string; baseRefName: string; headRefOid: string;
|
|
@@ -20,6 +20,9 @@ export interface AdoptPrInput {
|
|
|
20
20
|
unlinkedTerminal?: boolean;
|
|
21
21
|
observedRun?: { runId?: string; runChildId?: string; parentHost?: string; launchId?: string };
|
|
22
22
|
observedChecklist?: { id: string; version: string; status: string; cardVersion?: string };
|
|
23
|
+
/** --rebind: source snapshot and terminal proof (computed before taking the state lock). */
|
|
24
|
+
rebindSource?: { card: Pick<TaskCard, 'id' | 'status' | 'runId' | 'runChildId' | 'launchId' | 'parentHost' | 'checklistId' | 'checklistVersion' | 'pr'>;
|
|
25
|
+
terminalRunEvidence: boolean };
|
|
23
26
|
checklistAtWrite?: () => { id: string; status: string } | undefined;
|
|
24
27
|
}
|
|
25
28
|
|
|
@@ -60,7 +63,7 @@ export function adoptedRunTerminal(card: TaskCard, pr: AdoptPrView,
|
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
/** The PR is read from the selected repository before this call; rejudge checks it again before every live move. */
|
|
63
|
-
export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created: boolean; changed: boolean } {
|
|
66
|
+
export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created: boolean; changed: boolean; previousCardId?: string } {
|
|
64
67
|
const { pr } = input;
|
|
65
68
|
const slug = pr.url.match(/^https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/\d+\/?$/)?.[1];
|
|
66
69
|
if (!Number.isSafeInteger(pr.number) || pr.number < 1 || pr.state !== 'OPEN' || pr.baseRefName !== 'main'
|
|
@@ -68,6 +71,11 @@ export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created:
|
|
|
68
71
|
|| Number(pr.url.match(/\/pull\/(\d+)/)?.[1]) !== pr.number
|
|
69
72
|
|| !/^[a-f0-9]{40}$/i.test(pr.headRefOid)) throw new Error('입양할 PR은 현재 저장소의 OPEN/main PR 번호·URL·head SHA40이어야 한다');
|
|
70
73
|
if ((input.cardId === undefined) === (input.checklist === undefined)) throw new Error('--card 또는 --checklist/--version 중 하나만 준다');
|
|
74
|
+
if (input.rebindSource) {
|
|
75
|
+
if (input.cardId || !input.checklist || !input.version || input.checklist.version !== input.version)
|
|
76
|
+
throw new Error('--rebind는 --checklist와 같은 --version을 지정하고 --card는 생략한다');
|
|
77
|
+
return rebindExistingPr(input, input.rebindSource);
|
|
78
|
+
}
|
|
71
79
|
if (input.cardId && !input.version) throw new Error('기존 카드는 체크리스트 판을 확정해야 한다');
|
|
72
80
|
if (input.checklist && (!input.checklist.id || !input.checklist.title || !input.checklist.version
|
|
73
81
|
|| ['green', 'done'].includes(input.checklist.status))) throw new Error('입양할 체크리스트 칸은 미완 판·id·제목이어야 한다');
|
|
@@ -138,3 +146,56 @@ export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created:
|
|
|
138
146
|
if (!result) throw new Error(`카드 쓰기 실패: ${id}`);
|
|
139
147
|
return { card: result, created, changed };
|
|
140
148
|
}
|
|
149
|
+
|
|
150
|
+
function rebindExistingPr(input: AdoptPrInput, sourceSnapshot: NonNullable<AdoptPrInput['rebindSource']>)
|
|
151
|
+
: { card: TaskCard; created: true; changed: true; previousCardId: string } {
|
|
152
|
+
const { pr, checklist, version } = input;
|
|
153
|
+
if (!checklist || !version) throw new Error('--rebind 대상 체크리스트 판이 없다');
|
|
154
|
+
const at = (input.now ?? new Date()).toISOString();
|
|
155
|
+
const id = `ta-${at.slice(0, 10).replaceAll('-', '')}-${randomBytes(3).toString('hex')}`;
|
|
156
|
+
const replacements = updateTaskCardsAtomically(input.statePath, (tasks) => {
|
|
157
|
+
if (tasks[id]) throw new Error(`새 카드 id 충돌: ${id}`);
|
|
158
|
+
const matches = Object.values(tasks).filter((card) => cardPrNumber(card) === pr.number);
|
|
159
|
+
if (matches.length !== 1) throw new Error(matches.length
|
|
160
|
+
? `PR #${pr.number}가 여러 카드에 묶였다 — 임의로 rebind하지 않는다`
|
|
161
|
+
: `PR #${pr.number}가 기존 카드에 묶이지 않았다 — --rebind 대상 없음`);
|
|
162
|
+
const current = matches[0]!;
|
|
163
|
+
const observed = sourceSnapshot.card;
|
|
164
|
+
if (current.id !== observed.id || current.status !== observed.status || current.runId !== observed.runId
|
|
165
|
+
|| current.runChildId !== observed.runChildId || current.launchId !== observed.launchId
|
|
166
|
+
|| current.checklistId !== observed.checklistId || current.checklistVersion !== observed.checklistVersion
|
|
167
|
+
|| current.parentHost?.host !== observed.parentHost?.host || cardPrNumber(current) !== cardPrNumber(observed)
|
|
168
|
+
|| (typeof current.pr === 'object' ? current.pr.url : undefined) !== (typeof observed.pr === 'object' ? observed.pr.url : undefined))
|
|
169
|
+
throw new Error(`rebind 중 원본 카드가 바뀌었다: ${observed.id}`);
|
|
170
|
+
if (typeof current.pr === 'object' && current.pr.url && current.pr.url !== pr.url)
|
|
171
|
+
throw new Error(`원본 카드의 PR URL이 조회 결과와 다르다: ${current.id}`);
|
|
172
|
+
if (current.status !== 'failed' && (current.checklistVersion === version && current.checklistId === checklist.id))
|
|
173
|
+
throw new Error(`같은 판·칸의 failed 카드만 rebind할 수 있다: ${current.id}`);
|
|
174
|
+
if (current.status !== 'failed' && (current.status !== 'launched' || sourceSnapshot.terminalRunEvidence !== true))
|
|
175
|
+
throw new Error(`원본 런 종결·정확한 PR 근거가 없다: ${current.id}`);
|
|
176
|
+
if (Object.values(tasks).some((card) => card.id !== current.id && card.status === 'launched' && card.taLand === true
|
|
177
|
+
&& cardPrNumber(card) !== undefined && card.checklistId === checklist.id && card.checklistVersion === version))
|
|
178
|
+
throw new Error(`칸 ${checklist.id}에 이미 TA 착지 후보 카드가 있다`);
|
|
179
|
+
const liveCell = input.checklistAtWrite?.();
|
|
180
|
+
if (input.checklistAtWrite && (!liveCell || liveCell.id !== checklist.id || ['green', 'done'].includes(liveCell.status)))
|
|
181
|
+
throw new Error(`입양 중 체크리스트 칸이 바뀌거나 완료됐다: ${checklist.id}`);
|
|
182
|
+
|
|
183
|
+
const { pr: _pr, adoptedPr: _adoptedPr, prTerminal: _prTerminal, taLand: _taLand, ...oldCard } = current;
|
|
184
|
+
const released: TaskCard = { ...oldCard, history: [...current.history, {
|
|
185
|
+
at, event: 'pr-rebound-out', pr: pr.number, head: pr.headRefOid,
|
|
186
|
+
detail: `PR 결속을 ${version}/${checklist.id} 새 카드 ${id}로 이동 · ${pr.url}`,
|
|
187
|
+
}] };
|
|
188
|
+
const adopted: TaskCard = {
|
|
189
|
+
id, text: checklist.title, checklistId: checklist.id, checklistVersion: version,
|
|
190
|
+
createdAt: at, status: 'launched', taLand: true, pr: { number: pr.number, url: pr.url },
|
|
191
|
+
adoptedPr: { pr: pr.number, url: pr.url, head: pr.headRefOid, at },
|
|
192
|
+
history: [{ at, event: 'pr-adopted', pr: pr.number, head: pr.headRefOid,
|
|
193
|
+
detail: `기존 PR rebind · 원본 카드 ${current.id} · ${pr.url} · 새 구현 발사 0` }],
|
|
194
|
+
};
|
|
195
|
+
return [released, adopted];
|
|
196
|
+
});
|
|
197
|
+
const card = replacements?.find((replacement) => replacement.id === id);
|
|
198
|
+
const previous = replacements?.find((replacement) => replacement.id !== id);
|
|
199
|
+
if (!card || !previous) throw new Error('PR rebind 원자 갱신 결과가 없다');
|
|
200
|
+
return { card, created: true, changed: true, previousCardId: previous.id };
|
|
201
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { linesOutsideFencedCode, validateGoalDoneEvidenceCommand } from '../self-implement/goal-author.js';
|
|
2
|
+
|
|
3
|
+
const EVIDENCE_LINE = /^(\s*(?:[-*]\s*)?완료 경계 증거 명령\s*:\s*)(.*?)(\s*)$/;
|
|
4
|
+
|
|
5
|
+
/** Remove known result annotations from an evidence command, preserving every other line. */
|
|
6
|
+
export function normalizeEvidenceCommandLines(document: string): { text: string; warnings: string[]; unrecognized: string[] } {
|
|
7
|
+
const warnings: string[] = [];
|
|
8
|
+
const unrecognized: string[] = [];
|
|
9
|
+
const replacements: Array<{ start: number; old: string; next: string }> = [];
|
|
10
|
+
for (const line of linesOutsideFencedCode(document)) {
|
|
11
|
+
const match = EVIDENCE_LINE.exec(line.text);
|
|
12
|
+
if (!match) continue;
|
|
13
|
+
const original = match[2].trim();
|
|
14
|
+
if (!original) continue;
|
|
15
|
+
let candidate = original.replace(/\s*(?:→|->)\s*0\s+fail\s*$/i, '')
|
|
16
|
+
.replace(/\s*·\s*typecheck\s+PASS\s*$/i, '').trim();
|
|
17
|
+
// Some cards have both annotations; peel them in either order.
|
|
18
|
+
candidate = candidate.replace(/\s*(?:→|->)\s*0\s+fail\s*$/i, '')
|
|
19
|
+
.replace(/\s*·\s*typecheck\s+PASS\s*$/i, '').trim();
|
|
20
|
+
if (candidate.startsWith('`') && candidate.endsWith('`') && candidate.length > 2)
|
|
21
|
+
candidate = candidate.slice(1, -1).trim();
|
|
22
|
+
if (candidate === original) {
|
|
23
|
+
if (/[`→]|->|·\s*typecheck\b/i.test(original)) {
|
|
24
|
+
warnings.push(`완료 경계 증거 명령 정규화 불가: ${original}`);
|
|
25
|
+
unrecognized.push(original);
|
|
26
|
+
}
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// An unrecognized decoration is never silently converted into a shell command.
|
|
30
|
+
if (!validateGoalDoneEvidenceCommand(candidate).command) {
|
|
31
|
+
warnings.push(`완료 경계 증거 명령 정규화 불가: ${original}`);
|
|
32
|
+
unrecognized.push(original);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
replacements.push({ start: line.start, old: line.text, next: `${match[1]}${candidate}${match[3]}` });
|
|
36
|
+
warnings.push(`완료 경계 증거 명령 정규화: ${original} → ${candidate}`);
|
|
37
|
+
}
|
|
38
|
+
let text = document;
|
|
39
|
+
for (const replacement of replacements.reverse())
|
|
40
|
+
text = text.slice(0, replacement.start) + replacement.next + text.slice(replacement.start + replacement.old.length);
|
|
41
|
+
return { text, warnings, unrecognized };
|
|
42
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { lstatSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { loadPrivateRedactions, privateRedactionsPath } from '../../scripts/public-export.js';
|
|
3
|
+
import { defaultSshRunner, type SshRunner } from './parent-host.js';
|
|
4
|
+
import { shellQuote } from './task-hand.js';
|
|
5
|
+
|
|
6
|
+
const ALLOWED_HOSTS = new Set(['node-b', 'elangram-wsl', 'host-e-wsl']);
|
|
7
|
+
|
|
8
|
+
/** Give a train host the same private list that release export-check reads on HQ.
|
|
9
|
+
* The list travels only over SSH stdin and is installed atomically at mode 0600.
|
|
10
|
+
* A missing or unreadable list is a failed preflight, never a weaker leak check. */
|
|
11
|
+
export function provisionExportRedactions(
|
|
12
|
+
host: string,
|
|
13
|
+
sourcePath = privateRedactionsPath(),
|
|
14
|
+
ssh: SshRunner = defaultSshRunner,
|
|
15
|
+
): void {
|
|
16
|
+
if (!ALLOWED_HOSTS.has(host)) throw new Error('export redactions host not allowed');
|
|
17
|
+
let payload: string;
|
|
18
|
+
try {
|
|
19
|
+
const stat = lstatSync(sourcePath);
|
|
20
|
+
if (!stat.isFile() || (stat.mode & 0o077) !== 0 || stat.size === 0 || stat.size > 1_048_576) {
|
|
21
|
+
throw new Error('source is not a private regular file');
|
|
22
|
+
}
|
|
23
|
+
if (!loadPrivateRedactions(sourcePath)?.length) throw new Error('source has no redaction entries');
|
|
24
|
+
payload = readFileSync(sourcePath, 'utf8');
|
|
25
|
+
if (payload.includes('\0')) throw new Error('source contains NUL');
|
|
26
|
+
} catch {
|
|
27
|
+
throw new Error('export redactions source unavailable or invalid');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const code = [
|
|
31
|
+
'const fs=require("node:fs"),path=require("node:path"),crypto=require("node:crypto");',
|
|
32
|
+
// Remote SSH execution has no repository resolver module. Match privateRedactionsPath():
|
|
33
|
+
// ELANOUS_EXPORT_REDACTIONS first, then the remote shell HOME default (OP #40040).
|
|
34
|
+
'const home=process.env.HOME?.trim(),override=process.env.ELANOUS_EXPORT_REDACTIONS?.trim();',
|
|
35
|
+
'const file=override||(home?path.join(home,".elanous","export-redactions.tsv"):"");if(!file||!path.isAbsolute(file))process.exit(2);const dir=path.dirname(file);',
|
|
36
|
+
'const bytes=fs.readFileSync(0);if(!bytes.length||bytes.length>1048576||bytes.includes(0))process.exit(2);',
|
|
37
|
+
'fs.mkdirSync(dir,{recursive:true,mode:0o700});fs.chmodSync(dir,0o700);',
|
|
38
|
+
'const temp=file+"."+process.pid+"."+crypto.randomBytes(6).toString("hex")+".tmp";',
|
|
39
|
+
'try{fs.writeFileSync(temp,bytes,{mode:0o600,flag:"wx"});fs.chmodSync(temp,0o600);fs.renameSync(temp,file)}catch{try{fs.rmSync(temp,{force:true})}catch{};process.exit(3)}',
|
|
40
|
+
].join('');
|
|
41
|
+
const result = ssh(host, `umask 077; bun -e ${shellQuote(code)}`, 20_000, payload);
|
|
42
|
+
if (result.status !== 0) throw new Error(`export redactions provision failed (ssh rc=${result.status ?? 'unknown'})`);
|
|
43
|
+
}
|
|
@@ -44,6 +44,8 @@ export const PARENT_HOST_ENV = 'ELANOUS_TA_PARENT_HOST';
|
|
|
44
44
|
const DEFAULT_REMOTE_ELANOUS = '$HOME/.local/share/elanous/bin/elanous';
|
|
45
45
|
const DEFAULT_REMOTE_CONFIG_DIR = '$HOME/.elanous';
|
|
46
46
|
const HOST_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]{0,127}$/;
|
|
47
|
+
/** A parent can wait for a child for tens of minutes; the two-minute HTTP refresh floor is too short here. */
|
|
48
|
+
export const PARENT_CHILD_CREDENTIAL_MIN_REMAINING_MS = 60 * 60_000;
|
|
47
49
|
|
|
48
50
|
/** Missing child-provider metadata keeps the established Pod default: the HQ Codex mirror is needed. */
|
|
49
51
|
export function shouldInstallRemoteCodexAccess(effectiveChildProvider: string | undefined): boolean {
|
|
@@ -81,7 +83,7 @@ export function resolveParentHosts(config: ParentHostSetting | undefined, env: N
|
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
/** Capacity sample is read on the host before launch. Unknown or saturated capacity is not a positive weight. */
|
|
84
|
-
export interface ParentHostCapacity { active: number; waiting: number; approvalHeadroom: number; load: number }
|
|
86
|
+
export interface ParentHostCapacity { active: number; waiting: number; limit: number; headroom: number; approvalHeadroom: number; load: number }
|
|
85
87
|
|
|
86
88
|
export interface ParentHostPodFit {
|
|
87
89
|
state: 'fits' | 'never-fits' | 'unmeasured';
|
|
@@ -133,13 +135,13 @@ const LOAD_MARKER = '__ELANOUS_PARENT_LOAD__';
|
|
|
133
135
|
/** Best-effort macOS `ps` fallback; Linux/WSL uses argv boundaries below. */
|
|
134
136
|
export const PARENT_HOST_ACTIVE_FILTER = String.raw`/^(([^ ]+\/)?(bun|node|nodejs) )?([^ ]+\/)?elanous(\.mjs)?( --config-dir [^ ]+)? harness (say|ask)( |$)/ && / --no-auto-merge( |$)/ && !/ --substrate local( |$)/ && !/^([^ ]+\/)?[^ ]*sh -c/`;
|
|
135
137
|
/** Count exact Linux argv entries so Pod-local commands and goal text cannot masquerade as host parents. */
|
|
136
|
-
export const PARENT_HOST_PROC_COUNT_SCRIPT = "count=0; proc_root=${1:-/proc}; for file in \"$proc_root\"/[0-9]*/cmdline; do [ -r \"$file\" ] || continue; argv=(); while IFS= read -r -d '' arg; do argv+=(\"$arg\"); done < \"$file\" 2>/dev/null || true; [ ${#argv[@]} -ge 3 ] || continue; program=\"${argv[0]##*/}\"; case \"$program\" in elanous|elanous.mjs) ;; bun|node|nodejs) script_match=0; for ((i=1; i<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == */elanous.mjs ]]; then script_match=1; break; fi; [[ \"${argv[i]}\" == harness ]] && break; done; [ \"$script_match\" -eq 1 ] || continue ;; *) continue ;; esac; harness=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == harness && ( \"${argv[i+1]}\" == say || \"${argv[i+1]}\" == ask ) ]]; then harness=1; break; fi; done; [ \"$harness\" -eq 1 ] || continue; has_no_auto_merge=0; for arg in \"${argv[@]}\"; do [[ \"$arg\" == --no-auto-merge ]] && has_no_auto_merge=1; done; [ \"$has_no_auto_merge\" -eq 1 ] || continue; local_substrate=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == --substrate && \"${argv[i+1]}\" == local ]]; then local_substrate=1; break; fi; done; [ \"$local_substrate\" -eq 1 ] || count=$((count+1)); done; printf '__ELANOUS_PARENT_CAPACITY__%s\\n' \"$count\""
|
|
138
|
+
export const PARENT_HOST_PROC_COUNT_SCRIPT = "count=0; proc_root=${1:-/proc}; for file in \"$proc_root\"/[0-9]*/cmdline; do [ -r \"$file\" ] || continue; argv=(); while IFS= read -r -d '' arg; do argv+=(\"$arg\"); done < \"$file\" 2>/dev/null || true; [ ${#argv[@]} -ge 3 ] || continue; program=\"${argv[0]##*/}\"; case \"$program\" in elanous|elanous.mjs) ;; bun|node|nodejs) script_match=0; for ((i=1; i<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == */elanous.mjs ]]; then script_match=1; break; fi; [[ \"${argv[i]}\" == harness ]] && break; done; [ \"$script_match\" -eq 1 ] || continue ;; *) continue ;; esac; harness=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == harness && ( \"${argv[i+1]}\" == say || \"${argv[i+1]}\" == ask ) ]]; then harness=1; break; fi; done; [ \"$harness\" -eq 1 ] || continue; has_no_auto_merge=0; for arg in \"${argv[@]}\"; do [[ \"$arg\" == --no-auto-merge ]] && has_no_auto_merge=1; done; [ \"$has_no_auto_merge\" -eq 1 ] || continue; local_substrate=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == --substrate && \"${argv[i+1]}\" == local ]]; then local_substrate=1; break; fi; done; [ \"$local_substrate\" -eq 1 ] && continue; cgroup_file=${file%cmdline}cgroup; if [ ! -r $cgroup_file ]; then [ ! -d ${file%/cmdline} ] && continue; printf '__ELANOUS_PARENT_CAPACITY_ERROR__cgroup-unreadable\\n'; exit 1; fi; cgroup=$(cat $cgroup_file 2>/dev/null) || { [ ! -d ${file%/cmdline} ] && continue; printf '__ELANOUS_PARENT_CAPACITY_ERROR__cgroup-unreadable\\n'; exit 1; }; case $cgroup in *docker*|*kubepods*|*containerd*|*libpod*|*lxc*) continue;; esac; count=$((count+1)); done; printf '__ELANOUS_PARENT_CAPACITY__%s\\n' \"$count\""
|
|
137
139
|
/** Recent admission decisions are the host's measured approval backlog, not an inferred process count. */
|
|
138
140
|
export function readParentHostCapacity(target: ParentHostConfig, ssh: SshRunner = defaultSshRunner): ParentHostCapacity | null {
|
|
139
141
|
const executable = remotePath(target.elanous ?? DEFAULT_REMOTE_ELANOUS);
|
|
140
142
|
const configDir = remotePath(target.configDir ?? DEFAULT_REMOTE_CONFIG_DIR);
|
|
141
143
|
const unavailable = (reason: string): null => { try { debug.log('task-agent.parent-host', 'capacity-unavailable', { host: target.host, reason }); } catch { /* fail-soft */ } return null; };
|
|
142
|
-
const processCount = `if [ -r /proc/self/cmdline ]; then if command -v bash >/dev/null 2>&1; then bash -c ${shellQuote(PARENT_HOST_PROC_COUNT_SCRIPT)} -- /proc; else printf "${CAPACITY_ERROR_MARKER}bash-unavailable\\n"; exit 1; fi; else parents=$(ps -Ao command) || exit 1; printf '%s\\n' "$parents" | awk '${PARENT_HOST_ACTIVE_FILTER} { n++ } END { print "${CAPACITY_MARKER}" n+0 }'; fi`;
|
|
144
|
+
const processCount = `if [ -r /proc/self/cmdline ]; then if command -v bash >/dev/null 2>&1; then bash -c ${shellQuote(PARENT_HOST_PROC_COUNT_SCRIPT)} -- /proc || exit 1; else printf "${CAPACITY_ERROR_MARKER}bash-unavailable\\n"; exit 1; fi; else parents=$(ps -Ao command) || exit 1; printf '%s\\n' "$parents" | awk '${PARENT_HOST_ACTIVE_FILTER} { n++ } END { print "${CAPACITY_MARKER}" n+0 }'; fi`;
|
|
143
145
|
const script = `${processCount}; `
|
|
144
146
|
+ `${executable} --config-dir ${configDir} logs --event admit-by-usage --since 5m --json --limit 1000 || exit 1; `
|
|
145
147
|
+ `printf '\\n${APPROVAL_MARKER}\\n'; `
|
|
@@ -147,7 +149,8 @@ export function readParentHostCapacity(target: ParentHostConfig, ssh: SshRunner
|
|
|
147
149
|
+ `cores=$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null) || exit 1; printf '${LOAD_MARKER}cores=%s\\n' "$cores"`;
|
|
148
150
|
try {
|
|
149
151
|
const result = ssh(target.host, script, 15_000);
|
|
150
|
-
if (result.status !== 0) return unavailable(result.stdout.includes(`${CAPACITY_ERROR_MARKER}bash-unavailable`) ? 'bash-unavailable'
|
|
152
|
+
if (result.status !== 0) return unavailable(result.stdout.includes(`${CAPACITY_ERROR_MARKER}bash-unavailable`) ? 'bash-unavailable'
|
|
153
|
+
: result.stdout.includes(`${CAPACITY_ERROR_MARKER}cgroup-unreadable`) ? 'cgroup-unreadable' : 'remote-command-failed');
|
|
151
154
|
const activeMatch = new RegExp(`^${CAPACITY_MARKER}(\\d+)$`, 'm').exec(result.stdout);
|
|
152
155
|
const boundary = result.stdout.indexOf(`\n${APPROVAL_MARKER}\n`);
|
|
153
156
|
const logsStart = result.stdout.indexOf('\n');
|
|
@@ -181,12 +184,13 @@ export function readParentHostCapacity(target: ParentHostConfig, ssh: SshRunner
|
|
|
181
184
|
decisions.set(data.runId, data.recommended as number);
|
|
182
185
|
}
|
|
183
186
|
const waiting = [...decisions.values()].filter((n) => n === 0).length;
|
|
184
|
-
|
|
187
|
+
const headroom = Math.max(0, capacity - active - waiting);
|
|
188
|
+
return { active, waiting, limit: capacity, headroom, approvalHeadroom: headroom, load: Math.max(0, cpu / (cores * 100)) };
|
|
185
189
|
} catch { return unavailable('capacity-parse-failed'); }
|
|
186
190
|
}
|
|
187
191
|
|
|
188
192
|
/** Weighted rendezvous rank with evidence fields for launch-time observation. */
|
|
189
|
-
export function rankParentHosts(targets: readonly ParentHostConfig[], runId: string, capacities: Readonly<Record<string, ParentHostCapacity | null>>): Array<{ target: ParentHostConfig; weight: number; score: number }> {
|
|
193
|
+
export function rankParentHosts(targets: readonly ParentHostConfig[], runId: string, capacities: Readonly<Record<string, Pick<ParentHostCapacity, 'approvalHeadroom' | 'load'> | null>>): Array<{ target: ParentHostConfig; weight: number; score: number }> {
|
|
190
194
|
return targets.map((target, index) => {
|
|
191
195
|
const sample = capacities[target.host];
|
|
192
196
|
const weight = sample && Number.isSafeInteger(sample.approvalHeadroom) && sample.approvalHeadroom > 0 && Number.isFinite(sample.load) && sample.load >= 0
|
|
@@ -264,14 +268,22 @@ export interface ParentHostPreflight { ok: boolean; gaps: string[]; warnings: st
|
|
|
264
268
|
export function preflightScript(target: ParentHostConfig): string {
|
|
265
269
|
const elanous = remotePath(target.elanous ?? DEFAULT_REMOTE_ELANOUS);
|
|
266
270
|
const configDir = remotePath(target.configDir ?? DEFAULT_REMOTE_CONFIG_DIR);
|
|
271
|
+
const grokCredentialFloorSeconds = Math.ceil(PARENT_CHILD_CREDENTIAL_MIN_REMAINING_MS / 1_000);
|
|
267
272
|
return [
|
|
268
273
|
`echo "version=$(${elanous} --version 2>/dev/null | tail -1 | cut -d' ' -f1)"`,
|
|
269
274
|
`test -f ${configDir}/config.json && echo config=1`,
|
|
270
275
|
`grep -Eq '"podPool"[[:space:]]*:[[:space:]]*"[^"[:space:]]+' ${configDir}/config.json 2>/dev/null && echo podPool=1`,
|
|
271
276
|
`(cd ${shellQuote(target.cwd)} 2>/dev/null && git rev-parse --is-inside-work-tree >/dev/null 2>&1) && echo repo=1`,
|
|
272
277
|
`command -v kubectl >/dev/null 2>&1 && echo kubectl=1`,
|
|
278
|
+
`{ command -v grok >/dev/null 2>&1 || [ -x "$HOME/.grok/bin/grok" ]; } && echo grokCli=1`,
|
|
279
|
+
`{ command -v codex >/dev/null 2>&1 || [ -x "$HOME/.local/bin/codex" ]; } && echo codexCli=1`,
|
|
273
280
|
`n=$(grep -Ec '^[[:space:]]*"openai-codex(:[^"]*)?"[[:space:]]*:[[:space:]]*\\{' ${configDir}/auth.json 2>/dev/null); echo "codexAccounts=\${n:-0}"`,
|
|
274
281
|
`{ grep -Eq '"key"[[:space:]]*:[[:space:]]*"[^"]+"' "$HOME/.grok/auth.json" 2>/dev/null || [ -n "\${XAI_API_KEY:-}\${GROK_API_KEY:-}\${GROK_CODE_XAI_API_KEY:-}" ]; } && echo grok=1`,
|
|
282
|
+
// The remote host owns its device-auth session. Ignore the legacy HQ mirror entry; it can outlive and mask the host credential.
|
|
283
|
+
// Read only expiry metadata, never credential values, and compare against the shared minimum lifetime.
|
|
284
|
+
`grokProbe=$(if [ ! -f "$HOME/.grok/auth.json" ]; then printf '0|'; else bun -e 'const fs=require("node:fs");try{const auth=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const entries=Object.entries(auth).filter(([id])=>id!=="https://auth.x.ai::hq-mirror");const hasKey=entries.some(([,entry])=>typeof entry?.key==="string"&&entry.key.length>0);const expiries=entries.filter(([,entry])=>typeof entry?.expires_at==="string").map(([,entry])=>entry.expires_at).sort();process.stdout.write((hasKey?"1":"0")+"|"+(expiries.length?expiries[expiries.length-1]:""))}catch{}' "$HOME/.grok/auth.json" 2>/dev/null; fi); grokOtherKey=\${grokProbe%%|*}; grokExp=\${grokProbe#*|}`,
|
|
285
|
+
`grokFloor=$(date -u -d "@$(( $(date +%s) + ${grokCredentialFloorSeconds} ))" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -r "$(( $(date +%s) + ${grokCredentialFloorSeconds} ))" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true); grokNow=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)`,
|
|
286
|
+
`grokHost=$(if [ -n "$XAI_API_KEY$GROK_API_KEY$GROK_CODE_XAI_API_KEY" ]; then echo valid; elif [ -z "$grokProbe" ]; then echo unknown; elif [ -z "$grokExp" ]; then [ "$grokOtherKey" = 1 ] && echo unknown || echo missing; elif [ -z "$grokFloor" ] || [ -z "$grokNow" ]; then echo unknown; else printf '%s\n%s\n%s\n' "$grokExp" "$grokFloor" "$grokNow" | awk 'NR==1{e=$0} NR==2{f=$0} NR==3{n=$0} END{if (e >= f) print "valid"; else if (e >= n) print "expiring"; else print "expired"}'; fi); echo "grokHost=$grokHost"`,
|
|
275
287
|
`{ [ -s "\${ELANOUS_KEY_CACHE_DIR:-$HOME/.cache}/openrouter_api_key" ] || [ -n "\${OPENROUTER_API_KEY:-}" ]; } && echo openrouter=1`,
|
|
276
288
|
`true`,
|
|
277
289
|
].join('; ');
|
|
@@ -283,6 +295,8 @@ export interface PreflightInput {
|
|
|
283
295
|
localVersion: string;
|
|
284
296
|
/** HQ 착지 동결이 «발사도 막는» 상태인가 — 원격 부모는 그 동결을 못 본다. */
|
|
285
297
|
launchHoldActive: boolean;
|
|
298
|
+
/** Provider that the detached parent will use for its child. */
|
|
299
|
+
childProvider?: string;
|
|
286
300
|
ssh?: SshRunner;
|
|
287
301
|
}
|
|
288
302
|
|
|
@@ -306,11 +320,34 @@ export function judgeParentHostFacts(facts: Record<string, string>, input: Omit<
|
|
|
306
320
|
if (facts.podPool !== '1' && !input.podPoolOverride) gaps.push('remote-pod-pool-unset');
|
|
307
321
|
if (facts.repo !== '1') gaps.push('remote-repo-missing');
|
|
308
322
|
if (facts.kubectl !== '1') gaps.push('remote-kubectl-missing');
|
|
323
|
+
if (input.childProvider === 'grok' && facts.grokCli !== '1') gaps.push('grok-cli-missing');
|
|
324
|
+
if ((input.childProvider === 'openai-codex' || input.childProvider === 'codex') && facts.codexCli !== '1') gaps.push('codex-cli-missing');
|
|
309
325
|
}
|
|
310
326
|
if (input.launchHoldActive) gaps.push('hq-launch-freeze-active');
|
|
311
327
|
return gaps;
|
|
312
328
|
}
|
|
313
329
|
|
|
330
|
+
/** Host-side Grok credential states the preflight probe reports; HQ never sees the token itself. */
|
|
331
|
+
export type ParentHostGrokCredentialState = 'valid' | 'expiring' | 'expired' | 'missing' | 'unknown';
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* 순수 판정 — 원격 호스트가 스스로 보고한 grok 자격 상태 → **막는** gap 목록(GROK-MIRROR-REAL-SCOPE · 10-20 방향 전환).
|
|
335
|
+
*
|
|
336
|
+
* 왜 경고가 아니라 gap 인가: access-only 미러(4필드)는 원격 grok CLI 1.0.41 에서 `session/new` -32000 으로
|
|
337
|
+
* 거부됐고, HQ refresh_token 복사는 단일 주인 원칙 위반이다. ⇒ 호스트가 각자 device-auth 세션을 스스로
|
|
338
|
+
* 갱신하고, HQ 는 「쓸 수 있나」만 재서 **무효면 Grok 자식 발사 전에** 막는다(발사 뒤 -32000 반복 금지).
|
|
339
|
+
*
|
|
340
|
+
* ⛔ 상태를 «안 보고한» 호스트(구 판)는 막지 않는다 — 모름을 「죽었다」로 읽으면 멀쩡한 호스트가 조용히 빠진다.
|
|
341
|
+
*/
|
|
342
|
+
export function judgeParentHostGrokCredential(facts: Record<string, string>, opts: { childProvider?: string } = {}): string[] {
|
|
343
|
+
if (opts.childProvider !== 'grok' || facts.unreachable) return [];
|
|
344
|
+
const state = facts.grokHost as ParentHostGrokCredentialState | undefined;
|
|
345
|
+
if (state === 'missing') return ['grok-credential-missing'];
|
|
346
|
+
if (state === 'expiring') return ['grok-credential-expiring'];
|
|
347
|
+
if (state === 'expired') return ['grok-credential-expired'];
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
|
|
314
351
|
/** 순수 판정 — 원격 LLM 자격 사실 → 경고 목록(막지 않는다 · gaps 와 별개). 못 닿은 호스트는 사실이 없으므로 경고도 없다. */
|
|
315
352
|
export function judgeParentHostCredentials(facts: Record<string, string>): string[] {
|
|
316
353
|
if (facts.unreachable) return [];
|
|
@@ -330,7 +367,16 @@ export function preflightParentHost(input: PreflightInput): ParentHostPreflight
|
|
|
330
367
|
const at = line.indexOf('=');
|
|
331
368
|
if (at > 0) facts[line.slice(0, at).trim()] = line.slice(at + 1).trim();
|
|
332
369
|
}
|
|
333
|
-
const gaps = judgeParentHostFacts(facts, { localVersion: input.localVersion, launchHoldActive: input.launchHoldActive, podPoolOverride: Boolean(input.target.podPool) });
|
|
370
|
+
const gaps = judgeParentHostFacts(facts, { localVersion: input.localVersion, launchHoldActive: input.launchHoldActive, podPoolOverride: Boolean(input.target.podPool), ...(input.childProvider ? { childProvider: input.childProvider } : {}) });
|
|
371
|
+
// 호스트 자체 grok 자격은 «경고»가 아니라 발사 전 «차단» 축이다 — 무효면 OP 재로그인 요청 신호를 남긴다.
|
|
372
|
+
const credentialGaps = judgeParentHostGrokCredential(facts, { ...(input.childProvider ? { childProvider: input.childProvider } : {}) });
|
|
373
|
+
if (credentialGaps.length) {
|
|
374
|
+
try {
|
|
375
|
+
debug.log('task-agent.parent-host', 'grok-relogin-required', {
|
|
376
|
+
host: input.target.host, state: facts.grokHost ?? 'unknown', gaps: credentialGaps,
|
|
377
|
+
});
|
|
378
|
+
} catch { /* fail-soft */ }
|
|
379
|
+
}
|
|
334
380
|
const warnings = judgeParentHostCredentials(facts);
|
|
335
381
|
if (warnings.length) {
|
|
336
382
|
try {
|
|
@@ -342,7 +388,8 @@ export function preflightParentHost(input: PreflightInput): ParentHostPreflight
|
|
|
342
388
|
});
|
|
343
389
|
} catch { /* fail-soft */ }
|
|
344
390
|
}
|
|
345
|
-
|
|
391
|
+
const blocking = [...gaps, ...credentialGaps];
|
|
392
|
+
return { ok: blocking.length === 0, gaps: blocking, warnings, facts };
|
|
346
393
|
}
|
|
347
394
|
|
|
348
395
|
/** 원격이 «확실히 안 띄웠다»고 답했다 — 호출부가 로컬로 돌아가도 중복 발사가 아니다. */
|
|
@@ -360,9 +407,7 @@ export function launchRemoteParent(
|
|
|
360
407
|
args: readonly string[],
|
|
361
408
|
env: Record<string, string>,
|
|
362
409
|
ssh: SshRunner = defaultSshRunner,
|
|
363
|
-
grokMirrorResolver: () => OwnerGrokAccessMirror = resolveOwnerGrokAccessMirror,
|
|
364
410
|
effectiveChildProvider?: string,
|
|
365
|
-
now: () => number = Date.now,
|
|
366
411
|
): { pid: number; log: string } {
|
|
367
412
|
const argvProvider = childProviderFromArgs(args);
|
|
368
413
|
if (effectiveChildProvider && argvProvider && argvProvider !== effectiveChildProvider) {
|
|
@@ -371,9 +416,11 @@ export function launchRemoteParent(
|
|
|
371
416
|
const launchArgs = effectiveChildProvider && !argvProvider
|
|
372
417
|
? [...args.slice(0, 2), '--child-llm-provider', effectiveChildProvider, ...args.slice(2)]
|
|
373
418
|
: args;
|
|
419
|
+
// GROK-MIRROR-REAL-SCOPE: 원격 부모는 HQ access 미러를 «설치하지 않는다»(4필드 미러는 grok 1.0.41 에서
|
|
420
|
+
// `session/new` -32000 · HQ refresh_token 복사는 단일 주인 원칙 위반). 호스트가 각자 device-auth 로
|
|
421
|
+
// 자체 갱신 세션을 쓰고, HQ 는 preflight 에서 «유효성»만 재서 무효면 발사 전에 막는다.
|
|
374
422
|
if ((effectiveChildProvider ?? argvProvider) === 'grok') {
|
|
375
|
-
|
|
376
|
-
installRemoteGrokAccess(target, mirror, ssh, now);
|
|
423
|
+
try { debug.log('task-agent.parent-host', 'grok-host-credential', { host: target.host, runId: env.ELANOUS_RUN_ID ?? 'unknown', source: 'host-device-auth' }); } catch { /* fail-soft */ }
|
|
377
424
|
}
|
|
378
425
|
const result = ssh(target.host, remoteLaunchScript(target, launchArgs, env), 30_000);
|
|
379
426
|
const log = remoteParentLogPath(target, env.ELANOUS_RUN_ID ?? 'unknown');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** HQ same-PR repair launch and result collection; the reviewed head is the sole source of truth. */
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
3
4
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
5
|
import { dirname, join, resolve, sep } from 'node:path';
|
|
5
6
|
import { debug } from '../debug/log.js';
|
|
@@ -13,13 +14,14 @@ import { applyRepairBundle, type RepairCasOutcome, type RepairCasRequest } from
|
|
|
13
14
|
import { pairMoveId, repairNextMove } from './repair-next-move.js';
|
|
14
15
|
import type { SupervisorGoalDeficit } from '../self-implement/goal-supervisor-fill.js';
|
|
15
16
|
import { loadRunLedger, type RunLedgerEntry } from '../self-implement/run-ledger.js';
|
|
16
|
-
import { parseRepairWorkerResult } from './repair-worker.js';
|
|
17
|
+
import { parseRepairWorkerResult, repairFailureSignature } from './repair-worker.js';
|
|
17
18
|
import { TASK_SEATS, readTaskCard, updateTaskCard, type TaskCard, type TaskChildLlm, type TaskSeat } from './task-hand.js';
|
|
18
19
|
|
|
19
20
|
const WAIT_MS = 90 * 60_000;
|
|
20
21
|
const ESCALATE_MS = 6 * 60 * 60_000;
|
|
21
22
|
const ALERT_CLAIM_STALE_MS = 10 * 60_000;
|
|
22
23
|
const safe = (value: string) => value.replace(/[^A-Za-z0-9._-]/g, '_');
|
|
24
|
+
const reviewSignature = (mustFix: readonly string[]) => createHash('sha256').update(JSON.stringify(mustFix)).digest('hex');
|
|
23
25
|
|
|
24
26
|
export interface RepairLaunchRequest {
|
|
25
27
|
card: string; pr: number; head: string; repo: string; resultPath: string;
|
|
@@ -108,9 +110,9 @@ export async function repairModelAvailability(readInputs: () => Promise<Pick<Bud
|
|
|
108
110
|
export function alternateRepairModel(card: TaskCard, availability: RepairModelAvailability = { codexSubscription: false, grokSubscription: false }): { from: string; to: TaskChildLlm } {
|
|
109
111
|
const last = card.repairs?.at(-1);
|
|
110
112
|
const from = last?.toModel ?? (card.childLlm ? `${card.childLlm.provider}/${card.childLlm.model}` : 'unknown');
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
const glm: TaskChildLlm = { provider: '
|
|
113
|
+
// Pin the full model route; a bare glm-5.3 can be ambiguous in the Pod review path.
|
|
114
|
+
// A failed full GLM repair must never be retried with the smaller flash model.
|
|
115
|
+
const glm: TaskChildLlm = { provider: 'openrouter', model: 'openrouter/z-ai/glm-5.3' };
|
|
114
116
|
const sol: TaskChildLlm = { provider: 'openai-codex', model: 'gpt-6-sol' };
|
|
115
117
|
const grok: TaskChildLlm = { provider: 'grok', model: 'grok-4.6' };
|
|
116
118
|
const tier = card.tier ?? '중';
|
|
@@ -275,6 +277,8 @@ export async function runRepairCycle(input: RepairCycleInput): Promise<RepairCyc
|
|
|
275
277
|
}
|
|
276
278
|
}
|
|
277
279
|
const status = applied?.ok ? 'applied' : applied?.unconfirmed ? 'unconfirmed' : 'failed';
|
|
280
|
+
const failureSignature = status === 'failed' && !result.ok
|
|
281
|
+
? result.failureSignature ?? repairFailureSignature(result.reason ?? '') : null;
|
|
278
282
|
// NEXTMOVE-GENERAL-RELAUNCH-MOVEID — 결과 파일의 수 id 를 카드(발사 순간 적은 값)와 짝짓는다. 못 짝지으면 관측만(소비는 그대로).
|
|
279
283
|
const pairing = pairMoveId(latest.moveId, result.moveId);
|
|
280
284
|
if (pairing.kind === 'unpaired') try { debug.log('task-agent', 'move-id-unpaired', { card: card.id, pr, head: latest.head,
|
|
@@ -282,13 +286,16 @@ export async function runRepairCycle(input: RepairCycleInput): Promise<RepairCyc
|
|
|
282
286
|
const pairedMoveId = pairing.kind === 'paired' ? { moveId: pairing.moveId } : {};
|
|
283
287
|
try { debug.log('task-agent', 'repair-attempt-result', { card: card.id, pr, head: latest.head,
|
|
284
288
|
runId: latest.runId, failureType: status === 'applied' || status === 'unconfirmed' ? null : result.ok ? 'artifact-or-cas' : 'worker',
|
|
285
|
-
model: latest.toModel, resultPath: latest.resultPath, artifactDir: result.artifactDir ?? null, status, detail
|
|
289
|
+
model: latest.toModel, resultPath: latest.resultPath, artifactDir: result.artifactDir ?? null, status, detail,
|
|
290
|
+
...(result.gateFailureTests ? { gateFailureTests: result.gateFailureTests } : {}) });
|
|
286
291
|
} catch { /* diagnostics cannot change the result */ }
|
|
287
292
|
try {
|
|
288
293
|
updateTaskCard(statePath, card.id, (current) => current?.repairs?.some((entry) => entry.runId === latest.runId
|
|
289
294
|
&& (entry.status === 'requested' || (claimedThisCycle && entry.status === 'unconfirmed' && entry.commit === result?.result?.commit)))
|
|
290
295
|
? { ...current, repairs: current.repairs.map((entry) => entry.runId === latest.runId
|
|
291
|
-
? { ...entry, status, detail, ...(
|
|
296
|
+
? { ...entry, status, detail, ...(failureSignature ? { failureSignature } : {}),
|
|
297
|
+
...(failureSignature?.startsWith('gate:') && result.gateFailureTests ? { gateFailureTests: result.gateFailureTests } : {}),
|
|
298
|
+
...(result?.result && status === 'unconfirmed' ? { commit: result.result.commit,
|
|
292
299
|
bundleSha256: result.result.bundleSha256, bundlePath: join(resolve(result.artifactDir!), 'commit.bundle') } : {}),
|
|
293
300
|
...(applied?.ok ? { commit: applied.toHead } : {}) } : entry),
|
|
294
301
|
history: [...(current.history ?? []), { at: now.toISOString(), event: 'repair-result', pr, head: latest.head,
|
|
@@ -428,10 +435,61 @@ export async function runRepairCycle(input: RepairCycleInput): Promise<RepairCyc
|
|
|
428
435
|
return { decision: 'would-repair', reason };
|
|
429
436
|
}
|
|
430
437
|
const next = attempts.length + 1;
|
|
431
|
-
const runId = mintRunId();
|
|
432
438
|
// 결정 순간 만든 수 id — 아래 발사·카드·관측이 «이 값»만 쓴다(다시 만들지 않는다).
|
|
433
439
|
const moveId = judged.moveId;
|
|
434
440
|
const { from, to } = alternateRepairModel(card, availability);
|
|
441
|
+
const nextModel = `${to.provider}/${to.model}`;
|
|
442
|
+
const repeatSignature = latest?.status === 'failed' && latest.head.toLowerCase() === head.toLowerCase()
|
|
443
|
+
&& latest.reviewSignature === reviewSignature(input.mustFix) && latest.failureSignature
|
|
444
|
+
&& (latest.failureSignature.startsWith('gate:sha256:')
|
|
445
|
+
|| latest.failureSignature.startsWith('provider:ambiguous-primary:') && latest.toModel === nextModel)
|
|
446
|
+
? latest.failureSignature : null;
|
|
447
|
+
if (repeatSignature) {
|
|
448
|
+
const prior = latest!;
|
|
449
|
+
const tests = prior.gateFailureTests?.slice(0, 4).join(' | ');
|
|
450
|
+
const reason = `same PR/head/review deterministic repair failure ${repeatSignature}; owner repair required${tests ? ` · ${tests}` : ''}`;
|
|
451
|
+
let recorded = false;
|
|
452
|
+
updateTaskCard(statePath, card.id, (current) => {
|
|
453
|
+
if (!current || current.status !== 'launched' || !current.repairs?.some((entry) =>
|
|
454
|
+
entry.runId === prior.runId && entry.status === 'failed' && entry.failureSignature === repeatSignature
|
|
455
|
+
&& entry.reviewSignature === prior.reviewSignature)
|
|
456
|
+
|| current.history?.some((entry) => entry.event === 'repair-signature-repeat-stopped' && entry.pr === pr
|
|
457
|
+
&& entry.head?.toLowerCase() === head.toLowerCase() && entry.runId === prior.runId)) return undefined;
|
|
458
|
+
recorded = true;
|
|
459
|
+
return { ...current, status: 'failed', history: [...(current.history ?? []),
|
|
460
|
+
{ at: now.toISOString(), event: 'repair-signature-repeat-stopped', pr, head, runId: prior.runId, detail: reason }] };
|
|
461
|
+
});
|
|
462
|
+
if (recorded) try { debug.log('task-agent', 'repair-signature-repeat-stopped', { card: card.id, pr, head,
|
|
463
|
+
signature: repeatSignature, priorRunId: prior.runId, skippedRelaunch: true }); } catch { /* fail-soft */ }
|
|
464
|
+
let notifyClaimed = false;
|
|
465
|
+
updateTaskCard(statePath, card.id, (current) => {
|
|
466
|
+
const history = current?.history ?? [];
|
|
467
|
+
const lastAlert = history.filter((entry) => entry.runId === prior.runId && entry.event.startsWith('repair-repeat-owner-')).at(-1);
|
|
468
|
+
const staleClaim = lastAlert?.event === 'repair-repeat-owner-claimed'
|
|
469
|
+
&& now.getTime() - Date.parse(lastAlert.at) >= ALERT_CLAIM_STALE_MS;
|
|
470
|
+
if (!current || !history.some((entry) => entry.event === 'repair-signature-repeat-stopped'
|
|
471
|
+
&& entry.pr === pr && entry.head?.toLowerCase() === head.toLowerCase() && entry.runId === prior.runId)
|
|
472
|
+
|| lastAlert && lastAlert.event !== 'repair-repeat-owner-failed' && !staleClaim) return undefined;
|
|
473
|
+
notifyClaimed = true;
|
|
474
|
+
return { ...current, history: [...history,
|
|
475
|
+
{ at: now.toISOString(), event: 'repair-repeat-owner-claimed', pr, head, runId: prior.runId, detail: reason }] };
|
|
476
|
+
});
|
|
477
|
+
if (notifyClaimed) {
|
|
478
|
+
let event = 'repair-repeat-owner-sent';
|
|
479
|
+
let detail = reason;
|
|
480
|
+
try {
|
|
481
|
+
(input.notify ?? defaultNotify)(owner.seat, `${reason} · card ${card.id} · owner ${owner.seat} via ${owner.source}`);
|
|
482
|
+
} catch (error) {
|
|
483
|
+
event = 'repair-repeat-owner-failed';
|
|
484
|
+
detail = `${reason} · ${String(error).slice(0, 200)}`;
|
|
485
|
+
}
|
|
486
|
+
updateTaskCard(statePath, card.id, (current) => current?.history?.some((entry) =>
|
|
487
|
+
entry.event === 'repair-repeat-owner-claimed' && entry.runId === prior.runId)
|
|
488
|
+
? { ...current, history: [...current.history, { at: now.toISOString(), event, pr, head, runId: prior.runId, detail }] } : undefined);
|
|
489
|
+
}
|
|
490
|
+
return { decision: 'repair-stopped', reason };
|
|
491
|
+
}
|
|
492
|
+
const runId = mintRunId();
|
|
435
493
|
const resultPath = repairResultPath(statePath, card.id, pr, head, next, runId);
|
|
436
494
|
const goalFile = resultPath.replace(/\.json$/, '.goal.txt');
|
|
437
495
|
const goal = `기존 PR #${pr}의 리뷰 때 head ${head}를 같은 가지에서 수리한다. 새 PR을 열지 말고 아래 must-fix 원문만 고쳐 commit-only 결과를 반환한다.\n\n${input.mustFix.map((item, i) => `${i + 1}. ${item}`).join('\n')}`;
|
|
@@ -442,7 +500,8 @@ export async function runRepairCycle(input: RepairCycleInput): Promise<RepairCyc
|
|
|
442
500
|
if (!current || current.status !== 'launched' || (current.repairs ?? []).length !== (card.repairs ?? []).length) return undefined;
|
|
443
501
|
claimed = true;
|
|
444
502
|
return { ...current, repairs: [...(current.repairs ?? []), { pr, head, branch, at: now.toISOString(),
|
|
445
|
-
move: judged.judgement.move, moveId, runId, resultPath, fromModel: from, toModel: `${to.provider}/${to.model}`,
|
|
503
|
+
move: judged.judgement.move, moveId, runId, resultPath, fromModel: from, toModel: `${to.provider}/${to.model}`,
|
|
504
|
+
reviewSignature: reviewSignature(input.mustFix), status: 'requested' }],
|
|
446
505
|
history: [...(current.history ?? []), { at: now.toISOString(), event: 'repair-launched', pr, head, runId,
|
|
447
506
|
effect: judged.judgement.move, moveId, detail: `source pr:${pr} · owner ${owner.seat} via ${owner.source} · must-fix ${input.mustFix.length} · childLlm ${from} → ${to.provider}/${to.model}` }] };
|
|
448
507
|
});
|
|
@@ -22,9 +22,32 @@ export interface RepairWorkerRequest {
|
|
|
22
22
|
|
|
23
23
|
export interface RepairWorkerResult {
|
|
24
24
|
pr: number; head: string; runId: string; ok: boolean; reason?: string; moveId?: string;
|
|
25
|
+
/** A classified, stable failure only. Generic gate-failed is deliberately unsigned. */
|
|
26
|
+
failureSignature?: string;
|
|
27
|
+
/** Exact introduced test identities from the same signed gate receipt. */
|
|
28
|
+
gateFailureTests?: string[];
|
|
25
29
|
job?: string; artifactDir?: string; result?: RepairCommitResult;
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
export function repairFailureSignature(output: string): string | null {
|
|
33
|
+
const gate = output.match(/^GATE_FAILURE_SIGNATURE=sha256:([a-f0-9]{64})\s*$/m);
|
|
34
|
+
if (gate) return `gate:sha256:${gate[1]}`;
|
|
35
|
+
const model = output.match(/review fallback: ambiguous or unsupported primary model ["“]([^"”\n]+)["”]/i);
|
|
36
|
+
const name = model?.[1]?.trim().toLowerCase();
|
|
37
|
+
return name && /^[a-z0-9._/-]{1,120}$/.test(name) ? `provider:ambiguous-primary:${name}` : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function repairGateFailureTests(output: string): string[] | null {
|
|
41
|
+
const line = /^GATE_FAILURE_TESTS=(\[[^\r\n]*\])\s*$/m.exec(output)?.[1];
|
|
42
|
+
if (!line) return null;
|
|
43
|
+
try {
|
|
44
|
+
const tests: unknown = JSON.parse(line);
|
|
45
|
+
return Array.isArray(tests) && tests.length > 0 && tests.length <= 32
|
|
46
|
+
&& tests.every((test) => typeof test === 'string' && test.length > 0 && test.length <= 512)
|
|
47
|
+
? tests as string[] : null;
|
|
48
|
+
} catch { return null; }
|
|
49
|
+
}
|
|
50
|
+
|
|
28
51
|
export function repairHarnessArgs(request: RepairWorkerRequest): string[] {
|
|
29
52
|
if (!Number.isSafeInteger(request.pr) || request.pr < 1 || !SHA40.test(request.head)
|
|
30
53
|
|| !request.goal.trim() || !request.runId) throw new Error('repair worker request invalid');
|
|
@@ -71,7 +94,15 @@ export async function runRepairWorker(request: RepairWorkerRequest): Promise<Rep
|
|
|
71
94
|
child.once('close', resolve);
|
|
72
95
|
});
|
|
73
96
|
const marker = parseRepairMarker(output, request.pr, request.head, request.runId);
|
|
74
|
-
if (code !== 0)
|
|
97
|
+
if (code !== 0) {
|
|
98
|
+
result.reason = `harness exited ${code}: ${output.slice(-600)}`;
|
|
99
|
+
const failureSignature = repairFailureSignature(output);
|
|
100
|
+
if (failureSignature) {
|
|
101
|
+
result.failureSignature = failureSignature;
|
|
102
|
+
const tests = failureSignature.startsWith('gate:') ? repairGateFailureTests(output) : null;
|
|
103
|
+
if (tests) result.gateFailureTests = tests;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
75
106
|
else if (!marker) result.reason = `repair artifact marker missing or invalid: ${output.slice(-600)}`;
|
|
76
107
|
else Object.assign(result, { ok: true, ...marker });
|
|
77
108
|
} catch (error) {
|
|
@@ -96,6 +127,11 @@ export function parseRepairWorkerResult(text: string, pr: number, head: string,
|
|
|
96
127
|
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
97
128
|
const v = value as RepairWorkerResult;
|
|
98
129
|
if (v.pr !== pr || typeof v.head !== 'string' || v.head.toLowerCase() !== head.toLowerCase() || v.runId !== runId || typeof v.ok !== 'boolean') return null;
|
|
130
|
+
if (v.failureSignature !== undefined && (typeof v.failureSignature !== 'string'
|
|
131
|
+
|| !/^(?:gate:sha256:[a-f0-9]{64}|provider:ambiguous-primary:[a-z0-9._/-]{1,120})$/.test(v.failureSignature))) delete v.failureSignature;
|
|
132
|
+
if (v.gateFailureTests !== undefined && (!v.failureSignature?.startsWith('gate:')
|
|
133
|
+
|| !Array.isArray(v.gateFailureTests) || v.gateFailureTests.length < 1 || v.gateFailureTests.length > 32
|
|
134
|
+
|| !v.gateFailureTests.every((test) => typeof test === 'string' && test.length > 0 && test.length <= 512))) delete v.gateFailureTests;
|
|
99
135
|
if (v.ok && (typeof v.artifactDir !== 'string' || !v.artifactDir.startsWith('/') || typeof v.job !== 'string' || !v.job
|
|
100
136
|
|| !v.result || v.result.pr !== pr || typeof v.result.baseHead !== 'string'
|
|
101
137
|
|| v.result.baseHead.toLowerCase() !== head.toLowerCase() || v.result.runId !== runId || !SHA40.test(v.result.commit)
|