elanous 0.2.29 → 0.2.32
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/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
- package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
- package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
- package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
- package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-c219f2ed171131be.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-04d00ae9b0890349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
- package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +26 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/bin/elanous.mjs +7 -3
- package/graphs/context/nightly-condense.yaml +1 -0
- package/graphs/implement-loop.yaml +5 -0
- package/graphs/intake/intake-daily.yaml +8 -1
- package/graphs/intake/recipes.yaml +5 -0
- package/graphs/lecture/lecture-note.yaml +2 -2
- package/graphs/ops/harness-gc.yaml +1 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +9 -5
- package/graphs/units/recipes.yaml +3 -0
- package/graphs/units/release-gate-recheck.yaml +15 -0
- package/package.json +2 -1
- package/scripts/check-native-tool-wiring.ts +3 -2
- package/scripts/ci-android-unit-tests.ts +16 -0
- package/scripts/ci-typecheck-changed.ts +63 -10
- package/scripts/coord-channel-watch.sh +22 -16
- package/scripts/coord-role-pack.ts +81 -2
- package/scripts/cron-run.ts +96 -3
- package/scripts/detect-test-interference.ts +38 -5
- package/scripts/gate-pr-cache.ts +65 -0
- package/scripts/gh-surface/capture.ts +126 -0
- package/scripts/gh-surface/gh +40 -0
- package/scripts/import-graph-scc.ts +38 -0
- package/scripts/install.ps1 +19 -0
- package/scripts/intake-social.ts +181 -0
- package/scripts/lecture-note/node.ts +71 -4
- package/scripts/lib/android-toolchain.ts +32 -0
- package/scripts/lib/deterministic-env.ts +62 -0
- package/scripts/lib/gate-test-env.ts +19 -0
- package/scripts/measure-goal-grounding-corpus.ts +2 -1
- package/scripts/measure-si-task-cpu.ts +143 -0
- package/scripts/ratchets/test-interference-patterns.allowlist.txt +255 -0
- package/scripts/ratchets/test-interference-patterns.ts +367 -0
- package/scripts/release-loop/cut-branch.ts +4 -3
- package/scripts/release-loop/export-check-node.ts +0 -1
- package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
- package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
- package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
- package/scripts/release-loop/gate-closure.ts +12 -8
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-host-mirror.ts +66 -0
- package/scripts/release-loop/gate-node.ts +523 -75
- package/scripts/release-loop/gate-partial.ts +106 -9
- package/scripts/release-loop/gate-pr-cache.ts +66 -0
- package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
- package/scripts/release-loop/gate-r2-verdict.ts +189 -0
- package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
- package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
- package/scripts/release-loop/import-graph-scc-run.ts +54 -0
- package/scripts/release-loop/import-graph-scc.ts +215 -0
- package/scripts/release-loop/node-verdict.ts +2 -0
- package/scripts/release-loop/prepare-node.ts +102 -4
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
- package/scripts/release-loop/resume-release.ts +33 -4
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/spawn-lane.ts +2 -19
- package/scripts/release-loop/tui-sim-node.ts +3 -2
- package/scripts/release-loop/unattended-release.ts +16 -0
- package/scripts/test-deterministic.ts +5 -61
- package/scripts/train-reach-grouping.ts +48 -0
- package/scripts/tsc-incremental-cache.ts +86 -0
- package/scripts/tsc-incremental-diagnostics.ts +76 -0
- package/scripts/tsc-main-safety-net.ts +2 -2
- package/src/acp/client.ts +4 -1
- package/src/acp/core-turn-bridge.ts +65 -8
- package/src/acp/elanous-extensions.ts +3 -0
- package/src/acp/server.ts +3 -0
- package/src/acp/tool-trace.ts +186 -11
- package/src/ad-pipeline/run.ts +4 -2
- package/src/agent/runner.ts +169 -3
- package/src/agent/self-ambient-cache.ts +156 -0
- package/src/agent/self-ambient.ts +8 -1
- package/src/agent/subagent-callable.ts +3 -2
- package/src/agent/task-notification.ts +5 -0
- package/src/agent-mission/review-loop.ts +6 -3
- package/src/agent-substrate/acp-implementer.ts +14 -2
- package/src/agent-substrate/pr-reviewer.ts +14 -0
- package/src/agent-substrate/self-review-cli.ts +30 -4
- package/src/ask-user-question/tool.ts +22 -0
- package/src/autopilot/build/llm-conflict-merge.ts +56 -10
- package/src/autopilot/pr-manager.ts +80 -7
- package/src/briefing/brief-items.ts +24 -22
- package/src/capture/frame-state-detect.ts +39 -0
- package/src/capture/tui-self-report.ts +149 -6
- package/src/chat/chat-cli.ts +10 -2
- package/src/chat/index.ts +138 -26
- package/src/chat/input-control-key.ts +5 -3
- package/src/chat/pickers/modal-runtime.ts +6 -0
- package/src/chat/pickers/modals.ts +8 -2
- package/src/chat/tool-interrupt-behavior.ts +38 -0
- package/src/chat/tool-render/dispatch.ts +5 -1
- package/src/chat/turn-typeahead.ts +75 -20
- package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
- package/src/cli/agent-cli.ts +41 -13
- package/src/cli/ask-bare.ts +1 -0
- package/src/cli/config-audit.ts +123 -0
- package/src/cli/decisions-cli.ts +80 -6
- package/src/cli/import-cli.ts +12 -0
- package/src/cli/log-event-names.ts +17 -0
- package/src/cli/mcp-login.ts +21 -5
- package/src/cli/msg-cli.ts +89 -0
- package/src/cli/pod-cli.ts +14 -3
- package/src/cli/pr-cli.ts +273 -81
- package/src/cli/pr-land-base-read.ts +34 -0
- package/src/cli/pr-land-heavy-remote.ts +82 -26
- package/src/cli/pr-land-overlap-evidence.ts +109 -11
- package/src/cli/pr-land-pod-shadow-job.ts +106 -0
- package/src/cli/pr-land-pod-shadow.ts +16 -3
- package/src/cli/pr-land-refusal.ts +20 -5
- package/src/cli/pr-land-virtual-rebase.ts +108 -0
- package/src/cli/pty-takeover-cli.ts +88 -14
- package/src/cli/release-cli.ts +80 -14
- package/src/cli/seat-cli.ts +138 -3
- package/src/cli/self-update.ts +5 -2
- package/src/cli/sim-cli.ts +18 -0
- package/src/cli/tasks-cli.ts +97 -19
- package/src/context-bus/context-first.ts +13 -0
- package/src/context-bus/context-now.ts +13 -2
- package/src/context-bus/ops-events.ts +79 -0
- package/src/control-plane/lease-holder.ts +12 -8
- package/src/control-plane/ledger.ts +163 -4
- package/src/control-plane/server.ts +91 -11
- package/src/core-turn/run-core-turn.ts +2 -0
- package/src/core-turn/run-goal-loop.ts +243 -3
- package/src/core-turn/seat-turn-cap.ts +79 -0
- package/src/core-turn/short-question.ts +38 -6
- package/src/core-turn/types.ts +6 -0
- package/src/dashboard/acp-active-model.ts +42 -1
- package/src/dashboard/acp-boot.ts +3 -0
- package/src/dashboard/background-jobs-status.ts +66 -0
- package/src/dashboard/index.ts +339 -657
- package/src/dashboard/input/agent-wake.ts +242 -0
- package/src/dashboard/input/chat-main-entry-runtime.ts +6 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
- package/src/dashboard/input/chat-main-session.ts +8 -1
- package/src/dashboard/input/chat-main-turn.ts +12 -3
- package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
- package/src/dashboard/input/external-input-host.ts +49 -9
- package/src/dashboard/input/internal-turn.ts +261 -0
- package/src/dashboard/input/mouse-wiring.ts +108 -11
- package/src/dashboard/input/seat-autowake.ts +318 -0
- package/src/dashboard/input/turn-steer-bridge.ts +70 -0
- package/src/dashboard/log-click-runtime.ts +118 -2
- package/src/dashboard/loop-scheduler.ts +72 -0
- package/src/dashboard/seat-boot-preamble.ts +18 -0
- package/src/dashboard/skill-runtime.ts +2 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
- package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
- package/src/dashboard/slash-runtime/index.ts +13 -0
- package/src/dashboard/turn-busy-teardown.ts +50 -0
- package/src/dashboard/turn-preamble.ts +116 -40
- package/src/dashboard/turn-session-layers.ts +4 -2
- package/src/dashboard/turn-start-segments.ts +222 -0
- package/src/decisions/decision-ledger.ts +45 -4
- package/src/discord-self-message.ts +4 -4
- package/src/display/prompt-row-owner.ts +146 -0
- package/src/display/resize-listener.ts +33 -2
- package/src/domains/release-tool.ts +18 -1
- package/src/field-note/transcribe.ts +17 -0
- package/src/fold-stack.ts +4 -2
- package/src/git-fs/index.ts +263 -36
- package/src/github/remote-call.ts +81 -0
- package/src/goals/registry.ts +46 -6
- package/src/goals/types.ts +7 -1
- package/src/graph-runner/runner.ts +1 -0
- package/src/grok/credential.ts +26 -0
- package/src/harness/gate-reserve.ts +87 -0
- package/src/harness/harness-clean.ts +2 -1
- package/src/harness/harness-cli-command.ts +52 -5
- package/src/harness/harness-gc.ts +2 -1
- package/src/harness/harness-incidents.ts +70 -20
- package/src/harness/harness-pod-dispatch.ts +87 -10
- package/src/harness/harness-queue.ts +68 -4
- package/src/harness/harness-stop.ts +4 -3
- package/src/harness/harness-substrate-default.ts +78 -7
- package/src/harness/harness-worktree-auto.ts +2 -1
- package/src/harness/harness-worktrees.ts +3 -2
- package/src/hooks/dispatch.ts +2 -1
- package/src/index.ts +156 -27
- package/src/input/external-input-queue.ts +64 -7
- package/src/intake-plane/slash.ts +14 -3
- package/src/keybindings.ts +4 -1
- package/src/llm/route-decision.ts +36 -0
- package/src/llm/tool-loop-steered-rejection.ts +41 -0
- package/src/llm-request-shape.ts +209 -0
- package/src/llm.ts +301 -283
- package/src/loops/consensus.ts +348 -0
- package/src/loops/msg-wake.ts +206 -4
- package/src/loops/observe.ts +19 -3
- package/src/loops/orchestrator/tick.ts +88 -12
- package/src/loops/orchestrator/traffic.ts +64 -1
- package/src/loops/registry.ts +30 -0
- package/src/market/signed-index.ts +14 -0
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/mcp/mcp-oauth.ts +54 -5
- package/src/models/prompts.ts +28 -0
- package/src/msg/msg-sse-client.ts +223 -0
- package/src/msg/msg-store.ts +86 -2
- package/src/mss/logging/log-store.ts +225 -1
- package/src/mss/logging/render-categories.ts +5 -0
- package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
- package/src/nexus/api/http-server.ts +54 -15
- package/src/nexus/api/loop-resources.ts +19 -3
- package/src/nexus/api/ops-api.ts +11 -0
- package/src/nexus/daemon-thin-inventory.md +37 -0
- package/src/nexus/index.ts +70 -0
- package/src/nexus/state/state.ts +1 -0
- package/src/oauth/store.ts +32 -7
- package/src/onboarding/first-run.ts +28 -3
- package/src/ops/overview-cache.ts +16 -4
- package/src/ops/overview.ts +59 -2
- package/src/ops/resources.ts +82 -0
- package/src/plugins/maker/connector-maker.ts +41 -0
- package/src/plugins/maker/skill-maker.ts +42 -0
- package/src/pr-tool/census.ts +303 -0
- package/src/pr-tool/inflight-registry.ts +143 -0
- package/src/prompt-library/chat-conciseness.ts +13 -0
- package/src/prompt-library/universal-preamble.ts +10 -5
- package/src/pty-shell/pty-manifest.ts +12 -3
- package/src/pty-shell/tui-run-state.ts +34 -3
- package/src/release-loop/gate-host-reservation.ts +97 -0
- package/src/release-loop/landing-freeze.ts +5 -0
- package/src/release-loop/light-rc.ts +5 -2
- package/src/release-loop/placement.ts +92 -1
- package/src/release-loop/rehearsal-shard-plan.ts +149 -0
- package/src/release-loop/rehearsal.ts +73 -17
- package/src/repl/index.ts +20 -2
- package/src/seat-loop/seat-knowhow.ts +282 -0
- package/src/seat-loop/seat-loop.ts +41 -2
- package/src/seat-loop/traffic-signal.ts +5 -1
- package/src/self-dev/ask-launch-flow.ts +37 -3
- package/src/self-dev/decompose-compose-graph.ts +28 -27
- package/src/self-dev/decompose-proposal.ts +53 -38
- package/src/self-dev/decompose.ts +17 -0
- package/src/self-dev/dev-pipeline.ts +31 -2
- package/src/self-dev/draft-residue.ts +267 -33
- package/src/self-dev/draft-sweep.ts +59 -4
- package/src/self-dev/external-call-zero.ts +77 -0
- package/src/self-dev/launch-preflight-text.ts +6 -0
- package/src/self-dev/launch-preflight.ts +25 -3
- package/src/self-dev/local-supervisor-judge.ts +185 -0
- package/src/self-dev/run-supervisor.ts +229 -19
- package/src/self-dev/run-types.ts +20 -0
- package/src/self-dev/shard-aggregate.ts +13 -2
- package/src/self-dev/shard-plan.ts +56 -1
- package/src/self-dev/shard-run.ts +207 -12
- package/src/self-dev/spawn-lane-files.ts +19 -0
- package/src/self-implement/app-api-budget.ts +51 -11
- package/src/self-implement/config-gate.ts +2 -1
- package/src/self-implement/elanous-tui-spawn.ts +14 -0
- package/src/self-implement/expose-gate.ts +2 -1
- package/src/self-implement/follow-up-placement.ts +79 -0
- package/src/self-implement/gate-artifacts.ts +416 -0
- package/src/self-implement/gate-baseline.ts +96 -5
- package/src/self-implement/gate-cli.ts +207 -17
- package/src/self-implement/gate-remote.ts +136 -26
- package/src/self-implement/gate-scenario.ts +85 -0
- package/src/self-implement/goal-author.ts +160 -8
- package/src/self-implement/graph-authority.ts +38 -6
- package/src/self-implement/graph-overlay-condition.ts +92 -1
- package/src/self-implement/heal-triage.ts +79 -0
- package/src/self-implement/host-regate.ts +97 -7
- package/src/self-implement/orchestrator.ts +115 -134
- package/src/self-implement/pr-title.ts +123 -0
- package/src/self-implement/run-checkpoint.ts +235 -0
- package/src/self-implement/run-ledger.ts +162 -15
- package/src/self-implement/run-stop.ts +4 -3
- package/src/self-implement/run-ttl.ts +28 -4
- package/src/self-implement/seams.ts +2 -0
- package/src/self-implement/shadow-stage.ts +7 -6
- package/src/self-implement/stop-autoheal.ts +2 -1
- package/src/self-implement/train-gate-remote.ts +37 -8
- package/src/self-implement/train-reach-grouping.ts +157 -0
- package/src/self-implement/train-scenario-layers.ts +133 -0
- package/src/self-implement/uncommitted-work.ts +2 -0
- package/src/session/pending-input.ts +19 -0
- package/src/session/session-start.ts +224 -0
- package/src/session-runtime/index.ts +22 -267
- package/src/session-runtime/parallel-dispatch.ts +22 -5
- package/src/shell-runner/background-surface.ts +15 -5
- package/src/skills/tools/agent.ts +39 -6
- package/src/skills/tools/dev-harness.ts +6 -4
- package/src/skills/tools/list-dir.ts +11 -0
- package/src/skills/tools/schedule-wakeup.ts +408 -0
- package/src/skills/tools/shell.ts +246 -4
- package/src/status/bar.ts +26 -0
- package/src/steward/digest-delivery.ts +118 -0
- package/src/steward/hold-hygiene.ts +120 -0
- package/src/steward/resync-tick.ts +114 -23
- package/src/steward/ta-repair-event-collect.ts +158 -0
- package/src/steward/triage.ts +10 -0
- package/src/surface/shell-runner-boot.ts +5 -2
- package/src/task-agent/card-evidence.ts +25 -1
- package/src/task-agent/green-sweep.ts +8 -3
- package/src/task-agent/judge.ts +76 -0
- package/src/task-agent/land-queue.ts +79 -0
- package/src/task-agent/live-moves.ts +30 -9
- package/src/task-agent/postland-card.ts +5 -0
- package/src/task-agent/prelaunch-already-done.ts +98 -0
- package/src/task-agent/real-launch-guard.ts +37 -0
- package/src/task-agent/rejudge-on-head.ts +89 -12
- package/src/task-agent/remote-rejudge-bind.ts +28 -8
- package/src/task-agent/repair-cycle.ts +45 -7
- package/src/task-agent/repair-worker.ts +7 -0
- package/src/task-agent/run-identity.ts +200 -0
- package/src/task-agent/shadow.ts +50 -3
- package/src/task-agent/task-hand.ts +182 -5
- package/src/task-agent/train-landing.ts +77 -0
- package/src/task-agent/work-order.ts +104 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +151 -37
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
- package/src/task-orchestrator/surfaces/pod-lease.ts +118 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +3 -1
- package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
- package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +67 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
- package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +525 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +362 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +138 -19
- package/src/telegram.ts +2 -4
- package/src/tui/chat/execution-badge.ts +5 -1
- package/src/tui/input/pickers.ts +732 -0
- package/src/tui/input-lag-probe.ts +230 -0
- package/src/tui/slash/mission.ts +492 -0
- package/src/tui/slash/term.ts +877 -0
- package/src/tui-client/dashboard-session.ts +9 -0
- package/src/tui.ts +52 -0
- package/src/user-config/gemini-server-tools.ts +9 -0
- package/src/user-config.ts +53 -16
- package/src/util/spawn-sync-output.ts +7 -0
- package/src/ux-sim/fake-bin.ts +154 -0
- package/src/ux-sim/fake-clock.ts +36 -0
- package/src/ux-sim/headless-tui.ts +72 -0
- package/src/ux-sim/in-process-cli.ts +2 -1
- package/src/ux-sim/scenario.ts +255 -0
- package/src/ux-sim/temp-git-remote.ts +82 -0
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/vlog.ts +25 -7
- package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
- package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
- package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
- package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
- package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
- package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
- package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
- package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
- package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
- package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
- package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
- package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
- package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
- package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
- package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
- package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
- package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
- package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +0 -1
- /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_ssgManifest.js +0 -0
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Past `tools.selfImplement.runTtlHours` (default 24) since its last commit, the sweep makes one pre-emptive move:
|
|
6
6
|
* · live owning run → one resync memo in its control inbox (same path as SIBLING-RESYNC #24893/#24899),
|
|
7
7
|
* at most once per (PR, head sha) — a rebase moves the head and re-arms it
|
|
8
|
-
* · no live run → the registered `elanous:needs-rebase` label, once (QUIET-PR-COMMENTS: never a comment)
|
|
8
|
+
* · no live run → the registered `elanous:needs-rebase` label, once (QUIET-PR-COMMENTS: never a comment);
|
|
9
|
+
* when `requestRegate` is supplied, at most one of those stale PRs is also selected
|
|
10
|
+
* for a re-gate request (shadow: would-regate observation only; live: one call)
|
|
9
11
|
*
|
|
10
12
|
* Mode `tools.selfImplement.runTtl.mode`: `shadow` (default) only logs what it would do; `live` writes.
|
|
11
13
|
* Cost bound: a PR opened inside the TTL is still inside its own time-to-landing and is never fetched
|
|
@@ -63,6 +65,8 @@ export interface RunTtlResult {
|
|
|
63
65
|
readonly memo: readonly number[];
|
|
64
66
|
/** Label added (live) or would be added (shadow). */
|
|
65
67
|
readonly label: readonly number[];
|
|
68
|
+
/** Re-gate requested (live) or would be requested (shadow). Empty when the adapter is omitted. */
|
|
69
|
+
readonly regate: readonly number[];
|
|
66
70
|
readonly alreadyMarked: readonly number[];
|
|
67
71
|
readonly alreadyMemoed: readonly number[];
|
|
68
72
|
/** Owning run lookup failed — left alone (a failed lookup is not a dead run). */
|
|
@@ -109,6 +113,8 @@ export async function runRunTtlSweep(input: {
|
|
|
109
113
|
concurrency?: number;
|
|
110
114
|
now?: () => number;
|
|
111
115
|
log?: (category: string, event: string, data: Record<string, unknown>) => void;
|
|
116
|
+
/** Optional: among stale PRs with no live run, request a re-gate for at most one per sweep. */
|
|
117
|
+
requestRegate?: (pr: RunTtlCandidate) => Promise<void> | void;
|
|
112
118
|
}): Promise<RunTtlResult> {
|
|
113
119
|
const { adapters } = input;
|
|
114
120
|
const now = input.now ?? Date.now;
|
|
@@ -132,6 +138,7 @@ export async function runRunTtlSweep(input: {
|
|
|
132
138
|
const stale: number[] = [];
|
|
133
139
|
const memo: number[] = [];
|
|
134
140
|
const label: number[] = [];
|
|
141
|
+
const regate: number[] = [];
|
|
135
142
|
const alreadyMarked: number[] = [];
|
|
136
143
|
const alreadyMemoed: number[] = [];
|
|
137
144
|
const unresolved: number[] = [];
|
|
@@ -139,17 +146,17 @@ export async function runRunTtlSweep(input: {
|
|
|
139
146
|
const skippedFetchCap: number[] = [];
|
|
140
147
|
const failed: number[] = [];
|
|
141
148
|
const result = (reason?: string): RunTtlResult => ({
|
|
142
|
-
mode, ttlHours, considered, freshByCreation, fetched, fresh, unknown, stale, memo, label, alreadyMarked,
|
|
149
|
+
mode, ttlHours, considered, freshByCreation, fetched, fresh, unknown, stale, memo, label, regate, alreadyMarked,
|
|
143
150
|
alreadyMemoed, unresolved, skippedOverCap, skippedFetchCap, failed, durationMs: Math.max(0, now() - startedAt),
|
|
144
151
|
...(reason ? { reason } : {}),
|
|
145
152
|
});
|
|
146
153
|
const summary = (out: RunTtlResult): RunTtlResult => {
|
|
147
154
|
emit('summary', {
|
|
148
155
|
ttlHours, cap, maxFetch, concurrency, considered, freshByCreation, fetched, fresh,
|
|
149
|
-
unknown: unknown.length, stale: stale.length, memo: memo.length, label: label.length,
|
|
156
|
+
unknown: unknown.length, stale: stale.length, memo: memo.length, label: label.length, regate: regate.length,
|
|
150
157
|
alreadyMarked: alreadyMarked.length, alreadyMemoed: alreadyMemoed.length, unresolved: unresolved.length,
|
|
151
158
|
skippedOverCap: skippedOverCap.length, skippedFetchCap: skippedFetchCap.length, failed: failed.length,
|
|
152
|
-
memoPrs: memo, labelPrs: label, durationMs: out.durationMs, ...(out.reason ? { reason: out.reason } : {}),
|
|
159
|
+
memoPrs: memo, labelPrs: label, regatePrs: regate, durationMs: out.durationMs, ...(out.reason ? { reason: out.reason } : {}),
|
|
153
160
|
});
|
|
154
161
|
return out;
|
|
155
162
|
};
|
|
@@ -200,6 +207,7 @@ export async function runRunTtlSweep(input: {
|
|
|
200
207
|
}
|
|
201
208
|
stalePrs.sort((a, b) => b.ageMs - a.ageMs || a.pr.number - b.pr.number);
|
|
202
209
|
let actions = 0;
|
|
210
|
+
let selectedRegate = false;
|
|
203
211
|
for (const { pr, target, ageMs } of stalePrs) {
|
|
204
212
|
const ageHours = ageMs / 3_600_000;
|
|
205
213
|
const key = `${pr.number}:${pr.headSha}`;
|
|
@@ -240,9 +248,15 @@ export async function runRunTtlSweep(input: {
|
|
|
240
248
|
}
|
|
241
249
|
}
|
|
242
250
|
const reason = target.alive ? 'memo-failed' : target.reason;
|
|
251
|
+
const canRegate = Boolean(input.requestRegate) && !target.alive && !selectedRegate;
|
|
243
252
|
if (mode === 'shadow') {
|
|
244
253
|
label.push(pr.number);
|
|
245
254
|
emit('would-label', { pr: pr.number, label: RUN_TTL_MARKER_LABEL, reason, ageHours: Math.floor(ageHours) });
|
|
255
|
+
if (canRegate) {
|
|
256
|
+
selectedRegate = true;
|
|
257
|
+
regate.push(pr.number);
|
|
258
|
+
emit('would-regate', { pr: pr.number, reason, ageHours: Math.floor(ageHours) });
|
|
259
|
+
}
|
|
246
260
|
continue;
|
|
247
261
|
}
|
|
248
262
|
try {
|
|
@@ -253,6 +267,16 @@ export async function runRunTtlSweep(input: {
|
|
|
253
267
|
failed.push(pr.number);
|
|
254
268
|
emit('label-failed', { pr: pr.number, error: String(error) });
|
|
255
269
|
}
|
|
270
|
+
if (canRegate) {
|
|
271
|
+
selectedRegate = true;
|
|
272
|
+
try {
|
|
273
|
+
await input.requestRegate!(pr);
|
|
274
|
+
regate.push(pr.number);
|
|
275
|
+
emit('regate-requested', { pr: pr.number, reason, ageHours: Math.floor(ageHours) });
|
|
276
|
+
} catch (error) {
|
|
277
|
+
emit('regate-failed', { pr: pr.number, error: String(error) });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
256
280
|
}
|
|
257
281
|
return summary(result());
|
|
258
282
|
}
|
|
@@ -2493,6 +2493,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2493
2493
|
|
|
2494
2494
|
openPr: async ({ title, body, head, base, draft, labels, cwd }) => {
|
|
2495
2495
|
const resolvedBase = assertBaseBranchOnOrigin(cwd, base);
|
|
2496
|
+
const harnessSeat = process.env.ELANOUS_HARNESS_SEAT;
|
|
2496
2497
|
const outcome = (o.prManager ?? makePrManager()).upsertPr({
|
|
2497
2498
|
branch: head,
|
|
2498
2499
|
worktreePath: cwd,
|
|
@@ -2501,6 +2502,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2501
2502
|
commitMessage: title,
|
|
2502
2503
|
...(resolvedBase ? { base: resolvedBase } : {}),
|
|
2503
2504
|
...(draft !== undefined ? { draft } : {}),
|
|
2505
|
+
...(harnessSeat === 'OP' || harnessSeat === 'TC' || harnessSeat === 'MK' || harnessSeat === 'UX' ? { seat: harnessSeat } : {}),
|
|
2504
2506
|
// BENCH-ISOLATED-ARMS ② — base 가 `bench/<id>/base` 면 라벨 `elanous:bench` 를 더한다.
|
|
2505
2507
|
...(() => {
|
|
2506
2508
|
const all = benchIdFromBase(resolvedBase) && !labels?.includes(BENCH_LABEL) ? [...(labels ?? []), BENCH_LABEL] : labels;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// 배선은 P4(현재 비-git 은 front door 에서 refuse 유지 → 이 적용 경로는 프로덕션 미도달).
|
|
11
11
|
|
|
12
12
|
import { spawnSync } from 'node:child_process';
|
|
13
|
+
import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
|
|
13
14
|
import { cpSync, existsSync, statSync } from 'node:fs';
|
|
14
15
|
import { tmpdir } from 'node:os';
|
|
15
16
|
import { basename, dirname, join } from 'node:path';
|
|
@@ -49,7 +50,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
|
|
|
49
50
|
const slug = basename(target).replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
50
51
|
const shadowPath = join(tmpdir(), `elanous-shadow-${slug}-${process.pid}`);
|
|
51
52
|
// 이전 세대 잔여 정리(고아 방지·createWorktree resetExisting 정합).
|
|
52
|
-
try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
|
|
53
|
+
try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
|
|
53
54
|
|
|
54
55
|
// ② 대상 → 그림자 복사(내용 전체·심볼릭 보존 X: cpSync 기본).
|
|
55
56
|
cpSync(target, shadowPath, { recursive: true });
|
|
@@ -69,7 +70,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
|
|
|
69
70
|
path: shadowPath,
|
|
70
71
|
branch,
|
|
71
72
|
base,
|
|
72
|
-
cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
|
|
73
|
+
cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -94,9 +95,9 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
|
|
|
94
95
|
const fileName = basename(target);
|
|
95
96
|
const slug = fileName.replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
96
97
|
const shadowPath = join(tmpdir(), `elanous-shadow-file-${slug}-${process.pid}`);
|
|
97
|
-
try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
|
|
98
|
+
try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
|
|
98
99
|
|
|
99
|
-
spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS });
|
|
100
|
+
spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
100
101
|
cpSync(target, join(shadowPath, fileName));
|
|
101
102
|
|
|
102
103
|
git(shadowPath, ['init', '-b', 'shadow-base']);
|
|
@@ -113,7 +114,7 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
|
|
|
113
114
|
fileName,
|
|
114
115
|
branch,
|
|
115
116
|
base,
|
|
116
|
-
cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
|
|
117
|
+
cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
|
|
117
118
|
};
|
|
118
119
|
}
|
|
119
120
|
|
|
@@ -166,7 +167,7 @@ export function applyShadowToTarget(opts: { shadowPath: string; target: string;
|
|
|
166
167
|
debug.log('harness.target', 'apply.backup', { target: target.slice(-48), backup: backup.slice(-48) });
|
|
167
168
|
|
|
168
169
|
// ② rsync 미러링(--delete·그림자 git 메타 제외). rsync 부재 = fail-closed(백업만 남기고 미적용).
|
|
169
|
-
const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000 });
|
|
170
|
+
const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
170
171
|
if (probe.status !== 0) {
|
|
171
172
|
debug.log('harness.target', 'apply.no-rsync', { target: target.slice(-48) });
|
|
172
173
|
return { backup, applied: false, log: 'rsync 미설치 → 적용 안 함(백업만 생성·fail-closed). 수동 적용 필요.' };
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* main-sync → rebase-regate 리베이스(MERGE-INTENT-RESOLVE 의도 해석) 뒤 재게이트
|
|
14
14
|
* pod-died → resume-from-salvage `salvage/run-<6hex>/<leaf>` 가지에서 resume(DRAFT-NOT-ARCHIVE)
|
|
15
15
|
* evidence-uncovered → derive-evidence-rejudge 런 출력·시험·배선에서 증거를 끌어내 1회 재판정
|
|
16
|
-
* review-repeat · review-out-of-scope · fabric · launch-failed · unclassified → needs-owner(새 라운드 없음)
|
|
16
|
+
* review-repeat · review-out-of-scope · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
|
|
17
17
|
*
|
|
18
18
|
* 사다리의 «출처»: `graphs/overlays/stop-heal-ladder.yaml` 이 갈래마다 처방 노드(id = 처방 이름)를 선언한다.
|
|
19
19
|
* 그 갈래에 얹힌 오버레이가 더한 노드 id 가 처방이다(source='graph'). 선언이 없거나 못 읽으면
|
|
@@ -52,6 +52,7 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
|
|
|
52
52
|
'review-out-of-scope': 'needs-owner',
|
|
53
53
|
fabric: 'needs-owner',
|
|
54
54
|
'launch-failed': 'needs-owner',
|
|
55
|
+
'gate-failed': 'needs-owner',
|
|
55
56
|
unclassified: 'needs-owner',
|
|
56
57
|
};
|
|
57
58
|
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Unlike `dispatchHeavyCheck` it never falls back to a local run: a busy host or an infra failure is «unmeasured».
|
|
4
4
|
* The only local commands are git (cat-file · rev-parse · push · diff). */
|
|
5
5
|
import { debug } from '../debug/log.js';
|
|
6
|
+
import { parseGateScenario, readGateScenarioFile } from './gate-scenario.js';
|
|
6
7
|
import { getDefaultLogStore } from '../mss/logging/log-store.js';
|
|
7
8
|
import {
|
|
8
|
-
realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
|
|
9
|
+
gateRemoteHostCap, realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
|
|
9
10
|
type GateRemoteRunner, type GateRemoteSettings, type RemoteRunOutcome,
|
|
10
11
|
} from './gate-remote.js';
|
|
11
12
|
|
|
@@ -21,6 +22,9 @@ export interface TrainGateInput {
|
|
|
21
22
|
changedFiles: readonly string[];
|
|
22
23
|
/** Paths deleted by the integration commit — kept in `changedFiles` for tsc/PWA reach, never run as tests. */
|
|
23
24
|
deletedFiles?: readonly string[];
|
|
25
|
+
/** Optional v0 JSON scenario. Selected tests are additive; invalid input is unmeasured. */
|
|
26
|
+
scenario?: unknown;
|
|
27
|
+
scenarioFile?: string;
|
|
24
28
|
settings?: GateRemoteSettings;
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -42,9 +46,10 @@ const quote = (value: string) => `'${value.replaceAll("'", `'\\''`)}'`;
|
|
|
42
46
|
const TEST_FILE = /\.test\.[cm]?[jt]sx?$/;
|
|
43
47
|
|
|
44
48
|
/** The host-side shell body: each step runs only if the one before it passed. Exported for tests. */
|
|
45
|
-
export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set()): string {
|
|
49
|
+
export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set(), scenarioTests: readonly string[] = []): string {
|
|
46
50
|
// A deleted test file is a changed path (tsc/PWA reach) but not something to run.
|
|
47
|
-
const
|
|
51
|
+
const changedTests = changedFiles.filter((file) => TEST_FILE.test(file) && !deleted.has(file));
|
|
52
|
+
const tests = scenarioTests.length ? [...new Set([...changedTests, ...scenarioTests])] : changedTests;
|
|
48
53
|
const steps = [
|
|
49
54
|
`TSC_BASE_REF=${quote(baseSha)} bun scripts/ci-typecheck-changed.ts --local`,
|
|
50
55
|
...(tests.length ? [`bun run test:deterministic ${tests.map(quote).join(' ')}`] : []),
|
|
@@ -72,6 +77,30 @@ export const TRAIN_GATE_HOST = 'node-b';
|
|
|
72
77
|
export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): Promise<TrainGateResult> {
|
|
73
78
|
const settings = input.settings ?? await loadSettings();
|
|
74
79
|
const host = settings.host;
|
|
80
|
+
const hostCap = gateRemoteHostCap(settings, host);
|
|
81
|
+
let scenarioTests: string[] = [];
|
|
82
|
+
if (input.scenario !== undefined || input.scenarioFile !== undefined) {
|
|
83
|
+
try {
|
|
84
|
+
if (input.scenario !== undefined && input.scenarioFile !== undefined) throw new Error('choose scenario or scenarioFile');
|
|
85
|
+
const scenario = parseGateScenario(input.scenarioFile === undefined ? input.scenario : readGateScenarioFile(input.scenarioFile), { baseSha: input.baseSha, headSha: input.commit, changedFiles: input.changedFiles });
|
|
86
|
+
if (scenario.selectedTests.some(({ path }) => input.deletedFiles?.includes(path))) throw new Error('selected test deleted');
|
|
87
|
+
scenarioTests = scenario.selectedTests.map(({ path }) => path);
|
|
88
|
+
// The remote checks out this exact commit. Verify every path against its tree locally before spending a host slot.
|
|
89
|
+
for (const path of scenarioTests) {
|
|
90
|
+
const file = runner.local('git', ['cat-file', '-e', `${input.commit}:${path}`], input.repo);
|
|
91
|
+
if (file.rc !== 0 || file.error) throw new Error(`selected test missing at head: ${path}`);
|
|
92
|
+
const tree = runner.local('git', ['ls-tree', '-z', input.commit, '--', path], input.repo);
|
|
93
|
+
if (tree.rc !== 0 || tree.error || !/^100(?:644|755) blob [0-9a-f]{40}\t/.test(tree.stdout)
|
|
94
|
+
|| !tree.stdout.endsWith(`\t${path}\0`)) throw new Error(`selected test is not a regular file at head: ${path}`);
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
98
|
+
const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason, changedFiles: input.changedFiles.length };
|
|
99
|
+
debug.log('merge-queue', 'train-gate', entry);
|
|
100
|
+
try { (deps.observe ?? defaultObserve)(entry); } catch { /* observation only */ }
|
|
101
|
+
return { outcome: 'unmeasured', host, reason };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
75
104
|
if (host !== TRAIN_GATE_HOST) {
|
|
76
105
|
const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason: `host-not-gate-host (${host} ≠ ${TRAIN_GATE_HOST})`, changedFiles: input.changedFiles.length };
|
|
77
106
|
debug.log('merge-queue', 'train-gate', entry);
|
|
@@ -81,13 +110,13 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
|
|
|
81
110
|
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
82
111
|
const now = deps.now ?? Date.now;
|
|
83
112
|
const deadline = now() + settings.slotWaitSeconds * 1000;
|
|
84
|
-
const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []));
|
|
113
|
+
const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []), scenarioTests);
|
|
85
114
|
let outcome: RemoteRunOutcome;
|
|
86
115
|
for (;;) {
|
|
87
116
|
try {
|
|
88
117
|
outcome = runOnRemote({
|
|
89
118
|
repo: input.repo, host, mirror: settings.mirror, commit: input.commit, refs: [input.baseSha],
|
|
90
|
-
argv: ['sh', '-c', script], installPwa: true, hostCap
|
|
119
|
+
argv: ['sh', '-c', script], installPwa: true, hostCap,
|
|
91
120
|
}, runner);
|
|
92
121
|
} catch (error) {
|
|
93
122
|
outcome = { kind: 'infra', reason: `exception: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -100,7 +129,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
|
|
|
100
129
|
}
|
|
101
130
|
const result: TrainGateResult = outcome.kind === 'ran'
|
|
102
131
|
? { outcome: outcome.rc === 0 ? 'pass' : 'fail', host, ms: outcome.ms, rc: outcome.rc }
|
|
103
|
-
: { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (
|
|
132
|
+
: { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (occupied ${outcome.occupied ?? 'unknown'}/${hostCap}, held for ${settings.slotWaitSeconds}s)` : outcome.reason };
|
|
104
133
|
const entry: TrainGateObservation = {
|
|
105
134
|
host, commit: input.commit, baseSha: input.baseSha, outcome: result.outcome,
|
|
106
135
|
rc: result.rc, ms: result.ms, reason: result.reason, changedFiles: input.changedFiles.length,
|
|
@@ -116,7 +145,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
|
|
|
116
145
|
* integration commit's diff against `baseSha` (local git only); a diff failure is «unmeasured», never a local run. */
|
|
117
146
|
export type TrainGate = (commitSha: string, prNumbers: readonly number[]) => Promise<TrainGateOutcome>;
|
|
118
147
|
|
|
119
|
-
export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
|
|
148
|
+
export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings; scenario?: unknown; scenarioFile?: string }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
|
|
120
149
|
const unmeasured = (commitSha: string, reason: string): 'unmeasured' => {
|
|
121
150
|
const entry: TrainGateObservation = { host: opts.settings?.host ?? TRAIN_GATE_HOST, commit: commitSha, baseSha: opts.baseSha, outcome: 'unmeasured', reason, changedFiles: 0 };
|
|
122
151
|
debug.log('merge-queue', 'train-gate', entry);
|
|
@@ -128,7 +157,7 @@ export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?
|
|
|
128
157
|
const diff = runner.local('git', ['diff', '--name-status', '-z', opts.baseSha, commitSha], opts.repo);
|
|
129
158
|
if (diff.rc !== 0 || diff.error) return unmeasured(commitSha, 'changed-files-unavailable');
|
|
130
159
|
const { changedFiles, deletedFiles } = parseNameStatus(diff.stdout);
|
|
131
|
-
return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings }, runner, deps)).outcome;
|
|
160
|
+
return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings, scenario: opts.scenario, scenarioFile: opts.scenarioFile }, runner, deps)).outcome;
|
|
132
161
|
} catch (error) {
|
|
133
162
|
// Any preparation failure (local git spawn, parse, settings) is «unmeasured» — never a rejected promise, never a local run.
|
|
134
163
|
return unmeasured(commitSha, `prepare-failed: ${error instanceof Error ? error.message : String(error)}`.slice(0, 200));
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
|
|
3
|
+
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { selectGateTestFiles } from './gate-cli.js';
|
|
5
|
+
|
|
6
|
+
export interface TrainReachCandidate {
|
|
7
|
+
pr: string;
|
|
8
|
+
headSha: string;
|
|
9
|
+
tree: string;
|
|
10
|
+
changedFiles: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TrainReachInput {
|
|
14
|
+
version: 1;
|
|
15
|
+
baseSha: string;
|
|
16
|
+
queueSig: string;
|
|
17
|
+
prs: TrainReachCandidate[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface TrainReachObservation {
|
|
21
|
+
changedFiles: readonly string[];
|
|
22
|
+
testFiles: readonly string[];
|
|
23
|
+
unverified: readonly string[];
|
|
24
|
+
unrunImporterTotal: number | null;
|
|
25
|
+
lookupFailed?: string;
|
|
26
|
+
routeLookupFailures: readonly { source: string; reason: string }[];
|
|
27
|
+
callerTestsOverflow: readonly { file: string }[];
|
|
28
|
+
alwaysIncludeMissing: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TrainReachGroup {
|
|
32
|
+
prs: string[];
|
|
33
|
+
reachTests: string[];
|
|
34
|
+
interactionTests: string[];
|
|
35
|
+
overlapEdges: Array<{ a: string; b: string; tests: string[]; paths: string[] }>;
|
|
36
|
+
status: 'measured' | 'unmeasured';
|
|
37
|
+
capacityBlocked: boolean;
|
|
38
|
+
reasons: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TrainReachDecision {
|
|
42
|
+
version: 1;
|
|
43
|
+
baseSha: string;
|
|
44
|
+
queueSig: string;
|
|
45
|
+
parallelSafe: boolean;
|
|
46
|
+
groups: TrainReachGroup[];
|
|
47
|
+
deferred: Array<{ pr: string; reason: string }>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type InspectCandidate = (candidate: TrainReachCandidate, baseSha: string) => TrainReachObservation;
|
|
51
|
+
|
|
52
|
+
const SHA40 = /^[a-f0-9]{40}$/i;
|
|
53
|
+
const SHA256 = /^[a-f0-9]{64}$/i;
|
|
54
|
+
const safePath = (path: string) => path.length > 0 && !path.startsWith('/')
|
|
55
|
+
&& !path.includes('\\') && !/[\x00-\x1f\x7f]/.test(path)
|
|
56
|
+
&& !path.split('/').some((part) => part === '..' || part === '.');
|
|
57
|
+
const sortedUnique = (values: readonly string[]) => [...new Set(values)].sort();
|
|
58
|
+
|
|
59
|
+
function git(tree: string, ...args: string[]): string {
|
|
60
|
+
const result = spawnSync('git', args, { cwd: tree, encoding: 'utf8', timeout: 15_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
61
|
+
if (result.status !== 0 || result.error) {
|
|
62
|
+
throw new Error(`git ${args[0]} unmeasured: ${result.error?.message ?? result.stderr?.trim() ?? `rc=${result.status}`}`);
|
|
63
|
+
}
|
|
64
|
+
return result.stdout.trim();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The selector's own base...HEAD comparison is independently checked against the queue snapshot. */
|
|
68
|
+
function inspectTrainReachCandidate(candidate: TrainReachCandidate, baseSha: string): TrainReachObservation {
|
|
69
|
+
if (git(candidate.tree, 'rev-parse', 'HEAD').toLowerCase() !== candidate.headSha.toLowerCase()) {
|
|
70
|
+
throw new Error('tree HEAD differs from queued headSha');
|
|
71
|
+
}
|
|
72
|
+
if (git(candidate.tree, 'status', '--porcelain=v1')) throw new Error('tree is dirty');
|
|
73
|
+
git(candidate.tree, 'cat-file', '-e', `${baseSha}^{commit}`);
|
|
74
|
+
const observation = selectGateTestFiles(candidate.tree, { base: baseSha, includeImporterTests: true });
|
|
75
|
+
if (git(candidate.tree, 'rev-parse', 'HEAD').toLowerCase() !== candidate.headSha.toLowerCase()) {
|
|
76
|
+
throw new Error('tree HEAD changed during reach selection');
|
|
77
|
+
}
|
|
78
|
+
if (git(candidate.tree, 'status', '--porcelain=v1')) throw new Error('tree changed during reach selection');
|
|
79
|
+
return observation;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function validateInput(input: TrainReachInput): void {
|
|
83
|
+
if (input?.version !== 1 || !SHA40.test(input.baseSha) || !SHA256.test(input.queueSig) || !Array.isArray(input.prs)) {
|
|
84
|
+
throw new Error('train reach input identity unmeasured');
|
|
85
|
+
}
|
|
86
|
+
const seen = new Set<string>();
|
|
87
|
+
for (const candidate of input.prs) {
|
|
88
|
+
if (!/^[1-9]\d*$/.test(candidate?.pr) || seen.has(candidate.pr) || !SHA40.test(candidate.headSha)
|
|
89
|
+
|| !isAbsolute(candidate.tree) || !Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0
|
|
90
|
+
|| !candidate.changedFiles.every((path) => typeof path === 'string' && safePath(path))) {
|
|
91
|
+
throw new Error(`train reach candidate invalid: ${candidate?.pr ?? 'unknown'}`);
|
|
92
|
+
}
|
|
93
|
+
seen.add(candidate.pr);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Pure grouping after one independently measured selector observation per queued PR. */
|
|
98
|
+
export function buildTrainReachDecision(input: TrainReachInput, inspect: InspectCandidate = inspectTrainReachCandidate): TrainReachDecision {
|
|
99
|
+
validateInput(input);
|
|
100
|
+
const measured: Array<{ candidate: TrainReachCandidate; tests: string[]; files: string[] }> = [];
|
|
101
|
+
const deferred: TrainReachDecision['deferred'] = [];
|
|
102
|
+
for (const candidate of input.prs) {
|
|
103
|
+
try {
|
|
104
|
+
const observed = inspect(candidate, input.baseSha);
|
|
105
|
+
const actual = sortedUnique(observed.changedFiles);
|
|
106
|
+
const expected = sortedUnique(candidate.changedFiles);
|
|
107
|
+
if (actual.length !== expected.length || actual.some((path, index) => path !== expected[index])) {
|
|
108
|
+
throw new Error('changedFiles differ from selector observation');
|
|
109
|
+
}
|
|
110
|
+
if (observed.lookupFailed || observed.routeLookupFailures.length || observed.unrunImporterTotal !== 0
|
|
111
|
+
|| observed.callerTestsOverflow.length || observed.alwaysIncludeMissing.length || observed.unverified.length) {
|
|
112
|
+
throw new Error('test selection has unmeasured reach');
|
|
113
|
+
}
|
|
114
|
+
if (!observed.testFiles.every(safePath)) throw new Error('selected test path invalid');
|
|
115
|
+
measured.push({ candidate, tests: sortedUnique(observed.testFiles), files: sortedUnique(observed.changedFiles) });
|
|
116
|
+
} catch (error) {
|
|
117
|
+
deferred.push({ pr: candidate.pr, reason: error instanceof Error ? error.message : String(error) });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const parent = measured.map((_, index) => index);
|
|
122
|
+
const find = (index: number): number => {
|
|
123
|
+
while (parent[index] !== index) index = parent[index] = parent[parent[index]];
|
|
124
|
+
return index;
|
|
125
|
+
};
|
|
126
|
+
const edges: Array<{ left: number; right: number; tests: string[]; paths: string[] }> = [];
|
|
127
|
+
for (let left = 0; left < measured.length; left++) {
|
|
128
|
+
for (let right = left + 1; right < measured.length; right++) {
|
|
129
|
+
const tests = measured[left].tests.filter((path) => measured[right].tests.includes(path));
|
|
130
|
+
const paths = measured[left].files.filter((path) => measured[right].files.includes(path));
|
|
131
|
+
if (!tests.length && !paths.length) continue;
|
|
132
|
+
edges.push({ left, right, tests, paths });
|
|
133
|
+
parent[find(right)] = find(left);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const components = new Map<number, number[]>();
|
|
137
|
+
for (let index = 0; index < measured.length; index++) {
|
|
138
|
+
const root = find(index);
|
|
139
|
+
components.set(root, [...(components.get(root) ?? []), index]);
|
|
140
|
+
}
|
|
141
|
+
const groups = [...components.values()].map((indices): TrainReachGroup => {
|
|
142
|
+
const prs = indices.map((index) => measured[index].candidate.pr);
|
|
143
|
+
const counts = new Map<string, number>();
|
|
144
|
+
for (const index of indices) for (const test of measured[index].tests) counts.set(test, (counts.get(test) ?? 0) + 1);
|
|
145
|
+
const reachTests = sortedUnique([...counts.keys()]);
|
|
146
|
+
const interactionTests = reachTests.filter((test) => (counts.get(test) ?? 0) > 1);
|
|
147
|
+
const overlapEdges = edges.filter(({ left, right }) => indices.includes(left) && indices.includes(right))
|
|
148
|
+
.map(({ left, right, tests, paths }) => ({ a: measured[left].candidate.pr, b: measured[right].candidate.pr, tests, paths }));
|
|
149
|
+
const capacityBlocked = indices.length > 5;
|
|
150
|
+
const reasons = capacityBlocked ? ['connected reach group exceeds five PR train limit'] : [];
|
|
151
|
+
return { prs, reachTests, interactionTests, overlapEdges,
|
|
152
|
+
status: 'measured', capacityBlocked, reasons };
|
|
153
|
+
});
|
|
154
|
+
return { version: 1, baseSha: input.baseSha, queueSig: input.queueSig,
|
|
155
|
+
parallelSafe: deferred.length === 0 && groups.every(({ status, capacityBlocked }) => status === 'measured' && !capacityBlocked),
|
|
156
|
+
groups, deferred };
|
|
157
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { isGateSpawnLaneFile } from '../self-dev/spawn-lane-files.js';
|
|
4
|
+
import { isTestPath } from './importer-test-index.js';
|
|
5
|
+
import type { TrainReachDecision, TrainReachInput } from './train-reach-grouping.js';
|
|
6
|
+
|
|
7
|
+
export interface TrainRiskEvidence {
|
|
8
|
+
/** Only evidence-backed paths; an empty list asserts no known hot paths for this queue. */
|
|
9
|
+
verifiedHotFiles: Array<{ path: string; evidence: string }>;
|
|
10
|
+
/** Both endpoints are test paths; evidence must describe a reproduced interaction. */
|
|
11
|
+
verifiedInterferencePairs: Array<{ a: string; b: string; evidence: string }>;
|
|
12
|
+
/** Unreproduced pairs remain visible and prohibit parallel apply when either endpoint is reached. */
|
|
13
|
+
suspectedPairs: Array<{ a: string; b: string; reason: string }>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TrainScenarioGroup {
|
|
17
|
+
prs: string[];
|
|
18
|
+
reachTests: string[];
|
|
19
|
+
interactionTests: string[];
|
|
20
|
+
riskTests: string[];
|
|
21
|
+
riskReasons: Array<{ test: string; reason: string; evidence: string }>;
|
|
22
|
+
groupRiskReasons: Array<{ reason: string; evidence: string }>;
|
|
23
|
+
canaryTests: string[];
|
|
24
|
+
scenarioTests: string[];
|
|
25
|
+
populationSize: number;
|
|
26
|
+
eligiblePopulationSize: number;
|
|
27
|
+
canaryTarget: number;
|
|
28
|
+
/** Reproducible SHA-256 input prefix: baseSha, queueSig, and sorted PRs separated by NUL. */
|
|
29
|
+
canarySelectionKey: string;
|
|
30
|
+
canaryHashMethod: string;
|
|
31
|
+
unmeasured: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TrainScenarioDecision {
|
|
35
|
+
version: 1;
|
|
36
|
+
baseSha: string;
|
|
37
|
+
queueSig: string;
|
|
38
|
+
parallelSafe: boolean;
|
|
39
|
+
groups: TrainScenarioGroup[];
|
|
40
|
+
unmeasured: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const sorted = (paths: readonly string[]) => [...new Set(paths)].sort();
|
|
44
|
+
const validPath = (path: unknown): path is string => typeof path === 'string' && !!path && !path.startsWith('/') && !path.includes('\\')
|
|
45
|
+
&& !/[\x00-\x1f\x7f]/.test(path) && !path.split('/').some((part) => part === '.' || part === '..');
|
|
46
|
+
const hash = (value: string) => createHash('sha256').update(value).digest('hex');
|
|
47
|
+
|
|
48
|
+
/** Read the tracked test population from the pinned base commit, including paths containing spaces. */
|
|
49
|
+
export function readTrainTestPopulation(tree: string, baseSha: string): string[] {
|
|
50
|
+
if (!/^[a-f0-9]{40}$/i.test(baseSha)) throw new Error('invalid baseSha for test population');
|
|
51
|
+
const result = spawnSync('git', ['ls-tree', '-r', '-z', '--name-only', baseSha],
|
|
52
|
+
{ cwd: tree, encoding: 'utf8', timeout: 30_000, maxBuffer: 256 * 1024 * 1024 });
|
|
53
|
+
if (result.error || result.status !== 0) throw new Error(`test population unmeasured: ${result.error?.message ?? result.stderr?.trim() ?? result.status}`);
|
|
54
|
+
return sorted(result.stdout.split('\0').filter(isTestPath));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Pure scenario composition. No unverified hot path or interference guess is promoted to a verified risk. */
|
|
58
|
+
export function buildTrainScenarioDecision(
|
|
59
|
+
input: TrainReachInput, reach: TrainReachDecision, population: readonly string[], evidence: TrainRiskEvidence,
|
|
60
|
+
): TrainScenarioDecision {
|
|
61
|
+
if (reach.version !== 1 || reach.baseSha !== input.baseSha || reach.queueSig !== input.queueSig
|
|
62
|
+
|| !Array.isArray(population) || !population.every((path) => typeof path === 'string' && validPath(path) && isTestPath(path))
|
|
63
|
+
|| !evidence || !Array.isArray(evidence.verifiedHotFiles) || !Array.isArray(evidence.verifiedInterferencePairs)
|
|
64
|
+
|| !Array.isArray(evidence.suspectedPairs)) throw new Error('scenario identity or population unmeasured');
|
|
65
|
+
const tests = sorted(population);
|
|
66
|
+
const commonTests = new Set(tests);
|
|
67
|
+
const known = new Set([...tests, ...reach.groups.flatMap((group) => group.reachTests)]);
|
|
68
|
+
const validEvidence = (value: unknown): value is string => typeof value === 'string' && value.trim().length > 0;
|
|
69
|
+
for (const item of evidence.verifiedHotFiles) {
|
|
70
|
+
if (!validPath(item?.path) || !validEvidence(item?.evidence)) throw new Error('hot-file evidence unmeasured');
|
|
71
|
+
}
|
|
72
|
+
for (const item of [...evidence.verifiedInterferencePairs, ...evidence.suspectedPairs]) {
|
|
73
|
+
if (!validPath(item?.a) || !validPath(item?.b) || !known.has(item.a) || !known.has(item.b)
|
|
74
|
+
|| item.a === item.b || !validEvidence(item && 'evidence' in item ? item.evidence : item?.reason)) {
|
|
75
|
+
throw new Error('interference-pair evidence unmeasured');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const changedByPr = new Map(input.prs.map(({ pr, changedFiles }) => [pr, changedFiles]));
|
|
79
|
+
const groups = reach.groups.map((group): TrainScenarioGroup => {
|
|
80
|
+
const reached = new Set(group.reachTests);
|
|
81
|
+
if ([...reached].some((path) => !validPath(path) || !isTestPath(path))) throw new Error('reached test path invalid');
|
|
82
|
+
const riskReasons: TrainScenarioGroup['riskReasons'] = [];
|
|
83
|
+
const groupRiskReasons: TrainScenarioGroup['groupRiskReasons'] = [];
|
|
84
|
+
const unavailable: string[] = [];
|
|
85
|
+
const risk = new Set<string>();
|
|
86
|
+
const addRisk = (test: string, reason: string, source: string): void => {
|
|
87
|
+
risk.add(test);
|
|
88
|
+
riskReasons.push({ test, reason, evidence: source });
|
|
89
|
+
};
|
|
90
|
+
for (const test of reached) if (isGateSpawnLaneFile(test)) addRisk(test, 'spawn-lane', 'src/self-dev/spawn-lane-files.ts');
|
|
91
|
+
const changed = new Set(group.prs.flatMap((pr) => changedByPr.get(pr) ?? []));
|
|
92
|
+
for (const hot of evidence.verifiedHotFiles) if (changed.has(hot.path)) {
|
|
93
|
+
groupRiskReasons.push({ reason: `hot-file:${hot.path}`, evidence: hot.evidence });
|
|
94
|
+
}
|
|
95
|
+
for (const pair of evidence.verifiedInterferencePairs) {
|
|
96
|
+
if (reached.has(pair.a) || reached.has(pair.b)) {
|
|
97
|
+
const endpoints: Array<[string, string]> = [[pair.a, pair.b], [pair.b, pair.a]];
|
|
98
|
+
for (const [test, other] of endpoints) {
|
|
99
|
+
if (reached.has(test) || commonTests.has(test)) addRisk(test, `interference-with:${other}`, pair.evidence);
|
|
100
|
+
else unavailable.push(`verified interference endpoint unavailable in every PR head: ${test}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const canaryPrefix = `${input.baseSha}\0${input.queueSig}\0${sorted(group.prs).join(',')}`;
|
|
105
|
+
const used = new Set([...reached, ...risk]);
|
|
106
|
+
const eligible = tests.filter((test) => !used.has(test));
|
|
107
|
+
const canaryTarget = eligible.length ? Math.max(1, Math.round(eligible.length * 0.02)) : 0;
|
|
108
|
+
const canaryTests = eligible
|
|
109
|
+
.sort((a, b) => hash(`${canaryPrefix}\0${a}`).localeCompare(hash(`${canaryPrefix}\0${b}`)) || a.localeCompare(b))
|
|
110
|
+
.slice(0, canaryTarget).sort();
|
|
111
|
+
const scenarioTests = sorted([...reached, ...risk, ...canaryTests]);
|
|
112
|
+
const scenarioSet = new Set(scenarioTests);
|
|
113
|
+
const unmeasured = [...unavailable, ...evidence.suspectedPairs
|
|
114
|
+
.filter((pair) => scenarioSet.has(pair.a) || scenarioSet.has(pair.b))
|
|
115
|
+
.map((pair) => `suspected interference ${pair.a} ↔ ${pair.b}: ${pair.reason}`)];
|
|
116
|
+
return { prs: group.prs, reachTests: group.reachTests, interactionTests: group.interactionTests,
|
|
117
|
+
riskTests: sorted([...risk]), riskReasons, groupRiskReasons, canaryTests,
|
|
118
|
+
scenarioTests, populationSize: tests.length, eligiblePopulationSize: eligible.length,
|
|
119
|
+
canaryTarget, canarySelectionKey: canaryPrefix,
|
|
120
|
+
canaryHashMethod: 'sha256(canarySelectionKey\\0path)', unmeasured };
|
|
121
|
+
});
|
|
122
|
+
const unmeasured = groups.flatMap((group) => group.unmeasured);
|
|
123
|
+
// A verified interference pair executed by multiple scenarios bars parallel trains, including canary selection.
|
|
124
|
+
for (const pair of evidence.verifiedInterferencePairs) {
|
|
125
|
+
const aOwners = groups.flatMap((group, index) => group.scenarioTests.includes(pair.a) ? [index] : []);
|
|
126
|
+
const bOwners = groups.flatMap((group, index) => group.scenarioTests.includes(pair.b) ? [index] : []);
|
|
127
|
+
if (aOwners.some((a) => bOwners.some((b) => a !== b))) {
|
|
128
|
+
unmeasured.push(`verified interference crosses groups ${pair.a} ↔ ${pair.b}: ${pair.evidence}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { version: 1, baseSha: input.baseSha, queueSig: input.queueSig,
|
|
132
|
+
parallelSafe: reach.parallelSafe && unmeasured.length === 0, groups, unmeasured };
|
|
133
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
|
|
2
3
|
import { isElanousRuntimeArtifactPath } from './gate-scope.js';
|
|
3
4
|
|
|
4
5
|
export type UncommittedWork =
|
|
@@ -19,6 +20,7 @@ export function detectUncommittedWork(worktree: string): UncommittedWork {
|
|
|
19
20
|
env: gitEnv,
|
|
20
21
|
encoding: 'utf8',
|
|
21
22
|
timeout: 10_000,
|
|
23
|
+
maxBuffer: SPAWN_SYNC_MAX_BUFFER,
|
|
22
24
|
});
|
|
23
25
|
} catch (error) {
|
|
24
26
|
return { status: 'unavailable', reason: error instanceof Error ? error.message : String(error) };
|
|
@@ -99,6 +99,25 @@ export function removePendingUserInput(
|
|
|
99
99
|
return removedIds.length;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* id 로 고른 항목을 버킷 «맨 앞»으로 옮긴다(주어진 순서대로) — «지금 밀어 넣기»가 끊을 수 없는 도구 때문에
|
|
104
|
+
* 다음 경계로 떨어질 때, 같은 버킷의 다른 항목(goal-loop 메모 등)보다 먼저 들어가게 한다. 옮긴 수를 낸다.
|
|
105
|
+
*/
|
|
106
|
+
export function prioritizePendingUserInput(ids: readonly string[]): number {
|
|
107
|
+
if (ids.length === 0) return 0;
|
|
108
|
+
const order = new Map(ids.map((id, index) => [id, index]));
|
|
109
|
+
let moved = 0;
|
|
110
|
+
for (const bucket of buckets.values()) {
|
|
111
|
+
const front = bucket.items.filter(item => order.has(item.id))
|
|
112
|
+
.sort((a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0));
|
|
113
|
+
if (front.length === 0) continue;
|
|
114
|
+
bucket.items = [...front, ...bucket.items.filter(item => !order.has(item.id))];
|
|
115
|
+
moved += front.length;
|
|
116
|
+
}
|
|
117
|
+
if (moved > 0) debug.log('llm.interjection', 'prioritized', { requested: ids.length, moved });
|
|
118
|
+
return moved;
|
|
119
|
+
}
|
|
120
|
+
|
|
102
121
|
/** 지금 이 세션에 대기 중인 수(관측·표시용). 비우지 «않는다». */
|
|
103
122
|
export function pendingUserInputCount(sessionId: string): number {
|
|
104
123
|
return buckets.get(sessionId)?.items.length ?? 0;
|