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
package/src/git-fs/index.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// on its own cadence (dashboard throttles to ~2s).
|
|
10
10
|
|
|
11
11
|
import { resolve } from 'node:path';
|
|
12
|
-
import { spawnSync } from 'node:child_process';
|
|
12
|
+
import { execFile, spawnSync } from 'node:child_process';
|
|
13
13
|
import { findGitDir, type LocatedGit } from './locate.js';
|
|
14
14
|
import { readGitHead } from './read-head.js';
|
|
15
15
|
import { GitFileWatcher } from './watcher.js';
|
|
@@ -31,13 +31,62 @@ export { probeDirty, probeAheadBehind, parsePorcelain } from './dirty.js';
|
|
|
31
31
|
const SNAPSHOT_TIMEOUT_MS = 5_000;
|
|
32
32
|
const SNAPSHOT_STATUS_MAX_CHARS = 2_000;
|
|
33
33
|
const GIT_SNAPSHOT_TTL_MS = 3_000;
|
|
34
|
+
/** A cached snapshot older than this is rebuilt in the background on the next periodic dirty tick. */
|
|
35
|
+
const GIT_SNAPSHOT_KEEP_WARM_MS = 30_000;
|
|
34
36
|
|
|
35
37
|
interface GitSnapshotCacheEntry {
|
|
36
38
|
at: number;
|
|
39
|
+
/** Monotonic store ordering — `at` can flip within the same millisecond. */
|
|
40
|
+
version: number;
|
|
37
41
|
value: string | null;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
const gitSnapshotCache = new Map<string, GitSnapshotCacheEntry>();
|
|
45
|
+
/** The entry an invalidation (known write · HEAD move) just evicted. Only the
|
|
46
|
+
* stale-while-revalidate turn path reads it, and only while it is younger than
|
|
47
|
+
* its window: the turn is served the last snapshot (its header states when it
|
|
48
|
+
* was taken) while the background rebuild runs, instead of rebuilding
|
|
49
|
+
* synchronously on the event loop. Any later store supersedes it. */
|
|
50
|
+
const gitSnapshotLastKnown = new Map<string, GitSnapshotCacheEntry>();
|
|
51
|
+
|
|
52
|
+
function storeGitSnapshot(key: string, entry: Omit<GitSnapshotCacheEntry, 'version'>): void {
|
|
53
|
+
gitSnapshotCache.set(key, { ...entry, version: bumpGitSnapshotVersion(key) });
|
|
54
|
+
gitSnapshotLastKnown.delete(key);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function evictGitSnapshot(key: string): boolean {
|
|
58
|
+
const entry = gitSnapshotCache.get(key);
|
|
59
|
+
if (!entry) return false;
|
|
60
|
+
gitSnapshotCache.delete(key);
|
|
61
|
+
gitSnapshotLastKnown.set(key, entry);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
/** One background snapshot rebuild per cwd and invalidation generation. */
|
|
65
|
+
const gitSnapshotInFlight = new Map<string, { generation: string; promise: Promise<string | null> }>();
|
|
66
|
+
|
|
67
|
+
/** Per-key monotonic store version: async rebuilds never overwrite a newer
|
|
68
|
+
* sync value, not even when both land in the same millisecond (`at`
|
|
69
|
+
* comparisons can flip). Generation guards invalidation races instead. */
|
|
70
|
+
const gitSnapshotVersion = new Map<string, number>();
|
|
71
|
+
|
|
72
|
+
function gitSnapshotVersionOf(key: string): number {
|
|
73
|
+
return gitSnapshotVersion.get(key) ?? 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function bumpGitSnapshotVersion(key: string): number {
|
|
77
|
+
const version = gitSnapshotVersionOf(key) + 1;
|
|
78
|
+
gitSnapshotVersion.set(key, version);
|
|
79
|
+
return version;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Test-only hold seam (production null): parks an async rebuild after its
|
|
83
|
+
* reads and before its store, so «a write during a rebuild wins» is provable
|
|
84
|
+
* deterministically instead of by racing timers. */
|
|
85
|
+
let gitSnapshotRebuildHold: (() => void | Promise<void>) | null = null;
|
|
86
|
+
|
|
87
|
+
export function __setGitSnapshotRebuildHoldForTest(hold: (() => void | Promise<void>) | null): void {
|
|
88
|
+
gitSnapshotRebuildHold = hold;
|
|
89
|
+
}
|
|
41
90
|
|
|
42
91
|
interface CacheEntry {
|
|
43
92
|
located: LocatedGit;
|
|
@@ -97,8 +146,15 @@ function ensureEntry(cwd: string): CacheEntry | null {
|
|
|
97
146
|
// Re-read HEAD + retarget watcher whenever a watched file changes.
|
|
98
147
|
// One handler covers all listeners so we don't race each subscriber.
|
|
99
148
|
watcher.subscribe(() => {
|
|
149
|
+
const before = entry.head;
|
|
100
150
|
entry.head = readGitHead(entry.located);
|
|
101
151
|
entry.watcher.retargetForHead(entry.head);
|
|
152
|
+
// A branch/ref move makes every cached snapshot's branch + log lines wrong. Only a real
|
|
153
|
+
// move: macOS fs.watch also replays the ref write that happened just before the watch was
|
|
154
|
+
// installed (measured: refs/heads/main «change» right after the first build), and that
|
|
155
|
+
// spurious event must not evict a fresh snapshot.
|
|
156
|
+
if (headMoved(before, entry.head)) invalidateAllGitSnapshots();
|
|
157
|
+
else debug.log('git-fs.snapshot', 'watch-event-head-unchanged', { root: entry.located.root });
|
|
102
158
|
for (const fn of entry.listeners) {
|
|
103
159
|
try { fn(); } catch { /* noop */ }
|
|
104
160
|
}
|
|
@@ -179,8 +235,8 @@ function viewOf(entry: CacheEntry): GitStatusView {
|
|
|
179
235
|
/** Non-blocking twin of `refreshDirty` for the TUI: the probes run as
|
|
180
236
|
* async subprocesses so a slow `git status` (large worktree, loaded
|
|
181
237
|
* host) never stalls key input. Same throttle; concurrent calls share
|
|
182
|
-
* one probe
|
|
183
|
-
*
|
|
238
|
+
* one probe. `force` also marks cached LLM snapshots stale and rebuilds
|
|
239
|
+
* them in the background — a known write happened. */
|
|
184
240
|
export function refreshDirtyAsync(
|
|
185
241
|
cwd: string,
|
|
186
242
|
opts: { minIntervalMs?: number; force?: boolean } = {},
|
|
@@ -188,26 +244,40 @@ export function refreshDirtyAsync(
|
|
|
188
244
|
let entry: CacheEntry | null;
|
|
189
245
|
try { entry = ensureEntry(cwd); } catch (error) { return Promise.reject(error); }
|
|
190
246
|
if (!entry) return Promise.resolve({ head: null, dirty: null, aheadBehind: null, lastDirtyProbeAt: 0 });
|
|
191
|
-
// An in-flight probe (possibly a forced, post-write one) is newer than the last stored view
|
|
247
|
+
// An in-flight probe (possibly a forced, post-write one) is newer than the last stored view —
|
|
248
|
+
// a throttled call joins it instead of returning the pre-write view (#27493 contract).
|
|
192
249
|
const running = dirtyInFlight.get(entry);
|
|
193
250
|
if (running && !opts.force) return running;
|
|
194
251
|
const min = opts.minIntervalMs ?? 2_000;
|
|
195
252
|
if (!opts.force && entry.lastDirtyProbeAt > 0 && Date.now() - entry.lastDirtyProbeAt < min) {
|
|
196
253
|
return Promise.resolve(viewOf(entry));
|
|
197
254
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
255
|
+
const probe = probeDirtyAsyncFor(entry, { fresh: !!opts.force });
|
|
256
|
+
// After the post-write probe is queued, so the snapshot rebuild joins it instead of an older one.
|
|
257
|
+
if (opts.force) invalidateGitSnapshots(cwd);
|
|
258
|
+
// Keep-warm: the dashboard's periodic (non-forced) dirty tick also re-warms a snapshot that is in
|
|
259
|
+
// use, so a turn typed after an idle stretch is served within the stale window instead of falling
|
|
260
|
+
// back to the synchronous build. Only snapshots already cached are kept warm.
|
|
261
|
+
else if (gitSnapshotCache.has(resolve(cwd)) || gitSnapshotLastKnown.has(resolve(cwd))) void refreshGitSnapshotAsync(cwd, { ifOlderThanMs: GIT_SNAPSHOT_KEEP_WARM_MS });
|
|
262
|
+
return probe;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Share the in-flight probe, unless the caller needs one that started after
|
|
266
|
+
* now (`fresh`: a known write just happened) — then queue a new probe behind it. */
|
|
267
|
+
function probeDirtyAsyncFor(entry: CacheEntry, opts: { fresh: boolean }): Promise<GitStatusView> {
|
|
268
|
+
const running = dirtyInFlight.get(entry);
|
|
269
|
+
if (running && !opts.fresh) return running;
|
|
270
|
+
const root = entry.located.root;
|
|
200
271
|
const start = (): Promise<GitStatusView> => Promise.all([probeDirtyAsync(root), probeAheadBehindAsync(root)])
|
|
201
272
|
.then(([dirty, aheadBehind]) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return viewOf(
|
|
273
|
+
entry.dirty = dirty;
|
|
274
|
+
entry.aheadBehind = aheadBehind;
|
|
275
|
+
entry.lastDirtyProbeAt = Date.now();
|
|
276
|
+
return viewOf(entry);
|
|
206
277
|
});
|
|
207
|
-
// A forced probe queues behind the running one so it reads the post-write tree.
|
|
208
278
|
const probe = (running ? running.then(start, start) : start())
|
|
209
|
-
.finally(() => { if (dirtyInFlight.get(
|
|
210
|
-
dirtyInFlight.set(
|
|
279
|
+
.finally(() => { if (dirtyInFlight.get(entry) === probe) dirtyInFlight.delete(entry); });
|
|
280
|
+
dirtyInFlight.set(entry, probe);
|
|
211
281
|
return probe;
|
|
212
282
|
}
|
|
213
283
|
|
|
@@ -217,7 +287,7 @@ export function refreshDirtyAsync(
|
|
|
217
287
|
* fresh state after mutations. Returns null outside a git repo. */
|
|
218
288
|
export function buildGitSnapshot(
|
|
219
289
|
cwd: string,
|
|
220
|
-
opts: { now?: () => number; ttlMs?: number } = {},
|
|
290
|
+
opts: { now?: () => number; ttlMs?: number; staleWhileRevalidateMs?: number } = {},
|
|
221
291
|
): string | null {
|
|
222
292
|
const now = opts.now ?? Date.now;
|
|
223
293
|
const ttlMs = opts.ttlMs ?? GIT_SNAPSHOT_TTL_MS;
|
|
@@ -228,41 +298,157 @@ export function buildGitSnapshot(
|
|
|
228
298
|
debug.log('git-fs.snapshot', 'cache-hit', { cwd, ageMs: at - cached.at });
|
|
229
299
|
return cached.value;
|
|
230
300
|
}
|
|
301
|
+
// Stale-while-revalidate (TUI turn path): serve the recent snapshot now
|
|
302
|
+
// and rebuild it off the event loop for the next turn.
|
|
303
|
+
if (cached && opts.staleWhileRevalidateMs !== undefined && at - cached.at < opts.staleWhileRevalidateMs) {
|
|
304
|
+
debug.log('git-fs.snapshot', 'stale-hit', { cwd, ageMs: at - cached.at });
|
|
305
|
+
void refreshGitSnapshotAsync(cwd);
|
|
306
|
+
return cached.value;
|
|
307
|
+
}
|
|
308
|
+
// Invalidated (known write · HEAD move) and the background rebuild has not
|
|
309
|
+
// stored yet: serve the evicted snapshot rather than a synchronous rebuild —
|
|
310
|
+
// the TYPING-LAG this path exists to remove. Bounded by the same window.
|
|
311
|
+
const evicted = !cached ? gitSnapshotLastKnown.get(key) : undefined;
|
|
312
|
+
if (evicted && opts.staleWhileRevalidateMs !== undefined && at - evicted.at < opts.staleWhileRevalidateMs) {
|
|
313
|
+
debug.log('git-fs.snapshot', 'stale-after-invalidate', { cwd, ageMs: at - evicted.at, rebuilding: gitSnapshotInFlight.has(key) });
|
|
314
|
+
void refreshGitSnapshotAsync(cwd);
|
|
315
|
+
return evicted.value;
|
|
316
|
+
}
|
|
231
317
|
|
|
232
318
|
const view = refreshDirty(cwd, { force: true });
|
|
233
319
|
let value: string | null = null;
|
|
234
320
|
if (view.head) {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
: status;
|
|
243
|
-
|
|
244
|
-
const parts = [
|
|
245
|
-
'This is the git status at the start of this turn. It is a snapshot and will not update during the turn.',
|
|
246
|
-
`Current branch: ${branch}${view.head.isWorktree ? ' (worktree)' : ''}`,
|
|
247
|
-
mainBranch ? `Main branch: ${mainBranch}` : '',
|
|
248
|
-
userName ? `Git user: ${userName}` : '',
|
|
249
|
-
view.aheadBehind
|
|
250
|
-
? `Upstream: ahead ${view.aheadBehind.ahead}, behind ${view.aheadBehind.behind}`
|
|
251
|
-
: '',
|
|
252
|
-
`Status:\n${truncatedStatus || '(clean)'}`,
|
|
253
|
-
`Recent commits:\n${recentLog || '(none)'}`,
|
|
254
|
-
].filter(Boolean);
|
|
255
|
-
value = parts.join('\n\n');
|
|
321
|
+
value = composeGitSnapshot(view, {
|
|
322
|
+
mainBranch: detectDefaultBranch(cwd),
|
|
323
|
+
status: runGit(cwd, ['status', '--short']),
|
|
324
|
+
recentLog: runGit(cwd, ['log', '--oneline', '-n', '5']),
|
|
325
|
+
userName: runGit(cwd, ['config', 'user.name']),
|
|
326
|
+
generatedAt: at,
|
|
327
|
+
});
|
|
256
328
|
}
|
|
257
329
|
|
|
258
|
-
|
|
330
|
+
storeGitSnapshot(key, { at, value });
|
|
259
331
|
debug.log('git-fs.snapshot', 'built', { cwd, ageMs: 0 });
|
|
260
332
|
return value;
|
|
261
333
|
}
|
|
262
334
|
|
|
335
|
+
function composeGitSnapshot(
|
|
336
|
+
view: GitStatusView,
|
|
337
|
+
git: { mainBranch: string | null; status: string; recentLog: string; userName: string; generatedAt: number },
|
|
338
|
+
): string {
|
|
339
|
+
const head = view.head!;
|
|
340
|
+
const branch = head.branch ?? `HEAD@${head.sha?.slice(0, 7) ?? 'unknown'}`;
|
|
341
|
+
const truncatedStatus = git.status.length > SNAPSHOT_STATUS_MAX_CHARS
|
|
342
|
+
? `${git.status.slice(0, SNAPSHOT_STATUS_MAX_CHARS)}\n... (truncated; run git status for more)`
|
|
343
|
+
: git.status;
|
|
344
|
+
const parts = [
|
|
345
|
+
`This is the git status as of ${new Date(git.generatedAt).toISOString()}. It is a snapshot and will not update during the turn.`,
|
|
346
|
+
`Current branch: ${branch}${head.isWorktree ? ' (worktree)' : ''}`,
|
|
347
|
+
git.mainBranch ? `Main branch: ${git.mainBranch}` : '',
|
|
348
|
+
git.userName ? `Git user: ${git.userName}` : '',
|
|
349
|
+
view.aheadBehind
|
|
350
|
+
? `Upstream: ahead ${view.aheadBehind.ahead}, behind ${view.aheadBehind.behind}`
|
|
351
|
+
: '',
|
|
352
|
+
`Status:\n${truncatedStatus || '(clean)'}`,
|
|
353
|
+
`Recent commits:\n${git.recentLog || '(none)'}`,
|
|
354
|
+
].filter(Boolean);
|
|
355
|
+
return parts.join('\n\n');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/** Rebuild the snapshot for `cwd` with async subprocesses and store it.
|
|
359
|
+
* Concurrent calls share one rebuild. Never throws. `ifOlderThanMs` turns it
|
|
360
|
+
* into a keep-warm tick: a cached snapshot younger than that is left alone. */
|
|
361
|
+
export function refreshGitSnapshotAsync(cwd: string, opts: { ifOlderThanMs?: number } = {}): Promise<string | null> {
|
|
362
|
+
const key = resolve(cwd);
|
|
363
|
+
const cached = gitSnapshotCache.get(key);
|
|
364
|
+
if (cached && opts.ifOlderThanMs !== undefined && Date.now() - cached.at < opts.ifOlderThanMs) {
|
|
365
|
+
return Promise.resolve(cached.value);
|
|
366
|
+
}
|
|
367
|
+
const generation = snapshotGeneration(key);
|
|
368
|
+
const running = gitSnapshotInFlight.get(key);
|
|
369
|
+
if (running && running.generation === generation) return running.promise;
|
|
370
|
+
const startedAt = Date.now();
|
|
371
|
+
const startVersion = gitSnapshotVersionOf(key);
|
|
372
|
+
const rebuild = (async (): Promise<string | null> => {
|
|
373
|
+
const entry = ensureEntry(cwd);
|
|
374
|
+
// Joins the in-flight probe; callers that need a post-write/post-move probe queue a fresh one first.
|
|
375
|
+
const view = entry ? await probeDirtyAsyncFor(entry, { fresh: false }) : getGitStatusView(cwd);
|
|
376
|
+
let value: string | null = null;
|
|
377
|
+
if (view.head) {
|
|
378
|
+
const [mainBranch, status, recentLog, userName] = await Promise.all([
|
|
379
|
+
detectDefaultBranchAsync(cwd),
|
|
380
|
+
runGitAsync(cwd, ['status', '--short']),
|
|
381
|
+
runGitAsync(cwd, ['log', '--oneline', '-n', '5']),
|
|
382
|
+
runGitAsync(cwd, ['config', 'user.name']),
|
|
383
|
+
]);
|
|
384
|
+
// «as of» = when the reads finished, not when the rebuild was queued.
|
|
385
|
+
value = composeGitSnapshot(view, { mainBranch, status, recentLog, userName, generatedAt: Date.now() });
|
|
386
|
+
}
|
|
387
|
+
// Test-only hold seam: reads are done, the store decision is next.
|
|
388
|
+
if (gitSnapshotRebuildHold) await gitSnapshotRebuildHold();
|
|
389
|
+
// An invalidation that landed mid-rebuild wins: keep the entry stale.
|
|
390
|
+
// A newer entry (e.g. a synchronous build that overlapped this rebuild) is
|
|
391
|
+
// kept — ordered by monotonic version, never by `at` (same-ms flips).
|
|
392
|
+
const current = gitSnapshotCache.get(key);
|
|
393
|
+
if (snapshotGeneration(key) === generation && !(current && current.version > startVersion)) {
|
|
394
|
+
storeGitSnapshot(key, { at: startedAt, value });
|
|
395
|
+
}
|
|
396
|
+
debug.log('git-fs.snapshot', 'rebuilt-async', { cwd, ms: Date.now() - startedAt });
|
|
397
|
+
return value;
|
|
398
|
+
})()
|
|
399
|
+
.catch(() => null)
|
|
400
|
+
.finally(() => { if (gitSnapshotInFlight.get(key)?.promise === rebuild) gitSnapshotInFlight.delete(key); });
|
|
401
|
+
gitSnapshotInFlight.set(key, { generation, promise: rebuild });
|
|
402
|
+
return rebuild;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/** Invalidation generations: a rebuild only stores its result when no
|
|
406
|
+
* invalidation (per cwd or global) landed while it was running. */
|
|
407
|
+
const gitSnapshotGeneration = new Map<string, number>();
|
|
408
|
+
let allGitSnapshotsGeneration = 0;
|
|
409
|
+
|
|
410
|
+
function snapshotGeneration(key: string): string {
|
|
411
|
+
return `${allGitSnapshotsGeneration}:${gitSnapshotGeneration.get(key) ?? 0}`;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function invalidateAllGitSnapshots(): void {
|
|
415
|
+
// Snapshots that were in use (cached or being rebuilt) are re-warmed for the next turn.
|
|
416
|
+
const inUse = new Set([...gitSnapshotCache.keys(), ...gitSnapshotInFlight.keys()]);
|
|
417
|
+
for (const key of [...gitSnapshotCache.keys()]) evictGitSnapshot(key);
|
|
418
|
+
allGitSnapshotsGeneration += 1;
|
|
419
|
+
// Probes already running read the old ref's upstream — queue one fresh probe per repo behind
|
|
420
|
+
// them, so the rebuilds below join it instead.
|
|
421
|
+
const entries = new Set<CacheEntry>();
|
|
422
|
+
for (const key of inUse) {
|
|
423
|
+
const entry = ensureEntry(key);
|
|
424
|
+
if (entry) entries.add(entry);
|
|
425
|
+
}
|
|
426
|
+
for (const entry of entries) void probeDirtyAsyncFor(entry, { fresh: true });
|
|
427
|
+
for (const key of inUse) void refreshGitSnapshotAsync(key);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/** A known write happened: the cached snapshot must not be served again.
|
|
431
|
+
* When a snapshot was in use (cached or being rebuilt), rebuild it in the
|
|
432
|
+
* background so the next turn usually still hits. */
|
|
433
|
+
function invalidateGitSnapshots(cwd: string): void {
|
|
434
|
+
const key = resolve(cwd);
|
|
435
|
+
const wasCached = evictGitSnapshot(key);
|
|
436
|
+
const wasRebuilding = gitSnapshotInFlight.has(key);
|
|
437
|
+
gitSnapshotGeneration.set(key, (gitSnapshotGeneration.get(key) ?? 0) + 1);
|
|
438
|
+
// An in-flight rebuild of the old generation will be discarded — schedule its replacement.
|
|
439
|
+
if (wasCached || wasRebuilding) void refreshGitSnapshotAsync(cwd);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function headMoved(before: GitHeadInfo | null | undefined, after: GitHeadInfo | null | undefined): boolean {
|
|
443
|
+
if (!before || !after) return before !== after;
|
|
444
|
+
return before.branch !== after.branch || before.sha !== after.sha || before.detached !== after.detached;
|
|
445
|
+
}
|
|
446
|
+
|
|
263
447
|
/** Explicitly discard cached git snapshots, including cached non-repositories. */
|
|
264
448
|
export function clearGitSnapshotCache(): void {
|
|
265
449
|
gitSnapshotCache.clear();
|
|
450
|
+
gitSnapshotLastKnown.clear();
|
|
451
|
+
allGitSnapshotsGeneration += 1;
|
|
266
452
|
}
|
|
267
453
|
|
|
268
454
|
function detectDefaultBranch(cwd: string): string | null {
|
|
@@ -281,6 +467,34 @@ function detectDefaultBranch(cwd: string): string | null {
|
|
|
281
467
|
return null;
|
|
282
468
|
}
|
|
283
469
|
|
|
470
|
+
async function detectDefaultBranchAsync(cwd: string): Promise<string | null> {
|
|
471
|
+
const symbolic = await runGitAsync(cwd, ['symbolic-ref', 'refs/remotes/origin/HEAD']);
|
|
472
|
+
if (symbolic.startsWith('refs/remotes/origin/')) {
|
|
473
|
+
return symbolic.slice('refs/remotes/origin/'.length).trim() || null;
|
|
474
|
+
}
|
|
475
|
+
for (const candidate of ['main', 'master', 'develop']) {
|
|
476
|
+
if (await gitSucceeds(cwd, ['show-ref', '--verify', '--quiet', `refs/heads/${candidate}`])) return candidate;
|
|
477
|
+
}
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function gitSucceeds(cwd: string, args: string[]): Promise<boolean> {
|
|
482
|
+
return new Promise((resolveOk) => {
|
|
483
|
+
try { execFile('git', args, { cwd, timeout: SNAPSHOT_TIMEOUT_MS }, (error) => resolveOk(!error)); }
|
|
484
|
+
catch { resolveOk(false); }
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function runGitAsync(cwd: string, args: string[]): Promise<string> {
|
|
489
|
+
return new Promise((resolveOut) => {
|
|
490
|
+
try {
|
|
491
|
+
execFile('git', args, { cwd, encoding: 'utf8', timeout: SNAPSHOT_TIMEOUT_MS, maxBuffer: 2 * 1024 * 1024 }, (error, stdout) => {
|
|
492
|
+
resolveOut(error ? '' : String(stdout ?? '').trim());
|
|
493
|
+
});
|
|
494
|
+
} catch { resolveOut(''); }
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
284
498
|
function runGit(cwd: string, args: string[]): string {
|
|
285
499
|
const res = spawnSync('git', args, {
|
|
286
500
|
cwd,
|
|
@@ -292,10 +506,23 @@ function runGit(cwd: string, args: string[]): string {
|
|
|
292
506
|
return String(res.stdout ?? '').trim();
|
|
293
507
|
}
|
|
294
508
|
|
|
509
|
+
/** Test helper — the cached snapshot for `cwd` without building one. */
|
|
510
|
+
export function __peekGitSnapshot(cwd: string): string | null | undefined {
|
|
511
|
+
return gitSnapshotCache.get(resolve(cwd))?.value;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** Test helper — what a HEAD move does to cached snapshots. */
|
|
515
|
+
export function __invalidateAllGitSnapshotsForTest(): void {
|
|
516
|
+
invalidateAllGitSnapshots();
|
|
517
|
+
}
|
|
518
|
+
|
|
295
519
|
/** Test helper — drop the cache + dispose every watcher. */
|
|
296
520
|
export function __resetGitFsCache(): void {
|
|
297
521
|
for (const [, entry] of cache) entry.watcher.dispose();
|
|
298
522
|
cache.clear();
|
|
299
523
|
clearGitSnapshotCache();
|
|
524
|
+
gitSnapshotInFlight.clear();
|
|
300
525
|
dirtyInFlight.clear();
|
|
526
|
+
gitSnapshotGeneration.clear();
|
|
527
|
+
gitSnapshotVersion.clear();
|
|
301
528
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
|
|
3
|
+
/** One measured execution at a GitHub boundary. Never put an URL, arguments, token, or body here. */
|
|
4
|
+
export interface GithubRemoteCall {
|
|
5
|
+
kind: 'rest' | 'graphql' | 'gh-command' | 'git-clone' | 'git-fetch' | 'git-push';
|
|
6
|
+
caller: string;
|
|
7
|
+
route: string;
|
|
8
|
+
method?: string;
|
|
9
|
+
host: string;
|
|
10
|
+
scopeId?: string;
|
|
11
|
+
runId?: string;
|
|
12
|
+
retry?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface GithubRemoteOutcome<T> {
|
|
16
|
+
failed: boolean;
|
|
17
|
+
result?: T;
|
|
18
|
+
error?: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface GithubRemoteCallOptions<T> {
|
|
22
|
+
/** Return an observed HTTP status only; CLI success alone is not HTTP 200. */
|
|
23
|
+
status?: (outcome: GithubRemoteOutcome<T>) => number | undefined;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
emit?: (category: string, event: string, data: Record<string, unknown>) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Execute the real call and record exactly one completion, including failures. Observation cannot change the result. */
|
|
29
|
+
export async function runGithubRemoteCall<T>(
|
|
30
|
+
call: GithubRemoteCall,
|
|
31
|
+
execute: () => Promise<T>,
|
|
32
|
+
options: GithubRemoteCallOptions<T> = {},
|
|
33
|
+
): Promise<T> {
|
|
34
|
+
const now = options.now ?? Date.now;
|
|
35
|
+
const safeNow = (): number | undefined => {
|
|
36
|
+
try { const value = now(); return Number.isFinite(value) ? value : undefined; } catch { return undefined; }
|
|
37
|
+
};
|
|
38
|
+
const started = safeNow();
|
|
39
|
+
let outcome: GithubRemoteOutcome<T> = { failed: false };
|
|
40
|
+
try {
|
|
41
|
+
const result = await execute();
|
|
42
|
+
outcome = { failed: false, result };
|
|
43
|
+
return result;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
outcome = { failed: true, error };
|
|
46
|
+
throw error;
|
|
47
|
+
} finally {
|
|
48
|
+
let status: number | undefined;
|
|
49
|
+
try { status = options.status?.(outcome); } catch { /* telemetry must not alter the call */ }
|
|
50
|
+
const ended = safeNow();
|
|
51
|
+
const data: Record<string, unknown> = {
|
|
52
|
+
kind: call.kind,
|
|
53
|
+
caller: call.caller,
|
|
54
|
+
route: call.route,
|
|
55
|
+
method: call.method ?? 'unmeasured',
|
|
56
|
+
host: call.host,
|
|
57
|
+
scopeId: call.scopeId ?? 'unmeasured',
|
|
58
|
+
runId: call.runId ?? '',
|
|
59
|
+
retry: call.retry ?? 'unmeasured',
|
|
60
|
+
status: status ?? 'unmeasured',
|
|
61
|
+
ok: !outcome.failed,
|
|
62
|
+
durationMs: started === undefined || ended === undefined ? 'unmeasured' : Math.max(0, ended - started),
|
|
63
|
+
};
|
|
64
|
+
try { (options.emit ?? debug.log.bind(debug))('github.transport', 'complete', data); } catch { /* same rule */ }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Only a real GitHub remote belongs in the Git transport denominator. */
|
|
69
|
+
export function isGithubGitRemote(remote: string): boolean {
|
|
70
|
+
let host: string | undefined;
|
|
71
|
+
if (remote.includes('://')) {
|
|
72
|
+
try {
|
|
73
|
+
const url = new URL(remote);
|
|
74
|
+
if (!['http:', 'https:', 'ssh:', 'git:'].includes(url.protocol)) return false;
|
|
75
|
+
host = url.hostname;
|
|
76
|
+
} catch { return false; }
|
|
77
|
+
} else {
|
|
78
|
+
host = /^(?:[^@\s]+@)?([^:/\s]+):[^\s]+$/.exec(remote)?.[1];
|
|
79
|
+
}
|
|
80
|
+
return host === 'github.com' || host === 'ssh.github.com';
|
|
81
|
+
}
|
package/src/goals/registry.ts
CHANGED
|
@@ -75,8 +75,18 @@ export function hydrateGoalFromSnapshot(): Goal | null {
|
|
|
75
75
|
persistSnapshot(null);
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
// TUI-GOAL-LOOP-FRICTION(#35) — 프로세스가 죽어 있던 시간은 이 목표가 «돈» 시간이 아니다.
|
|
79
|
+
// active 로 되살아나면 벽시계 기준을 지금으로 다시 잡는다(낡은 createdAt 기준 4.9억 ms 소진 오판 방지).
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
const staleStart = goalWallClockStart(parsed);
|
|
82
|
+
current = parsed.status === 'active'
|
|
83
|
+
? { ...parsed, activeSince: now, usage: { ...parsed.usage, elapsedMs: 0 } }
|
|
84
|
+
: parsed;
|
|
85
|
+
debug.log('goal', 'snapshot.hydrated', {
|
|
86
|
+
id: current.id, status: current.status,
|
|
87
|
+
wallClockRestarted: parsed.status === 'active',
|
|
88
|
+
staleElapsedMs: Math.max(0, now - staleStart),
|
|
89
|
+
});
|
|
80
90
|
notify(current, null);
|
|
81
91
|
return getCurrentGoal();
|
|
82
92
|
} catch (error) {
|
|
@@ -100,12 +110,25 @@ export function generateGoalId(): string {
|
|
|
100
110
|
return `g-${ts}-${rand}`;
|
|
101
111
|
}
|
|
102
112
|
|
|
113
|
+
/** TUI-GOAL-LOOP-FRICTION(#35) — 벽시계 예산의 기준 시각 = 이번에 active 로 들어선 때.
|
|
114
|
+
* 옛 스냅숏(activeSince 없음)만 createdAt 으로 떨어진다. */
|
|
115
|
+
export function goalWallClockStart(goal: Goal): number {
|
|
116
|
+
return typeof goal.activeSince === 'number' && Number.isFinite(goal.activeSince)
|
|
117
|
+
? goal.activeSince
|
|
118
|
+
: goal.createdAt;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** 이번 활성화 기준 벽시계 경과(ms). 시계가 거꾸로 가도 음수는 내지 않는다. */
|
|
122
|
+
export function goalWallClockElapsedMs(goal: Goal, now: number): number {
|
|
123
|
+
return Math.max(0, now - goalWallClockStart(goal));
|
|
124
|
+
}
|
|
125
|
+
|
|
103
126
|
export function getCurrentGoal(): Goal | null {
|
|
104
127
|
if (!current) return null;
|
|
105
128
|
// Refresh elapsed ms on read so callers don't see stale values.
|
|
106
129
|
return {
|
|
107
130
|
...current,
|
|
108
|
-
usage: { ...current.usage, elapsedMs: Date.now()
|
|
131
|
+
usage: { ...current.usage, elapsedMs: goalWallClockElapsedMs(current, Date.now()) },
|
|
109
132
|
};
|
|
110
133
|
}
|
|
111
134
|
|
|
@@ -155,6 +178,7 @@ export function startGoal(input: GoalCreateInput): { ok: true; goal: Goal } | {
|
|
|
155
178
|
status: 'active',
|
|
156
179
|
createdAt: now,
|
|
157
180
|
updatedAt: now,
|
|
181
|
+
activeSince: now,
|
|
158
182
|
budget,
|
|
159
183
|
usage: { turnsUsed: 0, tokensUsed: 0, tokensMeasured: true, elapsedMs: 0 },
|
|
160
184
|
linkedTaskId: input.linkedTaskId,
|
|
@@ -173,8 +197,22 @@ export function setStatus(next: GoalStatus, reason?: string): { ok: true; goal:
|
|
|
173
197
|
return { ok: false, error: { code: 'GoalNotFound', message: 'No active goal.' } };
|
|
174
198
|
}
|
|
175
199
|
const prev = { ...current };
|
|
176
|
-
|
|
200
|
+
const now = Date.now();
|
|
201
|
+
// TUI-GOAL-LOOP-FRICTION(#35) — paused·budget-limited·resume_required → active 는 «새 활성화»다.
|
|
202
|
+
// 벽시계는 여기서 다시 잰다 — 멈춰 있던 시간(며칠)을 이번 실행 예산에 싣지 않는다.
|
|
203
|
+
const reactivated = next === 'active' && prev.status !== 'active';
|
|
204
|
+
current = {
|
|
205
|
+
...current,
|
|
206
|
+
status: next,
|
|
207
|
+
updatedAt: now,
|
|
208
|
+
...(reactivated ? { activeSince: now, usage: { ...current.usage, elapsedMs: 0 } } : {}),
|
|
209
|
+
};
|
|
177
210
|
debug.log('goal', 'status', { id: current.id, from: prev.status, to: next, reason: reason ?? '' });
|
|
211
|
+
if (reactivated) {
|
|
212
|
+
debug.log('goal', 'wall-clock-restart', {
|
|
213
|
+
id: current.id, from: prev.status, priorElapsedMs: goalWallClockElapsedMs(prev, now),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
178
216
|
try {
|
|
179
217
|
writeGoalTransitionLedger({
|
|
180
218
|
timestamp: new Date().toISOString(),
|
|
@@ -210,7 +248,7 @@ export function recordTurn(opts: { tokens?: number; verdict?: Goal['lastVerdict'
|
|
|
210
248
|
turnsUsed: current.usage.turnsUsed + 1,
|
|
211
249
|
tokensUsed: current.usage.tokensUsed + (opts.tokens ?? 0),
|
|
212
250
|
tokensMeasured: current.usage.tokensMeasured && opts.tokens !== undefined,
|
|
213
|
-
elapsedMs: Date.now()
|
|
251
|
+
elapsedMs: goalWallClockElapsedMs(current, Date.now()),
|
|
214
252
|
},
|
|
215
253
|
lastVerdict: opts.verdict ?? current.lastVerdict,
|
|
216
254
|
lastSummary: opts.summary ?? current.lastSummary,
|
|
@@ -251,7 +289,9 @@ const NO_GOAL_BUDGET_DIAGNOSTICS: GoalBudgetDiagnostics = {
|
|
|
251
289
|
export function evaluateGoalBudget(goal: Goal, now: number): GoalBudgetDiagnostics {
|
|
252
290
|
const { turnsUsed, tokensUsed, elapsedMs, tokensMeasured } = goal.usage;
|
|
253
291
|
const { maxTurns, tokenBudget, wallClockMaxMs } = goal.budget;
|
|
254
|
-
|
|
292
|
+
// TUI-GOAL-LOOP-FRICTION(#35) — 기준 = 이번 활성화 시작(activeSince · 옛 스냅숏만 createdAt).
|
|
293
|
+
// usage.elapsedMs 도 같은 기준으로만 쓰인다(재활성화·hydrate 때 0 으로 되돌린다).
|
|
294
|
+
const elapsedWallClockMs = Math.max(elapsedMs, goalWallClockElapsedMs(goal, now));
|
|
255
295
|
const exceededAxes = [
|
|
256
296
|
...(turnsUsed >= maxTurns ? [{ axis: 'maxTurns' as const, used: turnsUsed, limit: maxTurns }] : []),
|
|
257
297
|
...(tokenBudget > 0 && tokensUsed >= tokenBudget
|
package/src/goals/types.ts
CHANGED
|
@@ -69,7 +69,8 @@ export interface GoalUsage {
|
|
|
69
69
|
tokensUsed: number;
|
|
70
70
|
/** Whether every recorded auto-turn supplied a token measurement. */
|
|
71
71
|
tokensMeasured: boolean;
|
|
72
|
-
/** Wall-clock since
|
|
72
|
+
/** Wall-clock since this activation began (`activeSince`, falling back to
|
|
73
|
+
* `createdAt` for old snapshots), refreshed on read. */
|
|
73
74
|
elapsedMs: number;
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -97,6 +98,11 @@ export interface Goal {
|
|
|
97
98
|
status: GoalStatus;
|
|
98
99
|
/** Epoch ms. */
|
|
99
100
|
createdAt: number;
|
|
101
|
+
/** TUI-GOAL-LOOP-FRICTION(#35) — epoch ms when the goal last entered `active`
|
|
102
|
+
* (start · resume · process restart hydrate). The wall-clock budget is measured
|
|
103
|
+
* from here, not from `createdAt`: a goal created days ago and resumed now must
|
|
104
|
+
* not report 4.9e8 ms elapsed. Optional so older snapshots still parse. */
|
|
105
|
+
activeSince?: number;
|
|
100
106
|
/** Last time status transitioned. */
|
|
101
107
|
updatedAt: number;
|
|
102
108
|
budget: GoalBudget;
|
|
@@ -34,6 +34,7 @@ const RELEASE_NODE_COMMANDS: Readonly<Record<string, { recipe: string; command?:
|
|
|
34
34
|
'checklist-gate': { recipe: 'cmd:checklist-gate', command: 'bun scripts/release-loop/checklist-gate-node.ts' },
|
|
35
35
|
prefetch: { recipe: 'cmd:docs', command: 'bun scripts/release-loop/docs-node.ts --json' },
|
|
36
36
|
gate: { recipe: 'cmd:gate', command: 'bun scripts/release-loop/gate-node.ts --json' },
|
|
37
|
+
'gate-triage': { recipe: 'cmd:gate-triage', command: 'bun scripts/release-loop/gate-triage-node.ts' },
|
|
37
38
|
'mac-smoke': { recipe: 'cmd:mac-smoke', command: 'bun scripts/release-loop/mac-smoke-node.ts' },
|
|
38
39
|
'export-check': { recipe: 'cmd:export-check', command: 'bun scripts/release-loop/export-check-node.ts' },
|
|
39
40
|
pwa: { recipe: 'cmd:pwa', command: 'bun scripts/release-loop/node-verdict.ts pwa' },
|
package/src/grok/credential.ts
CHANGED
|
@@ -478,6 +478,32 @@ export function isGrokSubscriptionExpiring(
|
|
|
478
478
|
return (opts.now ?? Date.now)() + (opts.bufferMs ?? GROK_REFRESH_BUFFER_MS) >= ms;
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
/** 구독 만료 상태 — 칸 CRED-EXPIRY-REFRESH 기준 창. 이 안에 만료가 오면 갱신 후보다. */
|
|
482
|
+
export const GROK_EXPIRY_SOON_WINDOW_MS = 2 * 60 * 60 * 1000;
|
|
483
|
+
|
|
484
|
+
/** 만료 상태 셋 — ⛔ boolean 으로 접으면 「모름」과 «여유»가 «같은 값»이 된다. */
|
|
485
|
+
export type GrokSubscriptionExpiryState = 'healthy' | 'expiring' | 'unknown';
|
|
486
|
+
|
|
487
|
+
/** 실제로 쓸 구독(key 를 가진 scope 중 가장 늦게 만료되는 것)의 expires_at 만으로 상태를 가른다.
|
|
488
|
+
*
|
|
489
|
+
* ⭐ 칸 CRED-EXPIRY-REFRESH 첫 조각 — «토큰 없이» 읽는다:
|
|
490
|
+
* · 선택 규칙은 `readSubscriptionToken` 과 «같다»(key 없는 항목의 만료에 속지 않는다).
|
|
491
|
+
* · 반환은 상태 «하나»뿐 — 토큰 값은 어떤 형태로도 나가지 않는다.
|
|
492
|
+
* · 기존 `isGrokSubscriptionExpiring`(boolean)은 모름을 false 로 접는다 — 이 함수는
|
|
493
|
+
* 모름을 'unknown' 으로 «별도의 값»으로 낸다. 갱신 유도·호스트 발사는 후속 조각.
|
|
494
|
+
* · 순수 판정 — 부수효과가 없고, 파일이 못 읽히면 죽이지 않고 'unknown' 을 낸다. */
|
|
495
|
+
export function grokSubscriptionExpiryState(
|
|
496
|
+
opts: { home?: string; bufferMs?: number; now?: () => number } = {},
|
|
497
|
+
): GrokSubscriptionExpiryState {
|
|
498
|
+
const raw = readSubscriptionToken(grokAuthFilePath(opts.home))?.expiresAt ?? null;
|
|
499
|
+
if (raw === null) return 'unknown';
|
|
500
|
+
const ms = Date.parse(raw);
|
|
501
|
+
if (!Number.isFinite(ms)) return 'unknown';
|
|
502
|
+
return (opts.now ?? Date.now)() + (opts.bufferMs ?? GROK_EXPIRY_SOON_WINDOW_MS) >= ms
|
|
503
|
+
? 'expiring'
|
|
504
|
+
: 'healthy';
|
|
505
|
+
}
|
|
506
|
+
|
|
481
507
|
/** 갱신 경로의 관측 — ⛔ 토큰은 «절대» 싣지 않는다(판정·결과·출처만). */
|
|
482
508
|
function observeGrokAuth(event: string, data: Record<string, unknown>): void {
|
|
483
509
|
try {
|