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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { availableParallelism, cpus as hostCpus, freemem, totalmem } from 'node:os';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { selectGateTestFiles } from '../self-implement/gate-cli.js';
|
|
6
|
+
import { readFileMemory } from '../../scripts/release-loop/shard-plan.js';
|
|
7
|
+
import { gateShardsPath, readGateShards } from './gate-shards.js';
|
|
8
|
+
import { LIGHT_RC_ALWAYS_FILE, LIGHT_RC_DEFAULT_SHARDS, parseAlwaysIncludeList, previousCutBase } from './light-rc.js';
|
|
9
|
+
|
|
10
|
+
const FILE_MEMORY_SOURCE = 'docs/measurements/td1-whole-gate-mechanical-2026-10-01.tsv';
|
|
11
|
+
|
|
12
|
+
export interface RehearsalShardPlan {
|
|
13
|
+
shards: number;
|
|
14
|
+
testFiles: number | null;
|
|
15
|
+
/** Observed on the tick host, not necessarily the remote gate host. */
|
|
16
|
+
resources: { cpus: number; freeBytes: number; totalBytes: number };
|
|
17
|
+
gatePlanShards: number | null;
|
|
18
|
+
/** Local preflight budget, not a measured remote peak-RSS or a workload-specific guarantee. */
|
|
19
|
+
capacity?: { reserveBytes: number; bytesPerShard: number; memoryShards: number | null; requiredBytes: number; measuredFiles: number; peakFileBytes: number | null };
|
|
20
|
+
unmeasured: string | null;
|
|
21
|
+
/** The remote host's capacity is checked by the actual RC, after this preflight. */
|
|
22
|
+
remoteCapacityPending?: boolean;
|
|
23
|
+
rssRevisionPending?: boolean;
|
|
24
|
+
planningGaps?: string[];
|
|
25
|
+
remoteCapacityVerifiedBy?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RehearsalShardPlanDeps {
|
|
29
|
+
/** Rehearsal light RC dispatches remotely; local CPU/memory is evidence only, not a gate-host limit. */
|
|
30
|
+
remoteGate?: boolean;
|
|
31
|
+
select?: (checkout: string, options: { base: string; alwaysInclude: string[]; includeImporterTests: true }) => { testFiles: string[]; alwaysIncludeMissing?: readonly string[]; lookupFailed?: string | null; unrunImporterTotal?: number | null; skipTestStep?: boolean; routeLookupFailures?: readonly unknown[]; unverified?: readonly string[]; callerTestsOverflow?: readonly unknown[] };
|
|
32
|
+
resources?: () => RehearsalShardPlan['resources'];
|
|
33
|
+
board?: typeof readGateShards;
|
|
34
|
+
readAlways?: (path: string) => string;
|
|
35
|
+
resolveBase?: (version: string, checkout: string, root: string) => string;
|
|
36
|
+
fileMemory?: (path: string) => Map<string, number>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Preflight only: the gate still performs its own selection at execution time. The local budget uses measured
|
|
40
|
+
* selected-file peak RSS with a 2 GiB floor per shard and reserves 1 GiB for the host. The RC result is the
|
|
41
|
+
* authority for whether execution on its actual gate host succeeded. */
|
|
42
|
+
const GIB = 1024 ** 3;
|
|
43
|
+
const RESERVE_BYTES = GIB;
|
|
44
|
+
const BYTES_PER_SHARD = 2 * GIB;
|
|
45
|
+
|
|
46
|
+
/** The dated TSV has no dependency graph/revision. Require the whole checkout to match its source commit;
|
|
47
|
+
* otherwise RSS is provisional until a completed RC measures this actual checkout on its gate host. */
|
|
48
|
+
function measurementMatchesCheckout(checkout: string): boolean {
|
|
49
|
+
const source = spawnSync('git', ['log', '-1', '--format=%H', '--', FILE_MEMORY_SOURCE], { cwd: checkout, encoding: 'utf8' });
|
|
50
|
+
const commit = source.stdout?.trim();
|
|
51
|
+
if (source.status !== 0 || !/^[0-9a-f]{40}$/.test(commit ?? '')) return false;
|
|
52
|
+
const diff = spawnSync('git', ['diff', '--quiet', commit!, 'HEAD', '--', '.'], { cwd: checkout, encoding: 'utf8' });
|
|
53
|
+
if (diff.status !== 0) return false;
|
|
54
|
+
const working = spawnSync('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: checkout, encoding: 'utf8' });
|
|
55
|
+
return working.status === 0 && !working.stdout?.trim();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** OS free memory can describe the entire host rather than the tick's container; bound it by cgroup headroom. */
|
|
59
|
+
export function rehearsalHostResources(read: (path: string) => string = (path) => readFileSync(path, 'utf8')): RehearsalShardPlan['resources'] {
|
|
60
|
+
const cpus = Math.max(1, Number(availableParallelism?.() ?? hostCpus()?.length ?? 1) || 1);
|
|
61
|
+
let freeBytes = freemem(), totalBytes = totalmem();
|
|
62
|
+
for (const [limitPath, usagePath] of [
|
|
63
|
+
['/sys/fs/cgroup/memory.max', '/sys/fs/cgroup/memory.current'],
|
|
64
|
+
['/sys/fs/cgroup/memory/memory.limit_in_bytes', '/sys/fs/cgroup/memory/memory.usage_in_bytes'],
|
|
65
|
+
]) {
|
|
66
|
+
try {
|
|
67
|
+
const limit = Number(read(limitPath).trim()), usage = Number(read(usagePath).trim());
|
|
68
|
+
if (Number.isSafeInteger(limit) && limit > 0 && limit < totalBytes && Number.isSafeInteger(usage) && usage >= 0) {
|
|
69
|
+
totalBytes = limit;
|
|
70
|
+
freeBytes = Math.min(freeBytes, Math.max(0, limit - usage));
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
} catch { /* not running inside this cgroup version */ }
|
|
74
|
+
}
|
|
75
|
+
return { cpus, freeBytes, totalBytes };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function planRehearsalShards(version: string, root: string, checkout: string, deps: RehearsalShardPlanDeps = {}): RehearsalShardPlan {
|
|
79
|
+
const reasons: string[] = [];
|
|
80
|
+
let rssRevisionPending = false;
|
|
81
|
+
let resources: RehearsalShardPlan['resources'];
|
|
82
|
+
try { resources = (deps.resources ?? rehearsalHostResources)(); }
|
|
83
|
+
catch (error) {
|
|
84
|
+
resources = { cpus: 0, freeBytes: 0, totalBytes: 0 };
|
|
85
|
+
reasons.push(`host resource probe failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
86
|
+
}
|
|
87
|
+
let gatePlanShards: number | null = null;
|
|
88
|
+
try {
|
|
89
|
+
const board = (deps.board ?? readGateShards)(gateShardsPath(version, root));
|
|
90
|
+
gatePlanShards = board?.version === version && board.shards.length && new Set(board.shards.map(shard => shard.id)).size === board.shards.length ? board.shards.length : null;
|
|
91
|
+
} catch (error) { reasons.push(`persisted gate shard plan unreadable: ${error instanceof Error ? error.message : String(error)}`); }
|
|
92
|
+
let testFiles: number | null = null;
|
|
93
|
+
let measuredFiles = 0;
|
|
94
|
+
let peakFileBytes: number | null = null;
|
|
95
|
+
try {
|
|
96
|
+
const path = join(checkout, LIGHT_RC_ALWAYS_FILE);
|
|
97
|
+
const text = deps.readAlways ? deps.readAlways(path) : existsSync(path) ? readFileSync(path, 'utf8') : undefined;
|
|
98
|
+
if (text === undefined) throw new Error(`${LIGHT_RC_ALWAYS_FILE} missing`);
|
|
99
|
+
const base = (deps.resolveBase ?? ((v, cwd, ledgerRoot) => previousCutBase(v, { cwd, ledgerRoot })))(version, checkout, root);
|
|
100
|
+
const selection = (deps.select ?? ((cwd, opts) => selectGateTestFiles(cwd, opts)))(checkout, { base, alwaysInclude: parseAlwaysIncludeList(text), includeImporterTests: true });
|
|
101
|
+
const files = [...new Set(selection.testFiles)];
|
|
102
|
+
testFiles = files.length;
|
|
103
|
+
try {
|
|
104
|
+
const memory = (deps.fileMemory ?? readFileMemory)(join(checkout, FILE_MEMORY_SOURCE));
|
|
105
|
+
const peaks = files.map(file => memory.get(file)).filter((value): value is number => value !== undefined && Number.isFinite(value) && value > 0);
|
|
106
|
+
measuredFiles = peaks.length;
|
|
107
|
+
if (peaks.length) peakFileBytes = Math.ceil(peaks.reduce((largest, value) => Math.max(largest, value), 0) * 1_000_000);
|
|
108
|
+
if (measuredFiles !== testFiles) reasons.push(`selected file memory not measured: ${testFiles - measuredFiles}/${testFiles}`);
|
|
109
|
+
if (!deps.fileMemory && files.length && !measurementMatchesCheckout(checkout)) {
|
|
110
|
+
if (deps.remoteGate) rssRevisionPending = true;
|
|
111
|
+
else reasons.push('selected file RSS measurement revision not verified against checkout');
|
|
112
|
+
}
|
|
113
|
+
} catch (error) { reasons.push(`selected file memory unavailable: ${error instanceof Error ? error.message : String(error)}`); }
|
|
114
|
+
if (selection.alwaysIncludeMissing?.length) reasons.push(`always-include missing: ${selection.alwaysIncludeMissing.join(', ')}`);
|
|
115
|
+
if (selection.lookupFailed) reasons.push(`importer lookup failed: ${selection.lookupFailed}`);
|
|
116
|
+
if (selection.unrunImporterTotal === undefined) reasons.push('importer coverage not reported');
|
|
117
|
+
if (selection.unrunImporterTotal === null || (selection.unrunImporterTotal ?? 0) > 0) reasons.push(`importer tests not run: ${selection.unrunImporterTotal ?? 'unknown'}`);
|
|
118
|
+
if (selection.routeLookupFailures?.length) reasons.push(`route lookup failed: ${selection.routeLookupFailures.length}`);
|
|
119
|
+
if (selection.unverified?.length) reasons.push(`unverified scope: ${selection.unverified.length}`);
|
|
120
|
+
if (selection.callerTestsOverflow?.length) reasons.push(`caller tests overflow: ${selection.callerTestsOverflow.length}`);
|
|
121
|
+
if (selection.skipTestStep) reasons.push('gate test step skipped');
|
|
122
|
+
if (!testFiles) reasons.push('selected test files empty');
|
|
123
|
+
} catch (error) { reasons.push(`test selection unavailable: ${error instanceof Error ? error.message : String(error)}`); }
|
|
124
|
+
if (gatePlanShards === null) reasons.push('persisted gate shard plan unavailable');
|
|
125
|
+
const cpuValid = Number.isSafeInteger(resources.cpus) && resources.cpus > 0;
|
|
126
|
+
const memoryValid = Number.isFinite(resources.freeBytes) && resources.freeBytes >= 0 && Number.isFinite(resources.totalBytes) && resources.totalBytes > 0 && resources.freeBytes <= resources.totalBytes;
|
|
127
|
+
if (!deps.remoteGate && (!cpuValid || !memoryValid)) reasons.push('host resources unavailable');
|
|
128
|
+
const bytesPerShard = Math.max(BYTES_PER_SHARD, peakFileBytes ?? 0);
|
|
129
|
+
const memoryShards = memoryValid ? Math.max(0, Math.floor((resources.freeBytes - RESERVE_BYTES) / bytesPerShard)) : null;
|
|
130
|
+
const candidate = Math.max(1, Math.min(gatePlanShards ?? LIGHT_RC_DEFAULT_SHARDS, testFiles ?? LIGHT_RC_DEFAULT_SHARDS, deps.remoteGate ? Number.MAX_SAFE_INTEGER : cpuValid ? resources.cpus : LIGHT_RC_DEFAULT_SHARDS));
|
|
131
|
+
if (!deps.remoteGate && peakFileBytes !== null && memoryValid && resources.freeBytes < RESERVE_BYTES + peakFileBytes) {
|
|
132
|
+
reasons.push(`selected file peak exceeds host memory: peak ${peakFileBytes}, free ${resources.freeBytes}, reserve ${RESERVE_BYTES} bytes`);
|
|
133
|
+
}
|
|
134
|
+
// Never treat a 0-slot host as sufficient for one shard. The caller must leave an unrun step retryable.
|
|
135
|
+
const shards = deps.remoteGate || memoryShards === null ? candidate : Math.max(1, Math.min(candidate, memoryShards));
|
|
136
|
+
const capacity = { reserveBytes: RESERVE_BYTES, bytesPerShard, memoryShards, requiredBytes: RESERVE_BYTES + shards * bytesPerShard, measuredFiles, peakFileBytes };
|
|
137
|
+
if (!deps.remoteGate && memoryShards === 0) reasons.push(`host memory insufficient: free ${resources.freeBytes} < required ${capacity.requiredBytes} bytes for 1 shard`);
|
|
138
|
+
// The exported local planner has no local RC caller to validate aggregate workload capacity. A prior board's
|
|
139
|
+
// shard count and individual file peaks cannot prove that hundreds of tests fit one shard.
|
|
140
|
+
if (!deps.remoteGate) reasons.push('local gate shard workload sufficiency not measured');
|
|
141
|
+
// A complete selected-file measurement plus the persisted shard count and a valid host budget is enough to
|
|
142
|
+
// select a candidate. Execution on another host is judged by the RC result, not by a permanent preflight warning.
|
|
143
|
+
const remoteCapacityReason = 'remote gate host resources unmeasured before RC';
|
|
144
|
+
const rssRevisionReason = 'selected file RSS measurement revision not verified before RC';
|
|
145
|
+
return { shards, testFiles, resources, gatePlanShards, capacity,
|
|
146
|
+
...(deps.remoteGate ? { remoteCapacityPending: true, rssRevisionPending, planningGaps: reasons } : {}),
|
|
147
|
+
unmeasured: reasons.length || deps.remoteGate ? [...reasons, ...(rssRevisionPending ? [rssRevisionReason] : []), ...(deps.remoteGate ? [remoteCapacityReason] : [])].join('; ') : null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import { existsSync, linkSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { existsSync, linkSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
4
5
|
import { dirname, join } from 'node:path';
|
|
5
6
|
import { debug } from '../debug/log.js';
|
|
6
7
|
import { sendOutbound } from '../domains/outbound-alert.js';
|
|
7
8
|
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
8
|
-
import {
|
|
9
|
+
import { isValidGateHost } from '../self-implement/gate-remote.js';
|
|
10
|
+
import { LIGHT_RC_UNKNOWN_HOST, runLightRc, type LightRcResult } from './light-rc.js';
|
|
11
|
+
import { planRehearsalShards, type RehearsalShardPlan, type RehearsalShardPlanDeps } from './rehearsal-shard-plan.js';
|
|
9
12
|
import { listSchedules, type ReleaseSchedule } from './release-schedule.js';
|
|
10
13
|
|
|
11
14
|
export type StepId = 'rc-7h' | 'rc-150m';
|
|
@@ -50,6 +53,9 @@ export interface RehearsalStamp {
|
|
|
50
53
|
summary?: string;
|
|
51
54
|
regressionFiles?: string[];
|
|
52
55
|
result?: LightRcResult;
|
|
56
|
+
shardPlan?: RehearsalShardPlan;
|
|
57
|
+
leakCheck?: { outcome: 'ok' | 'fail'; sha: string; exitCode: number | null };
|
|
58
|
+
selection?: { shards?: number; remote?: string };
|
|
53
59
|
notifiedAt?: string;
|
|
54
60
|
ownerPid?: number;
|
|
55
61
|
}
|
|
@@ -58,14 +64,19 @@ export interface RehearsalOptions {
|
|
|
58
64
|
apply?: boolean;
|
|
59
65
|
checkout?: string;
|
|
60
66
|
ledgerRoot?: string;
|
|
67
|
+
shards?: number;
|
|
68
|
+
remote?: string;
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
export interface RehearsalDeps {
|
|
64
72
|
now?: () => Date;
|
|
65
73
|
schedules?: (root: string) => ReleaseSchedule[];
|
|
66
|
-
lightRc?: (version: string, checkout: string) => Promise<LightRcResult>;
|
|
74
|
+
lightRc?: (version: string, checkout: string, selection: { shards?: number; remote?: string }) => Promise<LightRcResult>;
|
|
75
|
+
shardPlan?: typeof planRehearsalShards;
|
|
76
|
+
shardPlanDeps?: RehearsalShardPlanDeps;
|
|
67
77
|
notify?: (text: string) => void | boolean | Promise<void | boolean>;
|
|
68
78
|
git?: (args: string[], cwd: string) => { rc: number | null; stdout: string; stderr?: string };
|
|
79
|
+
leakCheck?: (checkout: string) => { status: number | null };
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
export type RehearsalTickResult = RehearsalPlan & { applied?: boolean; stamps?: RehearsalStamp[]; notificationFailures?: number };
|
|
@@ -86,6 +97,17 @@ function gitResult(git: NonNullable<RehearsalDeps['git']>, args: string[], check
|
|
|
86
97
|
return result.stdout.trim();
|
|
87
98
|
}
|
|
88
99
|
|
|
100
|
+
/** Public export checks the pinned rehearsal checkout before any remote RC work. Its output is private and ephemeral. */
|
|
101
|
+
function runRehearsalLeakCheck(checkout: string): { status: number | null } {
|
|
102
|
+
const out = mkdtempSync(join(tmpdir(), 'elanous-rehearsal-export-'));
|
|
103
|
+
try {
|
|
104
|
+
const result = spawnSync('bun', ['scripts/public-export.ts', '--out', join(out, 'export')], {
|
|
105
|
+
cwd: checkout, encoding: 'utf8', timeout: 1_800_000, maxBuffer: 64 * 1024 * 1024,
|
|
106
|
+
});
|
|
107
|
+
return { status: result.status };
|
|
108
|
+
} finally { rmSync(out, { recursive: true, force: true }); }
|
|
109
|
+
}
|
|
110
|
+
|
|
89
111
|
function oneLine(text: string): string { return text.replace(/\s+/g, ' ').trim(); }
|
|
90
112
|
|
|
91
113
|
function outcomeLine(stamp: RehearsalStamp): string {
|
|
@@ -95,7 +117,11 @@ function outcomeLine(stamp: RehearsalStamp): string {
|
|
|
95
117
|
if (!stamp.result) return `${head}${stamp.summary ? ` · ${stamp.summary}` : ''}`;
|
|
96
118
|
const result = stamp.result;
|
|
97
119
|
const duration = Math.max(0, Math.round((Date.parse(stamp.endedAt!) - Date.parse(stamp.startedAt)) / minute));
|
|
98
|
-
|
|
120
|
+
const planningGap = stamp.shardPlan?.unmeasured
|
|
121
|
+
|| (stamp.selection?.shards !== undefined && result.shards !== stamp.selection.shards)
|
|
122
|
+
|| (stamp.selection?.remote !== undefined && result.remote !== stamp.selection.remote);
|
|
123
|
+
const detail = stamp.summary && (stamp.outcome === 'unmeasured' || stamp.outcome === 'error' && planningGap) ? ` · ${stamp.summary}` : '';
|
|
124
|
+
return `${head} · 새 회귀 ${result.introduced ?? '못 쟀다'} · 기존 ${result.preexisting ?? '못 쟀다'} · 미분류 ${result.unclassified ?? '못 쟀다'} · ${result.remote ?? 'local'} · ${duration}분${stamp.outcome === 'error' ? ` · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}` : ''}${stamp.regressionFiles?.length ? ` · 파일 ${stamp.regressionFiles.slice(0, 3).join(', ')}` : ''}${detail}`;
|
|
99
125
|
}
|
|
100
126
|
|
|
101
127
|
function persistStamp(path: string, stamp: RehearsalStamp): void {
|
|
@@ -207,6 +233,12 @@ function interruptStamp(path: string, saved: RehearsalStamp, now: Date): Rehears
|
|
|
207
233
|
|
|
208
234
|
/** wx claim is permanent per version/step; a crashed run is reported as interrupted without running RC twice. */
|
|
209
235
|
export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: RehearsalDeps = {}): Promise<RehearsalTickResult> {
|
|
236
|
+
if (opts.shards !== undefined && (!Number.isSafeInteger(opts.shards) || opts.shards < 1)) {
|
|
237
|
+
throw new Error(`release rehearsal tick: invalid --shards count: ${opts.shards}`);
|
|
238
|
+
}
|
|
239
|
+
if (opts.remote !== undefined && !isValidGateHost(opts.remote)) {
|
|
240
|
+
throw new Error(`release rehearsal tick: invalid --remote host: ${opts.remote}`);
|
|
241
|
+
}
|
|
210
242
|
const root = opts.ledgerRoot ?? releaseLedgerRoot();
|
|
211
243
|
const now = (deps.now ?? (() => new Date()))();
|
|
212
244
|
const schedules = (deps.schedules ?? listSchedules)(root);
|
|
@@ -289,26 +321,50 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
|
|
|
289
321
|
gitResult(git, ['checkout', '-q', '--detach', 'origin/main'], checkout);
|
|
290
322
|
stamp.sha = gitResult(git, ['rev-parse', 'HEAD'], checkout);
|
|
291
323
|
if (!stamp.sha) throw new Error('git rev-parse HEAD returned no sha');
|
|
324
|
+
const leak = (deps.leakCheck ?? runRehearsalLeakCheck)(checkout);
|
|
325
|
+
stamp.leakCheck = { outcome: leak.status === 0 ? 'ok' : 'fail', sha: stamp.sha, exitCode: leak.status };
|
|
326
|
+
if (leak.status !== 0) throw new Error(`public export leak-check failed (rc=${leak.status ?? 'spawn'})`);
|
|
292
327
|
const regressionFiles: string[] = [];
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
328
|
+
const shardPlan = opts.shards === undefined ? (deps.shardPlan ?? planRehearsalShards)(plan.version, root, checkout, { ...deps.shardPlanDeps, remoteGate: true }) : undefined;
|
|
329
|
+
if (shardPlan) stamp.shardPlan = shardPlan;
|
|
330
|
+
const selection = { shards: opts.shards ?? shardPlan?.shards, remote: opts.remote };
|
|
331
|
+
stamp.selection = selection;
|
|
332
|
+
const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, ...selection, rehearsalTui: true, log: (line) => {
|
|
333
|
+
for (const entry of line.split(/\r?\n/)) {
|
|
334
|
+
const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
|
|
335
|
+
if (file && regressionFiles.length < 3) regressionFiles.push(file);
|
|
336
|
+
}
|
|
337
|
+
console.error(line);
|
|
338
|
+
} }, { cwd })))(plan.version, checkout, selection);
|
|
300
339
|
stamp.result = result;
|
|
301
340
|
if (regressionFiles.length) stamp.regressionFiles = regressionFiles;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
341
|
+
const shardMismatch = selection.shards !== undefined && result.shards !== selection.shards
|
|
342
|
+
? `selected shards ${selection.shards} but RC reported ${result.shards}` : null;
|
|
343
|
+
const remoteMismatch = opts.remote && result.remote !== opts.remote
|
|
344
|
+
? `requested remote ${opts.remote} but RC reported ${result.remote ?? 'local'}` : null;
|
|
345
|
+
if (shardPlan?.remoteCapacityPending && result.remote && result.remote !== LIGHT_RC_UNKNOWN_HOST
|
|
346
|
+
&& !remoteMismatch && result.unmeasured === null
|
|
347
|
+
&& result.introduced !== null && result.unclassified === 0 && result.ok
|
|
348
|
+
&& result.gateExitCode === 0 && !shardMismatch) {
|
|
349
|
+
// Only the completed RC can validate capacity of the actual remote host. Keep independent
|
|
350
|
+
// selection/RSS gaps; clear just the provisional remote-capacity gap.
|
|
351
|
+
stamp.shardPlan = { ...shardPlan, remoteCapacityPending: false, rssRevisionPending: false,
|
|
352
|
+
remoteCapacityVerifiedBy: result.remote,
|
|
353
|
+
unmeasured: shardPlan.planningGaps?.length ? shardPlan.planningGaps.join('; ') : null };
|
|
354
|
+
}
|
|
355
|
+
const planningGap = stamp.shardPlan?.unmeasured || shardMismatch || remoteMismatch;
|
|
356
|
+
const missingEvidence = result.introduced === null || result.unclassified === null
|
|
357
|
+
|| result.unmeasured !== null || result.unclassified > 0 || !!planningGap;
|
|
358
|
+
stamp.outcome = result.introduced !== null && result.introduced > 0 ? missingEvidence ? 'unmeasured' : 'regression'
|
|
359
|
+
: result.introduced === null || result.unclassified === null || result.unmeasured !== null || result.unclassified > 0 ? 'unmeasured'
|
|
360
|
+
: result.unmeasured === null && (!result.ok || result.gateExitCode !== 0) ? 'error'
|
|
361
|
+
: planningGap ? 'unmeasured' : 'ok';
|
|
362
|
+
stamp.summary = oneLine(`introduced ${result.introduced} · preexisting ${result.preexisting ?? 'unmeasured'} · unclassified ${result.unclassified} · ${result.remote ?? 'local'} · gate rc ${result.gateExitCode}${!result.ok ? ' · RC 실패' : ''}${result.unmeasured !== null ? ` · unmeasured: ${result.unmeasured || 'RC reason empty'}` : ''}${stamp.shardPlan?.unmeasured ? ` · unmeasured: ${stamp.shardPlan.unmeasured}` : ''}${shardMismatch ? ` · unmeasured: ${shardMismatch}` : ''}${remoteMismatch ? ` · unmeasured: ${remoteMismatch}` : ''}`);
|
|
307
363
|
}
|
|
308
364
|
}
|
|
309
365
|
} catch (error) {
|
|
310
366
|
stamp.outcome = 'error';
|
|
311
|
-
stamp.summary = oneLine(String(error instanceof Error ? error.message : error).split(/\r?\n/, 1)[0] ?? 'unknown error');
|
|
367
|
+
stamp.summary = oneLine(`${String(error instanceof Error ? error.message : error).split(/\r?\n/, 1)[0] ?? 'unknown error'}${stamp.shardPlan?.unmeasured ? ` · unmeasured: ${stamp.shardPlan.unmeasured}` : ''}`);
|
|
312
368
|
}
|
|
313
369
|
await finish(path, stamp);
|
|
314
370
|
}
|
package/src/repl/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
import {
|
|
31
31
|
resolveSessionId,
|
|
32
32
|
loadSession,
|
|
33
|
+
listSessions,
|
|
33
34
|
setActiveSessionId,
|
|
34
35
|
getActiveSessionId,
|
|
35
36
|
} from '../session/index.js';
|
|
@@ -41,6 +42,7 @@ import {
|
|
|
41
42
|
} from '../user-config.js';
|
|
42
43
|
import { setAmbientSessionId, debug } from '../debug/log.js';
|
|
43
44
|
import { decideSigintAction } from './sigint.js';
|
|
45
|
+
import { decideSessionStart, observeSessionStart } from '../session/session-start.js';
|
|
44
46
|
import { buildReplayTurnsFromSession } from './replay.js';
|
|
45
47
|
import type { LLMToolSpec, ContentBlock } from '../llm.js';
|
|
46
48
|
import { inspectActiveProvider } from '../provider-summary.js';
|
|
@@ -58,6 +60,8 @@ export interface ReplOpts {
|
|
|
58
60
|
initialSessionId: string | undefined;
|
|
59
61
|
/** Force a fresh session even if active marker exists. */
|
|
60
62
|
forceNew: boolean;
|
|
63
|
+
/** `--continue`/`--resume` — 활성 세션 이어하기(명시). 대표 #73: 기본은 새 세션. */
|
|
64
|
+
continueActive?: boolean;
|
|
61
65
|
/** Enable the tool loop (Read/Grep/Bash/...). Default true — REPL
|
|
62
66
|
* is the agent surface; users opt out with --no-tools. */
|
|
63
67
|
enableTools: boolean;
|
|
@@ -445,11 +449,25 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
|
|
|
445
449
|
return 1;
|
|
446
450
|
}
|
|
447
451
|
initialId = id;
|
|
448
|
-
} else if (!opts.forceNew) {
|
|
449
|
-
initialId = getActiveSessionId() ?? undefined;
|
|
450
452
|
}
|
|
453
|
+
const startDecision = decideSessionStart({
|
|
454
|
+
...(initialId ? { explicitSessionId: initialId } : {}),
|
|
455
|
+
continueActive: opts.continueActive === true,
|
|
456
|
+
forceNew: opts.forceNew,
|
|
457
|
+
activeSessionId: () => getActiveSessionId(),
|
|
458
|
+
// TUI-H8-FOLLOW ① — 활성 표지가 사라진 세션이면 최신 세션으로.
|
|
459
|
+
sessionExists: (id) => loadSession(id) !== null,
|
|
460
|
+
latestSessionId: () => listSessions({ limit: 1 })[0]?.id ?? null,
|
|
461
|
+
});
|
|
462
|
+
initialId = startDecision.sessionIdHint;
|
|
451
463
|
const session = ensureCliSession(cfg, initialId);
|
|
452
464
|
setActiveSessionId(session.id);
|
|
465
|
+
observeSessionStart({
|
|
466
|
+
surface: 'repl',
|
|
467
|
+
origin: initialId && session.id === initialId ? startDecision.origin : 'new',
|
|
468
|
+
reason: initialId && session.id !== initialId ? 'resume-target-missing' : startDecision.reason,
|
|
469
|
+
sessionId: session.id,
|
|
470
|
+
});
|
|
453
471
|
setAmbientSessionId(session.id);
|
|
454
472
|
if (!opts.jsonOutput && (!initialId || session.id !== initialId)) {
|
|
455
473
|
try {
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// ── Seat knowhow packs — RFC-seat-knowhow-packs-adaptive-knowledge-2026-10-11.md §A ──
|
|
2
|
+
//
|
|
3
|
+
// Loader for `내부 문서 `KNOWHOW`` v2 items plus the role charter
|
|
4
|
+
// `내부 문서 `<자리>``. Replaces the two duplicate role-file reads inside
|
|
5
|
+
// seat-loop.ts (gatherSeatInputs + inquire) — one loader, no 4,000-char cut
|
|
6
|
+
// on the charter, one overall budget cap instead.
|
|
7
|
+
//
|
|
8
|
+
// Injection rules (§A3 ⊕ review must-fix 1):
|
|
9
|
+
// «사실» = status active ⊕ last verification «참» ⊕ within half-life
|
|
10
|
+
// «참고(검증 안 됨)» = unproven / unverifiable(못잼) / expired half-life
|
|
11
|
+
// dropped = any status outside active/unproven/unverifiable,
|
|
12
|
+
// last verification «거짓»/future/invalid date,
|
|
13
|
+
// 상태 미선언 · 검증 미선언 — a card is injected
|
|
14
|
+
// only with an explicit 상태 AND an explicit 검증 line;
|
|
15
|
+
// a missing 상태 is never assumed to be `active`.
|
|
16
|
+
//
|
|
17
|
+
// Half-life (§A1): fact 14 · warning 30 · heuristic 90 · playbook 60 days,
|
|
18
|
+
// case unlimited; kind defaults to fact when a card does not declare one.
|
|
19
|
+
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { debug } from '../debug/log.js';
|
|
23
|
+
|
|
24
|
+
export type KnowhowKind = 'fact' | 'warning' | 'heuristic' | 'playbook' | 'case';
|
|
25
|
+
|
|
26
|
+
export const KNOWHOW_HALF_LIFE_DAYS: Record<KnowhowKind, number> = {
|
|
27
|
+
fact: 14,
|
|
28
|
+
warning: 30,
|
|
29
|
+
heuristic: 90,
|
|
30
|
+
playbook: 60,
|
|
31
|
+
case: Number.POSITIVE_INFINITY,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** One overall budget cap for the whole injected pack (RFC §A3 — value
|
|
35
|
+
* unspecified in the ask; 32,000 chars adopted as the documented value for
|
|
36
|
+
* this slice, replacing the old per-chunk 4,000-char cuts).
|
|
37
|
+
*
|
|
38
|
+
* Budget policy (review must-fix 3) — whole items only, `text.slice` is never
|
|
39
|
+
* used: the charter, each block header, and each card enter the pack whole or
|
|
40
|
+
* not at all.
|
|
41
|
+
* 1. The charter is always kept whole and outranks every card.
|
|
42
|
+
* 2. Cards are appended whole in top-k order while the running total stays
|
|
43
|
+
* within this cap; a card that would exceed it is skipped (a later,
|
|
44
|
+
* smaller card may still fit).
|
|
45
|
+
* 3. A charter that alone exceeds the cap is still injected whole and both
|
|
46
|
+
* card blocks are dropped entirely — the seat keeps its charter; slicing
|
|
47
|
+
* the charter mid-way is exactly what this policy abolishes. */
|
|
48
|
+
export const SEAT_PACK_TOTAL_BUDGET_CHARS = 32_000;
|
|
49
|
+
export const DEFAULT_TOP_K = 8;
|
|
50
|
+
|
|
51
|
+
export interface KnowhowItem {
|
|
52
|
+
kind: KnowhowKind;
|
|
53
|
+
/** Declared 상태 — '' when the card states none (never assumed active). */
|
|
54
|
+
status: string;
|
|
55
|
+
verifiedAt: Date | null;
|
|
56
|
+
/** true = 참 · false = 거짓 · null = 못잼/unproven */
|
|
57
|
+
verified: boolean | null;
|
|
58
|
+
text: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SeatPack {
|
|
62
|
+
charter: string;
|
|
63
|
+
/** Card texts actually injected into `text` — never a superset of it. */
|
|
64
|
+
facts: string[];
|
|
65
|
+
refs: string[];
|
|
66
|
+
/** Cards refused by classification (contradicted·stale·superseded·거짓·
|
|
67
|
+
* 상태/검증 미선언). Cards skipped only by the budget are not counted. */
|
|
68
|
+
dropped: number;
|
|
69
|
+
text: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface SeatPackDeps {
|
|
73
|
+
repo?: string;
|
|
74
|
+
read?: (path: string) => string;
|
|
75
|
+
now?: () => Date;
|
|
76
|
+
topK?: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 참/거짓 뒤 경계는 \b 대신 명시적 뒷자리 제한 — \w 가 ASCII 한정이라
|
|
80
|
+
// 참(한글) 뒤에서는 \b 가 경계로 안 센다(실측: verified 가 null 로 흘렀다).
|
|
81
|
+
const VERIFIED_TRUE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*참(?![^\s(·])/;
|
|
82
|
+
const VERIFIED_FALSE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*거짓(?![^\s(·])/;
|
|
83
|
+
const VERIFIED_UNVERIFIABLE_RE = /^\s*(\d{4}-\d{2}-\d{2})\s*못잼/;
|
|
84
|
+
const FIELD_RE = /^-([^:]+):\s*(.*)$/;
|
|
85
|
+
|
|
86
|
+
function calendarDate(isoDay: string): Date | null {
|
|
87
|
+
const date = new Date(`${isoDay}T00:00:00Z`);
|
|
88
|
+
return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === isoDay ? date : null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function parseKnowhowItems(body: string, seat: string): KnowhowItem[] {
|
|
92
|
+
const headerRe = new RegExp(`^##\\s+K-${seat.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}-\\d+`, 'i');
|
|
93
|
+
const items: KnowhowItem[] = [];
|
|
94
|
+
// First section before any card header is the document preamble — drop it.
|
|
95
|
+
const sections = body.split(/^##\s+/m);
|
|
96
|
+
for (const section of sections) {
|
|
97
|
+
const lines = section.split('\n');
|
|
98
|
+
const header = lines[0] ?? '';
|
|
99
|
+
if (!headerRe.test(`## ${header}`)) continue;
|
|
100
|
+
const rest = lines.slice(1).join('\n');
|
|
101
|
+
const fields: Record<string, string> = {};
|
|
102
|
+
let kind: KnowhowKind | null = null;
|
|
103
|
+
let status = '';
|
|
104
|
+
let verifiedAt: Date | null = null;
|
|
105
|
+
let verified: boolean | null = null;
|
|
106
|
+
for (const line of rest.split('\n')) {
|
|
107
|
+
const m = line.match(FIELD_RE);
|
|
108
|
+
if (m) {
|
|
109
|
+
const label = m[1].trim();
|
|
110
|
+
const value = m[2].trim();
|
|
111
|
+
fields[label] = value;
|
|
112
|
+
if (label === '종류' && value in KNOWHOW_HALF_LIFE_DAYS) {
|
|
113
|
+
kind = value as KnowhowKind;
|
|
114
|
+
} else if (label === '상태') {
|
|
115
|
+
status = value;
|
|
116
|
+
} else if (label === '검증') {
|
|
117
|
+
// A later verification line supersedes the earlier one even when
|
|
118
|
+
// malformed; otherwise an old «참» survives a failed new check.
|
|
119
|
+
verified = null;
|
|
120
|
+
verifiedAt = null;
|
|
121
|
+
const t = value.match(VERIFIED_TRUE_RE);
|
|
122
|
+
const f = value.match(VERIFIED_FALSE_RE);
|
|
123
|
+
const u = value.match(VERIFIED_UNVERIFIABLE_RE);
|
|
124
|
+
if (t) {
|
|
125
|
+
verified = true;
|
|
126
|
+
verifiedAt = calendarDate(t[1]);
|
|
127
|
+
} else if (f) {
|
|
128
|
+
verified = false;
|
|
129
|
+
verifiedAt = calendarDate(f[1]);
|
|
130
|
+
} else if (u) {
|
|
131
|
+
verified = null;
|
|
132
|
+
verifiedAt = calendarDate(u[1]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Inline `상태:`/`종류:` inside other fields (e.g. the 출처 line) also count.
|
|
138
|
+
for (const value of Object.values(fields)) {
|
|
139
|
+
if (!status) {
|
|
140
|
+
const s = value.match(/(?:^|·\s*|[·,,;|\s])상태:\s*(\S+)/);
|
|
141
|
+
if (s) status = s[1];
|
|
142
|
+
}
|
|
143
|
+
if (!kind) {
|
|
144
|
+
const k = value.match(/(?:^|·\s*|[·,,;|\s])종류:\s*(\S+)/);
|
|
145
|
+
if (k && k[1] in KNOWHOW_HALF_LIFE_DAYS) kind = k[1] as KnowhowKind;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
items.push({
|
|
149
|
+
kind: kind ?? 'fact',
|
|
150
|
+
// Missing 상태 stays '' — the classifier refuses to inject it; the
|
|
151
|
+
// parser must not default a status-less card to `active` (must-fix 1).
|
|
152
|
+
status,
|
|
153
|
+
verifiedAt,
|
|
154
|
+
verified,
|
|
155
|
+
text: `## ${header}\n${rest}`.trim(),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return items;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function withinHalfLife(item: KnowhowItem, now: Date): boolean {
|
|
162
|
+
if (!item.verifiedAt) return false;
|
|
163
|
+
const ageMs = now.getTime() - item.verifiedAt.getTime();
|
|
164
|
+
if (!Number.isFinite(ageMs) || ageMs < 0) return false;
|
|
165
|
+
const days = KNOWHOW_HALF_LIFE_DAYS[item.kind];
|
|
166
|
+
if (!Number.isFinite(days)) return true;
|
|
167
|
+
return ageMs <= days * 24 * 60 * 60 * 1000;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** «사실» vs «참고(검증 안 됨)» vs dropped(contradicted·stale·superseded·최근
|
|
171
|
+
* 검증 거짓·상태/검증 미선언). Only active/unproven/unverifiable are admitted;
|
|
172
|
+
* a future or invalid verification date is rejected. A card is injected only when it declares an
|
|
173
|
+
* explicit 상태 AND an explicit 검증 line; a card whose most recent
|
|
174
|
+
* verification is «거짓» is contradicted — dropped, never filed as
|
|
175
|
+
* «검증 안 됨» (review must-fix 1). */
|
|
176
|
+
export function splitKnowhow(
|
|
177
|
+
items: KnowhowItem[],
|
|
178
|
+
now: Date,
|
|
179
|
+
): { facts: KnowhowItem[]; refs: KnowhowItem[]; dropped: number } {
|
|
180
|
+
const facts: KnowhowItem[] = [];
|
|
181
|
+
const refs: KnowhowItem[] = [];
|
|
182
|
+
let dropped = 0;
|
|
183
|
+
for (const item of items) {
|
|
184
|
+
const allowedStatus = item.status === 'active' || item.status === 'unproven' || item.status === 'unverifiable';
|
|
185
|
+
const verifiedAtMs = item.verifiedAt?.getTime();
|
|
186
|
+
const lacksExplicitConditions = !Number.isFinite(verifiedAtMs) || item.verified === false
|
|
187
|
+
|| verifiedAtMs! > now.getTime();
|
|
188
|
+
if (!allowedStatus || lacksExplicitConditions) {
|
|
189
|
+
dropped += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (item.verified === true && item.status === 'active' && withinHalfLife(item, now)) {
|
|
193
|
+
facts.push(item);
|
|
194
|
+
} else {
|
|
195
|
+
refs.push(item);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return { facts, refs, dropped };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function tokenize(text: string): string[] {
|
|
202
|
+
return text
|
|
203
|
+
.toLowerCase()
|
|
204
|
+
.split(/[^\p{L}\p{N}_]+/u)
|
|
205
|
+
.filter((t) => t.length > 0);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Top-k by word overlap with the query (default k = 8). Ties keep pack order. */
|
|
209
|
+
export function selectTopK(items: KnowhowItem[], query: string, k: number = DEFAULT_TOP_K): KnowhowItem[] {
|
|
210
|
+
const tokens = new Set(tokenize(query));
|
|
211
|
+
const scored = items.map((item, index) => {
|
|
212
|
+
const itemTokens = new Set(tokenize(item.text));
|
|
213
|
+
let score = 0;
|
|
214
|
+
for (const token of itemTokens) if (tokens.has(token)) score += 1;
|
|
215
|
+
return { item, score, index };
|
|
216
|
+
});
|
|
217
|
+
scored.sort((a, b) => b.score - a.score || a.index - b.index);
|
|
218
|
+
return scored.slice(0, Math.max(0, k)).map((s) => s.item);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Assemble the pack under SEAT_PACK_TOTAL_BUDGET_CHARS at whole-item
|
|
222
|
+
* granularity — see the policy on the constant. The `facts`/`refs` arrays in
|
|
223
|
+
* the result carry exactly the cards that made it into `text`. */
|
|
224
|
+
function assemblePack(
|
|
225
|
+
charter: string,
|
|
226
|
+
rankedItems: KnowhowItem[],
|
|
227
|
+
factSet: ReadonlySet<KnowhowItem>,
|
|
228
|
+
): { text: string; facts: string[]; refs: string[] } {
|
|
229
|
+
const SEP = '\n\n';
|
|
230
|
+
let used = charter.length;
|
|
231
|
+
const facts: string[] = [];
|
|
232
|
+
const refs: string[] = [];
|
|
233
|
+
// Budget in query rank order; rendering can still group facts before refs.
|
|
234
|
+
for (const item of rankedItems) {
|
|
235
|
+
const isFact = factSet.has(item);
|
|
236
|
+
const out = isFact ? facts : refs;
|
|
237
|
+
const header = isFact ? '### 사실 (검증된 노하우)' : '### 참고 (검증 안 됨)';
|
|
238
|
+
const cost = out.length === 0
|
|
239
|
+
? (used > 0 ? SEP.length : 0) + header.length + SEP.length + item.text.length
|
|
240
|
+
: SEP.length + item.text.length;
|
|
241
|
+
if (used + cost > SEAT_PACK_TOTAL_BUDGET_CHARS) continue;
|
|
242
|
+
out.push(item.text);
|
|
243
|
+
used += cost;
|
|
244
|
+
}
|
|
245
|
+
let text = charter;
|
|
246
|
+
if (facts.length > 0) text += `${text ? SEP : ''}### 사실 (검증된 노하우)${SEP}${facts.join(SEP)}`;
|
|
247
|
+
if (refs.length > 0) text += `${text ? SEP : ''}### 참고 (검증 안 됨)${SEP}${refs.join(SEP)}`;
|
|
248
|
+
return { text, facts, refs };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function loadSeatPack(seat: string, query = '', deps: SeatPackDeps = {}): SeatPack {
|
|
252
|
+
const repo = deps.repo ?? process.cwd();
|
|
253
|
+
const read = deps.read ?? ((path: string) => readFileSync(path, 'utf8'));
|
|
254
|
+
const now = deps.now ?? (() => new Date());
|
|
255
|
+
const charter = read(join(repo, 'docs', 'roles', `${seat}.md`)).trim();
|
|
256
|
+
const knowhowPath = join(repo, 'docs', 'roles', seat, 'KNOWHOW.md');
|
|
257
|
+
// NOTE: presence is decided by reading through `deps.read`, not existsSync —
|
|
258
|
+
// tests mount a virtual reader; a disk probe would report the virtual path
|
|
259
|
+
// missing and silently drop the whole KNOWHOW pack (observed: facts=0).
|
|
260
|
+
let knowhowBody = '';
|
|
261
|
+
try {
|
|
262
|
+
knowhowBody = read(knowhowPath);
|
|
263
|
+
} catch {
|
|
264
|
+
knowhowBody = '';
|
|
265
|
+
}
|
|
266
|
+
const items = parseKnowhowItems(knowhowBody, seat);
|
|
267
|
+
const { facts, refs, dropped } = splitKnowhow(items, now());
|
|
268
|
+
const topK = deps.topK ?? DEFAULT_TOP_K;
|
|
269
|
+
// One top-k pass over the whole candidate pool (facts ⊕ refs), then the
|
|
270
|
+
// winners are split back into their blocks in score order — applying k per
|
|
271
|
+
// block would inject up to 2k cards (review must-fix 2).
|
|
272
|
+
const selected = selectTopK([...facts, ...refs], query, topK);
|
|
273
|
+
const factSet = new Set(facts);
|
|
274
|
+
const pack = assemblePack(charter, selected, factSet);
|
|
275
|
+
debug.log('seat.loop', 'pack-loaded', {
|
|
276
|
+
seat,
|
|
277
|
+
facts: pack.facts.length,
|
|
278
|
+
refs: pack.refs.length,
|
|
279
|
+
dropped,
|
|
280
|
+
});
|
|
281
|
+
return { charter, facts: pack.facts, refs: pack.refs, dropped, text: pack.text };
|
|
282
|
+
}
|