elanous 0.2.43 → 0.2.44
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/{Om5xS9jpjSXJCeTNGYEi4 → HMXsxdy5MIIcHPMHv1wD4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{3557ac4a.c8931684475018ad.js → 08334415.f0e80896acbef722.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1032-78ba4f6391258cab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1082-53f86a26e03d309d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1109-7d0e264f6f2edbc7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1124-7c26330402481143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/118.2a89982fe4276880.js +23 -0
- package/apps/pwa/out/_next/static/chunks/1244.6c435dbf1bf21d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1252.9e665904d3aa3b1a.js +32 -0
- package/apps/pwa/out/_next/static/chunks/1266.a46cc33cb6a72d75.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{3955.6922286237f2ac2b.js → 1306.967240ede9a0f757.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1344.3b95f3bd1b77a3fe.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{5628.6ddb2d5ffba4ff4c.js → 1401.22dfe92640a2b1ac.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/1431-f7c78bd5be21e011.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1451-cdd35a8a0b31834b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2573.387a707f6f9d720c.js → 1694.18debfd77562e56d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1708-f03d587b7a7545c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1775-fa7152bdeff6c95f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/178-4da509cd7266672a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7910-6f139bcafd238b9f.js → 1850-522de4ee34957210.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1876-c6f6e0ddcc76c6a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1976.097066b072432242.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1406.a1dc2ab6f8449374.js → 1978.eeb60a606dc5deac.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3402.44b565b314f2263c.js → 2043.e233e3b5a3e790f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2150.71b94e3348107c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2158.ebc6fc5a10280ab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3694.e0099884345f0198.js → 2216.802962c04f40a26e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2294.7890edcfa046c97d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/235.c89aaae4bcd6233a.js +74 -0
- package/apps/pwa/out/_next/static/chunks/239.de075467b5523469.js +287 -0
- package/apps/pwa/out/_next/static/chunks/{1200.6a37c202f9f17e9a.js → 249.ba7051590d603c8f.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/2571.a6ac4e26c8618403.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2610.e149cd564a08913e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2705.9816f3c244f8b85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2801.afeb8a4dae22f85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3935.16701e33f8982dc9.js → 2954.bbefc95d6b20e0d8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{aa57532f.510551854ff239b1.js → 2e0f720a.a0697c08e3806a60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3042.96ec235fe41c8d4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3097-8e358f158acef46b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3205-93b1abe28b4fb16a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3273.b4434f0dcae7eb29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3311.9cbc43ea0c90d60c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5930.8b4df3b46c32b05a.js → 3349.b5f09ee474d9533e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5866.366966af47fdde5d.js → 3503.a47a9755fb4d97b0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3506-5f429b3b7e1392b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7900.096f455c7c1efc53.js → 3843.bad404d008893291.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3877-4b40e530b47e3bf9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/435-ce2958253cf7de61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8588.d1c6a2903727ce87.js → 4393.28fa5228d0eec217.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4404.7281c847c6e10dfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8062-7cd0bcc7f01455ba.js → 4415-b9d6a90960920a4a.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{8313-dfa1021bb58a46d6.js → 447-5b304de1fe098f43.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4484-8ebea83d431e6fae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6944.309f4e3ea54d1537.js → 4502.bdcc877abd437a05.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-f95790fc5c65b8df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3072.01338851ca21a6f7.js → 46.57c783fa4884714f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/463-b9114e411f33728e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4659.a57d1f0c5d754cd2.js +36 -0
- package/apps/pwa/out/_next/static/chunks/4722-a847e7a28115035f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8986.8e2e4efbfa655c59.js → 4757.67c6d7473a038e78.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4874-c86f878ec4502ad3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4891.3f80ba517a3b2373.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8205.282ca4bb62d54a0a.js → 4998.810ca8833084caa9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4f98febc.ea5841d4d616bfb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5789.2da35c258292e1e5.js → 5052.7dbb12a55d4f18f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5166-ca73b3e361085a6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5180-039f4a18b07ad387.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5232.5a2ce4daf7a9e11d.js +115 -0
- package/apps/pwa/out/_next/static/chunks/{9770.5f75bc6088b16109.js → 5439.3fec6dbce29ecb36.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1313-19f737e0222c4444.js → 5612-074d9a5e00dfac6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5675-01989d524a84c505.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5751.af641a1adf5ec697.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5758-c6cb98714d18ab0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/578eded8.b582637306e16964.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{3969.272ee7f9fd6c62e5.js → 5790.5eb06a653ebd8571.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5853-4033e5bd5afbe06b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904.97d70bb7f46b2db7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6540.c7bef57ad8f90a87.js → 5989.7ecd362c5c44b747.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{0ad6802e.ae7afb63fdcb4491.js → 5a34fb2f.52f1b4e1baebb48a.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{0966f8a1.745fcd44f64a87ea.js → 5a5078f8.2099200e5ea95e16.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6036-c302c34ff0b3d410.js +1 -0
- package/apps/pwa/out/_next/static/chunks/606.ef81c313381f4264.js +1 -0
- package/apps/pwa/out/_next/static/chunks/616.1af54a928b1ba704.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6201.bc936f71f613a8e9.js +41 -0
- package/apps/pwa/out/_next/static/chunks/6204-fdc86e0e64c4f92d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2144.25b292396712196d.js → 6245.1182e007e9d230d9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{363bfab3.9623b9f89363541f.js → 63699a35.17262e162bc514b2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6420.494801a80030160c.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{d96660fb.cbc21a2a88539dbb.js → 6549dad0.2740b25e51bf8f05.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{5564.9e72532188f57586.js → 6881.9e7955847640c7fe.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/6931.fcdfb94141e67b3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6991-8e081c6ce38c0ba1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3903.3ef4656c67572764.js → 7010.1bbd17a7f2b3e376.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7029.d1466acf55fae2ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7152-a123aa8e129c131f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7455.196168fffac3b9c4.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7638.6ca4770dd1129138.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7649-f37d76260e5e2a5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2312.0c8b61e22d3136d7.js → 7679.32c40cdd14f20b4a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7751.04bfbd16b4c6cd0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7864.b1ff31d4030b8994.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7869-c47bd2c075c1fefa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4199.ce86b281fd0a60b7.js → 8442.2f09ca969d631615.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8445.2738dbd59a78c78c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8447.5510c439f9938c6d.js +286 -0
- package/apps/pwa/out/_next/static/chunks/8551.f762945c2cda2e95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8635-57a9d8d9db70f4f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{fb7d20d5-6892502b6ee39ca6.js → 86961958-4b0689a5048f756b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8709.3c6019bb18f8554f.js +8 -0
- package/apps/pwa/out/_next/static/chunks/8759.c999528a0a907bf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/87f498e5-0881de09f2e44707.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8843.c3197f904c952b81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{cb0f8df8.09a4a6be97e3fc5f.js → 892fd990.456232f326cc39c2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{837-81336ebaca8198a8.js → 8965-135a2c9eaa2464cb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8971-8d3b9c96f8a6c958.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9059.c8598d96f8e5e9cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9115.90447ae198b84eae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9147.d9b0a02e0babc9b4.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9204-83075f4b70c61cdc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9244-c32ef14b5dc72bdf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/930.2a9a30f964350c66.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{8637.90f92d5c8db4732c.js → 9398.1f56e3f17795f43f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9527.3e5ad31c891c5fcb.js +79 -0
- package/apps/pwa/out/_next/static/chunks/9571-4ac933e774d1225c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-0c9dace2db62bee8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f5e65c3dc9d89f2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-2a9c19b9a140b7b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-61533ad92141adfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-112004ced6fd0329.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f733318c237a49d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-51ea677d2d33bbc0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-428b41f2f9566e3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1b29396ea90a61e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-cf83ec613ac904bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-3f4c0ecbc284bb5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b63c322f54f70cc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-fe328c4ee9aac6b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-bfb855c584f0fb98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-47b1710c110eabd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-42895214458bc6d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d03de0ebd8366e23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-3ed6c47e4b1c61c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-ae653e9bf261c738.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-23f3f0a0209c0ac4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-88c691273aae66f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e187ac52a95538b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6e45828daed1295e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-edb5d7287bb46186.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4a7eaacd93c3f6a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ca073d43d74cc84.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1e9fee67b1199436.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-df1283ea963c6816.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-19fcf8d8301ccd18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-5ab699e0303bbb40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7cde0d29756984c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9d4c598e8ee22f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-cc1609a71f44ec62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7659a9a1345bfaa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0afef60ecc0c4af5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a3553949f8f34f5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-057a69702f3c67c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-c0f0e570f3f74c73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-1825071ae34e3b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6244e3e135d8ccfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-0a815f34367b6db6.js → page-da787e8a10b8a82e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-1316d32498e2be42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-4df94572e343de2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-708969f7475e88c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c58add08c919a1dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-a24847f45e5d5bf9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-acfec65a3a60e22e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-3dfc598e6fbde245.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-c658a626118411b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-4c73685fd891445b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-6310f7e5de7dd01d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-51c326bf48610be1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-d0beadf754da59b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-acd243bfbf3f6732.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/overlays/README.md +6 -0
- package/graphs/release/release-loop.yaml +33 -17
- package/graphs/units/verbs/make-doc.yaml +1 -0
- package/package.json +1 -1
- package/scripts/bench-metering-plan.ts +229 -0
- package/scripts/demo/demo1104-parallel-host.ts +56 -0
- package/scripts/demo/demo1104-parallel.ts +72 -0
- package/scripts/public-leak-baseline.txt +0 -1
- package/scripts/release-loop/docs-node.ts +4 -2
- package/scripts/release-loop/gate-image-pin.ts +116 -2
- package/scripts/release-loop/gate-node.ts +217 -25
- package/scripts/release-loop/gate-progress-sim.ts +73 -0
- package/scripts/release-loop/notes-repair.ts +18 -1
- package/scripts/release-loop/preflight.ts +188 -8
- package/scripts/release-loop/render-warm-control-manifest.ts +22 -0
- package/scripts/release-loop/resume-release.ts +9 -7
- package/scripts/release-loop/resume.ts +13 -4
- package/scripts/release-loop/warm-control-forward.ts +178 -0
- package/scripts/retro-cycle.ts +30 -8
- package/scripts/rhythm/daily.ts +4 -1
- package/scripts/rhythm/linear-progress-sync.ts +28 -15
- package/scripts/ux-sim.ts +7 -1
- package/scripts/warm-pool-provider-config.ts +6 -1
- package/src/agent-mission/grok-auth-status.ts +78 -18
- package/src/agent-mission/mission-out.ts +2 -2
- package/src/agent-substrate/pr-reviewer.ts +147 -11
- package/src/agent-substrate/self-review-cli.ts +10 -2
- package/src/auto-research/research-fanout.ts +221 -0
- package/src/auto-research/research-turn.ts +282 -36
- package/src/autopilot/mission-codebase-gate.ts +7 -3
- package/src/cli/control-cli.ts +15 -6
- package/src/cli/log-event-names.ts +8 -0
- package/src/cli/setup-keys.ts +20 -8
- package/src/cli/tui-test-cli.ts +9 -5
- package/src/control-plane/ledger.ts +42 -4
- package/src/control-plane/member-tokens.ts +25 -2
- package/src/control-plane/ports.ts +8 -3
- package/src/control-plane/server.ts +26 -5
- package/src/core-turn/research-policy.ts +7 -1
- package/src/core-turn/run-core-turn.ts +186 -39
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +113 -24
- package/src/dashboard/classic-sidetab-mission-pair.ts +3 -2
- package/src/dashboard/classic-sidetab-mission-trio.ts +35 -12
- package/src/dashboard/classic-sidetab-mission.ts +2 -0
- package/src/dashboard/index.ts +9 -1
- package/src/dashboard/sidetab-runtime.ts +2 -0
- package/src/dashboard/visible-mission-diagnostics.ts +16 -0
- package/src/domains/retro-cycle-observation.ts +43 -0
- package/src/domains/retro-cycle.ts +13 -2
- package/src/domains/retro-proposals.ts +92 -0
- package/src/domains/retro-report.ts +6 -1
- package/src/graph-runner/graph-cli.ts +24 -1
- package/src/graph-runner/graph-grow-llm.ts +3 -1
- package/src/graph-runner/runner.ts +226 -30
- package/src/harness/harness-cli-command.ts +4 -2
- package/src/harness/harness-pod-dispatch.ts +3 -0
- package/src/index.ts +2 -2
- package/src/llm/child-first-llm-observation.ts +112 -0
- package/src/llm/provider-credentials.ts +60 -4
- package/src/llm/provider-failure-evidence.ts +44 -0
- package/src/llm.ts +170 -11
- package/src/mcp/client.ts +7 -0
- package/src/mcp/proxy-runtime.ts +6 -1
- package/src/mcp/server.ts +54 -0
- package/src/native-tool-catalog.ts +2 -2
- package/src/nexus/api/consult-requests.ts +18 -6
- package/src/nexus/api/discord-trigger-bot.ts +6 -6
- package/src/nexus/api/graphs-api.ts +4 -2
- package/src/nexus/api/grokbot-trigger-bot.ts +206 -0
- package/src/nexus/api/telegram-trigger-bot.ts +6 -6
- package/src/nexus/boot/register-mcp-clients.ts +114 -8
- package/src/nexus/index.ts +15 -0
- package/src/nexus/outbound/grokbot-adapter.ts +71 -0
- package/src/nexus/outbound/router.ts +33 -13
- package/src/oauth/codex-owner-mirror.ts +47 -10
- package/src/onboarding/first-run.ts +44 -6
- package/src/preview/terminal.ts +22 -7
- package/src/prompt-enhance/enhance.ts +10 -0
- package/src/pty-shell/pty-write-provenance.ts +21 -3
- package/src/pty-shell/registry.ts +9 -2
- package/src/release-loop/proposal-auto-place.ts +83 -0
- package/src/research/axis-fanout.ts +40 -5
- package/src/research/lenses/second-order.ts +312 -0
- package/src/self-dev/dev-cli.ts +3 -1
- package/src/self-dev/draft-sweep.ts +31 -10
- package/src/self-dev/draft-triage-rules.ts +60 -3
- package/src/self-dev/run-supervisor.ts +152 -2
- package/src/self-implement/goal-author.ts +208 -23
- package/src/self-implement/graph-overlay-yaml.ts +151 -0
- package/src/self-implement/graph-yaml.ts +68 -2
- package/src/self-implement/orchestrator.ts +62 -15
- package/src/self-implement/test-scenario-request.ts +37 -6
- package/src/session/chat.ts +2 -2
- package/src/session-runtime/index.ts +37 -5
- package/src/sidetab-core/model.ts +205 -10
- package/src/sidetab-core/visible-agent-mission-pair.ts +51 -0
- package/src/sidetab-core/visible-agent-mission.ts +105 -47
- package/src/skills/tools/omni-search.ts +4 -2
- package/src/task-agent/parent-host.ts +19 -1
- package/src/task-agent/recall-inject.ts +98 -0
- package/src/task-agent/task-hand.ts +26 -7
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +19 -1
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +15 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +21 -9
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +460 -96
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +45 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +38 -8
- package/src/tool-hints/gate.ts +45 -14
- package/src/tool-hints/signals.ts +1 -1
- package/src/tool-hints/types.ts +2 -0
- package/src/tool-runtime/browser-hand-runtime.ts +11 -1
- package/src/tool-runtime/browser-runtime.ts +31 -18
- package/src/tool-runtime/elanous-linear-secretary-runtime.ts +152 -36
- package/src/tool-runtime/types.ts +2 -0
- package/src/tui/entry.ts +27 -7
- package/src/tui/sidetab/attach.ts +112 -0
- package/src/tui/sidetab/list.ts +3 -2
- package/src/tui-client/next-dashboard-runtime.ts +52 -0
- package/src/ux-sim/draft-inventory-builder.ts +2 -1
- package/src/ux-sim/linear-secretary.ts +4 -12
- package/src/ux-sim/mock-scenario-catalog.json +32 -29
- package/src/ux-sim/mock-scenario-catalog.ts +55 -3
- package/src/ux-sim/release-sim-rig.ts +62 -18
- package/src/ux-sim/service-key-setup.ts +63 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1961.a81b12872c3e93a9.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +0 -90
- package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3113.d7472bbc27d580c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +0 -1
- package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4445.7990c76b3751a918.js +0 -115
- package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +0 -36
- package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +0 -287
- package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +0 -74
- package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/868.6e953be05bcf6dca.js +0 -41
- package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8861-cc1fa1c7b920fa8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +0 -1
- package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +0 -1
- package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +0 -32
- package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +0 -8
- package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-79a8b5fee4c20871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ca2d09128c585ca4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +0 -1
- package/apps/pwa/out/_next/static/chunks/c7945435-b44d4dbe90ba0dcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +0 -1
- /package/apps/pwa/out/_next/static/{Om5xS9jpjSXJCeTNGYEi4 → HMXsxdy5MIIcHPMHv1wD4}/_ssgManifest.js +0 -0
|
@@ -21,6 +21,7 @@ nodes:
|
|
|
21
21
|
# Public export is checked before expensive prefetch/gate work; a leak stops the release immediately.
|
|
22
22
|
- { node_id: export-check, kind: gate, recipe: 'cmd:export-check', max_visits: 1 }
|
|
23
23
|
- { node_id: prefetch, kind: agent, recipe: 'cmd:docs', max_visits: 1 }
|
|
24
|
+
- { node_id: pre-gate-join, kind: gate, recipe: none, max_visits: 1 }
|
|
24
25
|
- { node_id: gate, kind: gate, recipe: 'cmd:gate', max_visits: 1, notify: { on: [fail] } }
|
|
25
26
|
# Deterministic, best-effort traffic transition; it never changes the release verdict.
|
|
26
27
|
- { node_id: traffic-gate-passed, kind: gate, recipe: 'cmd:traffic-gate-passed', max_visits: 1 }
|
|
@@ -28,6 +29,7 @@ nodes:
|
|
|
28
29
|
- { node_id: gate-triage, kind: judge, recipe: 'cmd:gate-triage', max_visits: 1 }
|
|
29
30
|
- { node_id: mac-smoke, kind: gate, recipe: 'cmd:mac-smoke', max_visits: 1 }
|
|
30
31
|
- { node_id: pwa, kind: gate, recipe: 'cmd:pwa', max_visits: 1, notify: { on: [fail] } }
|
|
32
|
+
- { node_id: pre-prepare-join, kind: gate, recipe: none, max_visits: 1 }
|
|
31
33
|
- { node_id: prepare, kind: agent, recipe: 'cmd:prepare', max_visits: 1, notify: { on: [fail] } }
|
|
32
34
|
- { node_id: upgrade, kind: gate, recipe: 'cmd:upgrade', max_visits: 1 }
|
|
33
35
|
- { node_id: tui, kind: gate, recipe: 'cmd:docs', max_visits: 1 }
|
|
@@ -44,13 +46,13 @@ nodes:
|
|
|
44
46
|
- { node_id: npm-publish, kind: git, recipe: 'cmd:npm-publish', max_visits: 1 }
|
|
45
47
|
- { node_id: traffic-npm-published, kind: gate, recipe: 'cmd:traffic-npm-published', max_visits: 1 }
|
|
46
48
|
- { node_id: docs-land, kind: git, recipe: 'cmd:docs-land', max_visits: 1 }
|
|
49
|
+
- { node_id: release-post-publish-join, kind: gate, recipe: none, max_visits: 1 }
|
|
47
50
|
- { node_id: verify, kind: gate, recipe: 'cmd:verify', max_visits: 1, notify: { on: [ok, fail] } }
|
|
48
51
|
- { node_id: traffic-verify-complete, kind: gate, recipe: 'cmd:traffic-verify-complete', max_visits: 1 }
|
|
49
52
|
- { node_id: vault-note, kind: gate, recipe: 'cmd:vault-note', max_visits: 1 }
|
|
50
53
|
- { node_id: release-story, kind: gate, recipe: 'cmd:release-story', max_visits: 1 }
|
|
51
54
|
- { node_id: ops-upgrade, kind: agent, recipe: 'cmd:ops-upgrade', max_visits: 1 }
|
|
52
55
|
- { node_id: version-dev-bump, kind: git, recipe: 'cmd:version-dev-bump', max_visits: 1 }
|
|
53
|
-
- { node_id: version-dev-bump-after-failure, kind: git, recipe: 'cmd:version-dev-bump', max_visits: 1 }
|
|
54
56
|
- { node_id: traffic-failed-restore, kind: gate, recipe: 'cmd:traffic-failed-restore', max_visits: 1 }
|
|
55
57
|
- { node_id: done, kind: gate, max_visits: 1 }
|
|
56
58
|
- { node_id: failed, kind: gate, max_visits: 1 }
|
|
@@ -58,18 +60,29 @@ edges:
|
|
|
58
60
|
- { from: version-release, on: outcome, map: { ok: traffic-cut-start, fail: failed, error: failed } }
|
|
59
61
|
# Advisory traffic writes report failure to OP; release steps still proceed on fail/error.
|
|
60
62
|
- { from: traffic-cut-start, on: outcome, map: { ok: cutoff, fail: cutoff, error: cutoff } }
|
|
61
|
-
- { from: cutoff, on: outcome, map: { ok:
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
- { from: cutoff, on: outcome, map: { ok: export-check, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
64
|
+
- from: export-check
|
|
65
|
+
on: outcome
|
|
66
|
+
map: { fail: traffic-failed-restore, error: traffic-failed-restore }
|
|
67
|
+
# This single edge launches checklist-gate and prefetch concurrently; the join routes checklist failures to restore.
|
|
68
|
+
branches: { ok: [checklist-gate, prefetch] }
|
|
69
|
+
warning_branches: [prefetch]
|
|
70
|
+
join: pre-gate-join
|
|
71
|
+
# Export is required before fanout; checklist and prefetch then run together, with prefetch warning-only.
|
|
72
|
+
- { from: pre-gate-join, on: outcome, map: { ok: gate, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
66
73
|
- { from: gate, on: outcome, map: { ok: traffic-gate-passed, fail: gate-triage, error: gate-triage } }
|
|
67
74
|
# Warning-only: the transition result stays truthful; every outcome continues to the next release node.
|
|
68
|
-
-
|
|
75
|
+
- from: traffic-gate-passed
|
|
76
|
+
on: outcome
|
|
77
|
+
branches:
|
|
78
|
+
ok: [mac-smoke, pwa]
|
|
79
|
+
fail: [mac-smoke, pwa]
|
|
80
|
+
error: [mac-smoke, pwa]
|
|
81
|
+
warning_branches: [mac-smoke]
|
|
82
|
+
join: pre-prepare-join
|
|
69
83
|
- { from: gate-triage, on: outcome, map: { ok: traffic-failed-restore, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
70
84
|
# Warning-only: a macOS failure or unmeasured run never blocks publishing — auto-approve shows it as a warning row.
|
|
71
|
-
- { from:
|
|
72
|
-
- { from: pwa, on: outcome, map: { ok: prepare, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
85
|
+
- { from: pre-prepare-join, on: outcome, map: { ok: prepare, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
73
86
|
- { from: prepare, on: outcome, map: { ok: upgrade, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
74
87
|
- { from: upgrade, on: outcome, map: { ok: tui, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
75
88
|
- { from: tui, on: outcome, map: { ok: docs, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
@@ -84,16 +97,19 @@ edges:
|
|
|
84
97
|
- { from: publish, on: outcome, map: { ok: npm-publish, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
85
98
|
- { from: npm-publish, on: outcome, map: { ok: traffic-npm-published, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
86
99
|
# Publication already happened; a traffic write failure must not skip docs-land.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
# After npm publish these writes have independent ledgers and run together; the join keeps either result and gates verify.
|
|
101
|
+
- from: traffic-npm-published
|
|
102
|
+
on: outcome
|
|
103
|
+
branches:
|
|
104
|
+
ok: [docs-land, version-dev-bump]
|
|
105
|
+
fail: [docs-land, version-dev-bump]
|
|
106
|
+
error: [docs-land, version-dev-bump]
|
|
107
|
+
join: release-post-publish-join
|
|
108
|
+
- { from: release-post-publish-join, on: outcome, map: { ok: verify, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
109
|
+
- { from: verify, on: outcome, map: { ok: traffic-verify-complete, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
92
110
|
- { from: traffic-verify-complete, on: outcome, map: { ok: vault-note, fail: vault-note, error: vault-note } }
|
|
93
111
|
# Warning-only: vault note and release story failures after publication never block operational upgrades.
|
|
94
112
|
- { from: vault-note, on: outcome, map: { ok: release-story, fail: release-story, error: release-story } }
|
|
95
113
|
- { from: release-story, on: outcome, map: { ok: ops-upgrade, fail: ops-upgrade, error: ops-upgrade } }
|
|
96
|
-
- { from: ops-upgrade, on: outcome, map: { ok:
|
|
97
|
-
- { from: version-dev-bump, on: outcome, map: { ok: done, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
98
|
-
- { from: version-dev-bump-after-failure, on: outcome, map: { ok: traffic-failed-restore, fail: traffic-failed-restore, error: traffic-failed-restore } }
|
|
114
|
+
- { from: ops-upgrade, on: outcome, map: { ok: done, fail: done, error: done } }
|
|
99
115
|
- { from: traffic-failed-restore, on: outcome, map: { ok: failed, fail: failed, error: failed } }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elanous",
|
|
3
3
|
"mcpName": "io.github.ElanvitalAI/elanous",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.44",
|
|
5
5
|
"description": "Self-healing coding harness where eyes, hands, and memory all turn on one sentence — it authors its own goals, implements them in isolated worktrees, and reviews its own work.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Elanvital AI",
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** Validate that a paired benchmark has measurement sources and private sinks planned.
|
|
3
|
+
* This checks the plan only: it never launches arms, reads credentials, or claims measurements. */
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
|
|
6
|
+
export type BenchProvider = 'openrouter' | 'bedrock' | 'elanous' | 'claude-code';
|
|
7
|
+
|
|
8
|
+
export interface BenchMetricSource {
|
|
9
|
+
readonly collector: string;
|
|
10
|
+
readonly evidenceRef: string;
|
|
11
|
+
readonly region?: string;
|
|
12
|
+
readonly windowStartUtc?: string;
|
|
13
|
+
readonly windowEndUtc?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface BenchArmMeteringPlan {
|
|
17
|
+
readonly armId: string;
|
|
18
|
+
readonly provider: BenchProvider;
|
|
19
|
+
/** Product/agent identity is separate from the provider that supplies billing. */
|
|
20
|
+
readonly agent?: 'elanous' | 'claude-code' | 'provider-arm';
|
|
21
|
+
readonly billingProvider: string;
|
|
22
|
+
readonly noAutoMerge: boolean;
|
|
23
|
+
readonly metrics: Readonly<Record<string, BenchMetricSource | BenchMetricDisposition>>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface BenchMetricDisposition {
|
|
27
|
+
readonly status: 'not-applicable' | 'estimated' | 'unmeasured';
|
|
28
|
+
readonly reason: string;
|
|
29
|
+
readonly evidenceRef: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface BenchMeteringPlan {
|
|
33
|
+
readonly schemaVersion: 1;
|
|
34
|
+
readonly runId: string;
|
|
35
|
+
readonly promptSha256: string;
|
|
36
|
+
readonly baseSha: string;
|
|
37
|
+
readonly installedPin: string;
|
|
38
|
+
readonly arms: readonly BenchArmMeteringPlan[];
|
|
39
|
+
readonly sealed: {
|
|
40
|
+
readonly directory: string;
|
|
41
|
+
readonly directoryMode: string;
|
|
42
|
+
readonly unblindKey: string;
|
|
43
|
+
readonly meteringReceipt: string;
|
|
44
|
+
readonly fileMode: string;
|
|
45
|
+
};
|
|
46
|
+
readonly publicFields: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface BenchMeteringPlanCheck {
|
|
50
|
+
readonly readyToMeasure: boolean;
|
|
51
|
+
readonly metricsMeasured: false;
|
|
52
|
+
readonly armsLaunched: 0;
|
|
53
|
+
readonly issues: readonly string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const SHA256 = /^[0-9a-f]{64}$/i;
|
|
57
|
+
const COMMIT = /^[0-9a-f]{40}$/i;
|
|
58
|
+
const PROVIDER_PAIR_METRICS = [
|
|
59
|
+
'actualProvider',
|
|
60
|
+
'actualModel',
|
|
61
|
+
'rounds',
|
|
62
|
+
'inputTokens',
|
|
63
|
+
'outputTokens',
|
|
64
|
+
'elapsedMs',
|
|
65
|
+
'humanInterventions',
|
|
66
|
+
'actualChargeUsd',
|
|
67
|
+
'creditDelta',
|
|
68
|
+
] as const;
|
|
69
|
+
const COMPARISON_METRICS = [
|
|
70
|
+
'actualProvider', 'actualModel', 'rounds', 'inputTokens', 'outputTokens',
|
|
71
|
+
'toolCalls', 'elapsedMs', 'humanInterventions',
|
|
72
|
+
] as const;
|
|
73
|
+
const BEDROCK_METRICS = ['awsInvocationCount'] as const;
|
|
74
|
+
const PRIVATE_PUBLIC_FIELDS = /^(armId|provider|billingProvider|model|actualProvider|actualModel|elapsedMs|durationMs|humanInterventions|toolCalls|actualChargeUsd|estimatedChargeUsd|creditDelta|awsInvocationCount|accountId|region)$/i;
|
|
75
|
+
const SECRET_PROPERTY = /^(api[_-]?key|(?:secret|access)[_-]?(?:access)?key(?:id)?|authorization|password|credential|token)$/i;
|
|
76
|
+
|
|
77
|
+
function record(value: unknown): value is Record<string, unknown> {
|
|
78
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function scanSecretPropertyNames(value: unknown, path = '$'): string[] {
|
|
82
|
+
if (Array.isArray(value)) return value.flatMap((entry, index) => scanSecretPropertyNames(entry, `${path}[${index}]`));
|
|
83
|
+
if (!record(value)) return [];
|
|
84
|
+
return Object.entries(value).flatMap(([key, nested]) => [
|
|
85
|
+
...(SECRET_PROPERTY.test(key) ? [`${path}.${key}: credentials are not allowed in a measurement plan`] : []),
|
|
86
|
+
...scanSecretPropertyNames(nested, `${path}.${key}`),
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function validSource(value: unknown): value is BenchMetricSource {
|
|
91
|
+
const usableRef = (candidate: unknown): candidate is string => typeof candidate === 'string'
|
|
92
|
+
&& candidate.trim().length > 0
|
|
93
|
+
&& !/^(pending|tbd|unknown|n\/a)$/i.test(candidate.trim());
|
|
94
|
+
return record(value) && usableRef(value.collector) && usableRef(value.evidenceRef);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isDisposition(value: unknown): value is BenchMetricDisposition {
|
|
98
|
+
return record(value) && ['not-applicable', 'estimated', 'unmeasured'].includes(String(value.status));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function validDisposition(value: unknown): value is BenchMetricDisposition {
|
|
102
|
+
return isDisposition(value) && typeof value.reason === 'string' && value.reason.trim().length > 0
|
|
103
|
+
&& validSource({ collector: 'disposition', evidenceRef: value.evidenceRef });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function validAwsSource(value: unknown): value is BenchMetricSource {
|
|
107
|
+
if (!validSource(value) || typeof value.region !== 'string' || value.region.trim().length === 0) return false;
|
|
108
|
+
if (typeof value.windowStartUtc !== 'string' || typeof value.windowEndUtc !== 'string') return false;
|
|
109
|
+
const start = Date.parse(value.windowStartUtc);
|
|
110
|
+
const end = Date.parse(value.windowEndUtc);
|
|
111
|
+
return Number.isFinite(start) && Number.isFinite(end) && start < end
|
|
112
|
+
&& value.windowStartUtc.endsWith('Z') && value.windowEndUtc.endsWith('Z');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The output is deliberately plan-ready, never measurement-ready. */
|
|
116
|
+
export function checkBenchMeteringPlan(input: unknown): BenchMeteringPlanCheck {
|
|
117
|
+
const issues = scanSecretPropertyNames(input);
|
|
118
|
+
const issue = (message: string): void => { issues.push(message); };
|
|
119
|
+
if (!record(input)) {
|
|
120
|
+
issue('plan must be a JSON object');
|
|
121
|
+
return { readyToMeasure: false, metricsMeasured: false, armsLaunched: 0, issues };
|
|
122
|
+
}
|
|
123
|
+
if (input.schemaVersion !== 1) issue('schemaVersion must be 1');
|
|
124
|
+
if (typeof input.runId !== 'string' || input.runId.trim().length === 0) issue('runId is required');
|
|
125
|
+
if (typeof input.promptSha256 !== 'string' || !SHA256.test(input.promptSha256)) issue('promptSha256 must be a full SHA-256');
|
|
126
|
+
if (typeof input.baseSha !== 'string' || !COMMIT.test(input.baseSha)) issue('baseSha must be a full commit SHA');
|
|
127
|
+
if (typeof input.installedPin !== 'string' || !COMMIT.test(input.installedPin)) issue('installedPin must be a full commit SHA');
|
|
128
|
+
|
|
129
|
+
const arms = Array.isArray(input.arms) ? input.arms : [];
|
|
130
|
+
if (arms.length !== 2) issue('exactly two paired arms are required');
|
|
131
|
+
const claudePair = arms.some((arm) => record(arm) && arm.provider === 'elanous')
|
|
132
|
+
&& arms.some((arm) => record(arm) && arm.provider === 'claude-code');
|
|
133
|
+
const providers = new Set<string>();
|
|
134
|
+
const armIds = new Set<string>();
|
|
135
|
+
for (const [index, arm] of arms.entries()) {
|
|
136
|
+
const prefix = `arms[${index}]`;
|
|
137
|
+
if (!record(arm)) { issue(`${prefix} must be an object`); continue; }
|
|
138
|
+
if (typeof arm.armId !== 'string' || arm.armId.trim().length === 0) issue(`${prefix}.armId is required`);
|
|
139
|
+
else if (armIds.has(arm.armId)) issue(`${prefix}.armId must be unique`);
|
|
140
|
+
else armIds.add(arm.armId);
|
|
141
|
+
if (!['openrouter', 'bedrock', 'elanous', 'claude-code'].includes(String(arm.provider))) issue(`${prefix}.provider must be openrouter, bedrock, elanous, or claude-code`);
|
|
142
|
+
else providers.add(arm.provider as string);
|
|
143
|
+
if (typeof arm.billingProvider !== 'string' || arm.billingProvider.trim().length === 0) issue(`${prefix}.billingProvider is required`);
|
|
144
|
+
if (arm.provider === 'bedrock' && arm.billingProvider !== 'bedrock') issue(`${prefix}.billingProvider must match bedrock`);
|
|
145
|
+
if (arm.provider === 'openrouter' && arm.billingProvider !== 'openrouter') issue(`${prefix}.billingProvider must match openrouter`);
|
|
146
|
+
if (arm.provider === 'claude-code' && (arm.agent !== 'claude-code' || arm.billingProvider !== 'subscription')) issue(`${prefix} Claude Code arm must identify agent claude-code and subscription billing`);
|
|
147
|
+
if (arm.provider === 'elanous') {
|
|
148
|
+
if (arm.agent !== 'elanous') issue(`${prefix} Elanous arm must identify agent elanous`);
|
|
149
|
+
if (!['openrouter', 'bedrock', 'codex'].includes(String(arm.billingProvider))) issue(`${prefix} Elanous billingProvider must be openrouter, bedrock, or codex`);
|
|
150
|
+
}
|
|
151
|
+
if (arm.noAutoMerge !== true) issue(`${prefix}.noAutoMerge must be true`);
|
|
152
|
+
const metrics = record(arm.metrics) ? arm.metrics : {};
|
|
153
|
+
const requiredMetrics = claudePair
|
|
154
|
+
? COMPARISON_METRICS
|
|
155
|
+
: PROVIDER_PAIR_METRICS;
|
|
156
|
+
for (const metric of [...requiredMetrics, ...(arm.provider === 'bedrock' ? BEDROCK_METRICS : [])]) {
|
|
157
|
+
const value = metrics[metric];
|
|
158
|
+
if (isDisposition(value)) {
|
|
159
|
+
if (!validDisposition(value)) issue(`${prefix}.metrics.${metric} disposition needs a reason and evidenceRef`);
|
|
160
|
+
else if (value.status === 'unmeasured') issue(`${prefix}.metrics.${metric} is explicitly unmeasured; a collector and evidenceRef are required`);
|
|
161
|
+
else if (value.status === 'estimated') issue(`${prefix}.metrics.${metric} is estimated; a measured source is required`);
|
|
162
|
+
else if (metric !== 'actualChargeUsd' || arm.provider !== 'claude-code') issue(`${prefix}.metrics.${metric} is not applicable and cannot satisfy a required measurement`);
|
|
163
|
+
} else {
|
|
164
|
+
const sourceIsValid = metric === 'awsInvocationCount' ? validAwsSource(value) : validSource(value);
|
|
165
|
+
if (!sourceIsValid) issue(`${prefix}.metrics.${metric} needs a collector and evidenceRef${metric === 'awsInvocationCount' ? ', region, and an ordered UTC window' : ''}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const chargeMetric = metrics.actualChargeUsd;
|
|
169
|
+
const chargeSource = record(chargeMetric) ? chargeMetric.collector : undefined;
|
|
170
|
+
// This is deliberately a naming heuristic; it cannot prove the referenced billing artifact is genuine.
|
|
171
|
+
if (typeof chargeSource === 'string' && /estimate|rate.?card/i.test(chargeSource)) {
|
|
172
|
+
issue(`${prefix}.metrics.actualChargeUsd must identify an actual billing source, not an estimate`);
|
|
173
|
+
}
|
|
174
|
+
if (arm.provider === 'claude-code') {
|
|
175
|
+
if (!record(chargeMetric) || chargeMetric.status !== 'not-applicable'
|
|
176
|
+
|| chargeMetric.reason !== 'subscription · no billing source'
|
|
177
|
+
|| !validSource({ collector: 'subscription-disposition', evidenceRef: chargeMetric.evidenceRef })) {
|
|
178
|
+
issue(`${prefix}.metrics.actualChargeUsd must explicitly state subscription · no billing source`);
|
|
179
|
+
}
|
|
180
|
+
if ('creditDelta' in metrics) issue(`${prefix}.metrics.creditDelta must not imply subscription credit measurement`);
|
|
181
|
+
} else if (!validSource(chargeMetric)) {
|
|
182
|
+
issue(`${prefix}.metrics.actualChargeUsd needs an actual billing source`);
|
|
183
|
+
}
|
|
184
|
+
if ('estimatedChargeUsd' in metrics) {
|
|
185
|
+
const estimate = metrics.estimatedChargeUsd;
|
|
186
|
+
if (!record(estimate) || estimate.status !== 'estimated' || typeof estimate.reason !== 'string' || !estimate.reason.trim()
|
|
187
|
+
|| !validSource({ collector: 'estimate', evidenceRef: estimate.evidenceRef })) {
|
|
188
|
+
issue(`${prefix}.metrics.estimatedChargeUsd must be explicitly marked estimated with reason and evidenceRef`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const providerPair = providers.has('openrouter') && providers.has('bedrock');
|
|
193
|
+
const validClaudePair = providers.has('elanous') && providers.has('claude-code');
|
|
194
|
+
if (!providerPair && !validClaudePair) issue('pair must be openrouter + bedrock or elanous + claude-code');
|
|
195
|
+
|
|
196
|
+
const sealed = record(input.sealed) ? input.sealed : {};
|
|
197
|
+
if (sealed.directory !== 'sealed' || sealed.directoryMode !== '0700') issue('sealed output directory must be sealed/ with mode 0700');
|
|
198
|
+
if (sealed.unblindKey !== 'sealed/unblind-key.json') issue('unblind key must use the bench-blind-pack sealed path');
|
|
199
|
+
if (sealed.meteringReceipt !== 'sealed/metering-receipt.json') issue('metering receipt must stay beside the unblind key');
|
|
200
|
+
if (sealed.fileMode !== '0600') issue('sealed files must use mode 0600');
|
|
201
|
+
|
|
202
|
+
const publicFields = Array.isArray(input.publicFields) ? input.publicFields : [];
|
|
203
|
+
for (const field of publicFields) {
|
|
204
|
+
if (typeof field !== 'string' || PRIVATE_PUBLIC_FIELDS.test(field)) issue(`private metering/identity field cannot enter public output: ${String(field)}`);
|
|
205
|
+
}
|
|
206
|
+
return { readyToMeasure: issues.length === 0, metricsMeasured: false, armsLaunched: 0, issues };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function main(argv: string[]): Promise<number> {
|
|
210
|
+
if (argv.length !== 1 || argv.includes('--help') || argv.includes('-h')) {
|
|
211
|
+
process.stderr.write('Usage: bun scripts/bench-metering-plan.ts <measurement-plan.json>\n');
|
|
212
|
+
return argv.includes('--help') || argv.includes('-h') ? 0 : 2;
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const plan = JSON.parse(await readFile(argv[0]!, 'utf8')) as unknown;
|
|
216
|
+
const result = checkBenchMeteringPlan(plan);
|
|
217
|
+
if (!result.readyToMeasure) {
|
|
218
|
+
process.stderr.write(`bench metering plan refused (${result.issues.length} issue(s)):\n${result.issues.map((entry) => `- ${entry}`).join('\n')}\n`);
|
|
219
|
+
return 2;
|
|
220
|
+
}
|
|
221
|
+
process.stdout.write('plan-ready; no metrics measured; no benchmark arms launched\n');
|
|
222
|
+
return 0;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
process.stderr.write(`bench metering plan refused: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
225
|
+
return 2;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (import.meta.main) process.exitCode = await main(process.argv.slice(2));
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { TerminalSessionRegistry } from '../../src/terminal/session-registry.js';
|
|
2
|
+
import {
|
|
3
|
+
createDemo1104ParallelScenes,
|
|
4
|
+
createDemo1104TuiTabAdapters,
|
|
5
|
+
type DemoParallelSnapshot,
|
|
6
|
+
type DemoSurfaceAdapter,
|
|
7
|
+
} from './demo1104-parallel-scenes.js';
|
|
8
|
+
import type { DemoActId } from './demo1104-stage.config.js';
|
|
9
|
+
import { spawnCodingAgent } from '../../src/terminal/coding-agent.js';
|
|
10
|
+
|
|
11
|
+
export type Demo1104ParallelHostOptions = {
|
|
12
|
+
registry: TerminalSessionRegistry;
|
|
13
|
+
cwd: string;
|
|
14
|
+
termSize: () => { cols: number; rows: number };
|
|
15
|
+
runMission: Parameters<typeof createDemo1104TuiTabAdapters>[0]['runMission'];
|
|
16
|
+
showVideo: Parameters<typeof createDemo1104TuiTabAdapters>[0]['showVideo'];
|
|
17
|
+
videoSources: Readonly<Record<string, string>>;
|
|
18
|
+
webRunGraph: DemoSurfaceAdapter;
|
|
19
|
+
telegram: DemoSurfaceAdapter;
|
|
20
|
+
spawnAgent?: typeof spawnCodingAgent;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type Demo1104ParallelStage = {
|
|
24
|
+
start(): Promise<void>;
|
|
25
|
+
runActNow(id: DemoActId): Promise<void>;
|
|
26
|
+
switchToVideo(id: DemoActId): Promise<void>;
|
|
27
|
+
snapshot(): DemoParallelSnapshot;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** The single host composition point for the two visible agent tabs and the two secretary surfaces. */
|
|
31
|
+
export function createDemo1104ParallelHost(options: Demo1104ParallelHostOptions): Demo1104ParallelStage {
|
|
32
|
+
const tuiTabs = createDemo1104TuiTabAdapters({
|
|
33
|
+
registry: options.registry,
|
|
34
|
+
cwd: options.cwd,
|
|
35
|
+
termSize: options.termSize,
|
|
36
|
+
runMission: options.runMission,
|
|
37
|
+
showVideo: options.showVideo,
|
|
38
|
+
videoSources: options.videoSources,
|
|
39
|
+
...(options.spawnAgent ? { spawnAgent: options.spawnAgent } : {}),
|
|
40
|
+
});
|
|
41
|
+
return createDemo1104ParallelScenes({
|
|
42
|
+
...tuiTabs,
|
|
43
|
+
'web-run-graph': options.webRunGraph,
|
|
44
|
+
telegram: options.telegram,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Start all four demo surfaces together and return the live controls to the demo runner. */
|
|
49
|
+
export async function startDemo1104ParallelHost(options: Demo1104ParallelHostOptions): Promise<{
|
|
50
|
+
stage: Demo1104ParallelStage;
|
|
51
|
+
snapshot: DemoParallelSnapshot;
|
|
52
|
+
}> {
|
|
53
|
+
const stage = createDemo1104ParallelHost(options);
|
|
54
|
+
await stage.start();
|
|
55
|
+
return { stage, snapshot: stage.snapshot() };
|
|
56
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
|
+
import { stdin, stdout } from 'node:process';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import { DisplayCoordinator } from '../../src/display/coordinator.js';
|
|
7
|
+
import { TerminalSessionRegistry } from '../../src/terminal/session-registry.js';
|
|
8
|
+
import { createDemoRunGraphSurfaceAdapter, createDemoTelegramDryRunAdapter } from './demo1104-parallel-scenes.js';
|
|
9
|
+
import { DEMO1104_STAGE_CONFIG } from './demo1104-stage.config.js';
|
|
10
|
+
import { startDemo1104ParallelHost } from './demo1104-parallel-host.js';
|
|
11
|
+
|
|
12
|
+
const repoRoot = resolve(import.meta.dir, '../..');
|
|
13
|
+
const outputDir = resolve(process.env.DEMO1104_OUTPUT_DIR ?? `${process.env.HOME}/Movies/elanous/demo-1104/live`);
|
|
14
|
+
const videoSources = Object.fromEntries(['V1', 'V2', 'V3', 'V4', 'V5', 'V6'].map(id => [id, resolve(outputDir, `${id}.mp4`)]));
|
|
15
|
+
const coordinator = new DisplayCoordinator({ termSize: () => ({ cols: process.stdout.columns ?? 120, rows: process.stdout.rows ?? 40 }) });
|
|
16
|
+
const registry = new TerminalSessionRegistry({ coordinator });
|
|
17
|
+
const webRunGraph = createDemoRunGraphSurfaceAdapter({
|
|
18
|
+
graphId: 'inside-seed',
|
|
19
|
+
graphYaml: readFileSync(resolve(repoRoot, 'graphs/demo/inside-seed.yaml'), 'utf8'),
|
|
20
|
+
videoSources,
|
|
21
|
+
onView(view, act) { stdout.write(`[web-run-graph] ${act.id} ${view.status}\n`); },
|
|
22
|
+
onVideo(transition) { stdout.write(`[web-run-graph] video ${transition.videoId}: ${transition.source}\n`); },
|
|
23
|
+
});
|
|
24
|
+
const telegramFile = resolve(outputDir, 'telegram-dry-run.jsonl');
|
|
25
|
+
const telegram = createDemoTelegramDryRunAdapter({ file: telegramFile, linearIssueId: 'DEMO1104', videoSources });
|
|
26
|
+
let stage: Awaited<ReturnType<typeof startDemo1104ParallelHost>>['stage'] | undefined;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const started = await startDemo1104ParallelHost({
|
|
30
|
+
registry,
|
|
31
|
+
cwd: repoRoot,
|
|
32
|
+
termSize: () => ({ cols: process.stdout.columns ?? 120, rows: process.stdout.rows ?? 40 }),
|
|
33
|
+
videoSources,
|
|
34
|
+
webRunGraph,
|
|
35
|
+
telegram,
|
|
36
|
+
async runMission(session, act) {
|
|
37
|
+
const prompt = `\n[11-04 ${act.id}] ${act.title}\n`;
|
|
38
|
+
session.preview.write(`${prompt}\n`);
|
|
39
|
+
stdout.write(`[${session.agentBrand}] mission sent to ${session.id}\n`);
|
|
40
|
+
},
|
|
41
|
+
showVideo(session, transition) {
|
|
42
|
+
session.preview.write(`\n[11-04 video ${transition.videoId}] ${transition.source}\n`);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
stage = started.stage;
|
|
46
|
+
stdout.write(`11-04 parallel stage started\n${JSON.stringify(started.snapshot, null, 2)}\n`);
|
|
47
|
+
stdout.write(`Controls: act <act-id> | video <act-id> | snapshot | quit\nActs: ${DEMO1104_STAGE_CONFIG.acts.map(act => act.id).join(', ')}\n`);
|
|
48
|
+
const input = createInterface({ input: stdin, output: stdout, terminal: Boolean(stdin.isTTY) });
|
|
49
|
+
try {
|
|
50
|
+
for await (const line of input) {
|
|
51
|
+
const [command, id] = line.trim().split(/\s+/, 2);
|
|
52
|
+
if (command === 'quit' || command === 'exit') break;
|
|
53
|
+
if (command === 'snapshot') {
|
|
54
|
+
stdout.write(`${JSON.stringify(stage.snapshot(), null, 2)}\n`);
|
|
55
|
+
} else if (command === 'act' && id) {
|
|
56
|
+
await stage.runActNow(id as typeof DEMO1104_STAGE_CONFIG.acts[number]['id']);
|
|
57
|
+
stdout.write(`act complete: ${id}\n`);
|
|
58
|
+
} else if (command === 'video' && id) {
|
|
59
|
+
await stage.switchToVideo(id as typeof DEMO1104_STAGE_CONFIG.acts[number]['id']);
|
|
60
|
+
stdout.write(`video transition complete: ${id}\n`);
|
|
61
|
+
} else {
|
|
62
|
+
stdout.write('Use: act <act-id> | video <act-id> | snapshot | quit\n');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} finally {
|
|
66
|
+
input.close();
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
for (const session of registry.list()) registry.kill(session.id);
|
|
70
|
+
webRunGraph.close();
|
|
71
|
+
telegram.close();
|
|
72
|
+
}
|
|
@@ -794,7 +794,6 @@
|
|
|
794
794
|
2 runtime-path-outside-export src/self-implement/project-scaffold.test.ts
|
|
795
795
|
3 runtime-path-outside-export src/self-implement/run-ledger-cli.test.ts
|
|
796
796
|
1 runtime-path-outside-export src/workflow-runtime/discovery.ts
|
|
797
|
-
1 runtime-path-outside-export test/anatomy-doc-source-citations.test.ts
|
|
798
797
|
1 runtime-path-outside-export test/dev-help-concise.test.ts
|
|
799
798
|
1 runtime-path-outside-export test/dispatch/authored-goal-queue.test.ts
|
|
800
799
|
1 runtime-path-outside-export test/federation-guard-f11-paint-cache-opt-in.test.ts
|
|
@@ -29,6 +29,8 @@ type TranslationRunner = (line: string) => string;
|
|
|
29
29
|
type AskSpawn = (command: string, args: string[], options: SpawnSyncOptionsWithStringEncoding) => SpawnSyncReturns<string>;
|
|
30
30
|
|
|
31
31
|
const HANGUL = /[\uac00-\ud7a3]/;
|
|
32
|
+
// Allow common English typography without accepting arbitrary non-ASCII letters, digits, or symbols.
|
|
33
|
+
const PUBLIC_TRANSLATION_NON_ASCII = /[^\x00-\x7f\u00a0\u00a1\u00ab\u00b7\u00bb\u00bf\u2010-\u2015\u2018-\u201f\u2022\u2026]/u;
|
|
32
34
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
|
|
33
35
|
|
|
34
36
|
function splitMarkdownPrefix(raw: string): { prefix: string; text: string } {
|
|
@@ -130,8 +132,8 @@ function translatePublicText(text: string, runner: TranslationRunner, failures:
|
|
|
130
132
|
try {
|
|
131
133
|
const candidate = runner(source).trim();
|
|
132
134
|
const alphanumeric = [...candidate].filter((character) => /[\p{L}\p{N}]/u.test(character));
|
|
133
|
-
if (!candidate || HANGUL.test(candidate) || alphanumeric.length === 0 ||
|
|
134
|
-
throw new Error('translation is empty or contains non-
|
|
135
|
+
if (!candidate || HANGUL.test(candidate) || alphanumeric.length === 0 || PUBLIC_TRANSLATION_NON_ASCII.test(candidate)) {
|
|
136
|
+
throw new Error('translation is empty or contains unsupported non-ASCII characters');
|
|
135
137
|
}
|
|
136
138
|
translated = candidate;
|
|
137
139
|
cache.set(source, candidate);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import { dirname } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
3
5
|
|
|
4
6
|
/** A gate run may execute only against one immutable image identity and its exact source tag. */
|
|
5
7
|
export interface GateImagePin { runId: string; digest: string; image: string; commit: string }
|
|
@@ -17,7 +19,68 @@ export interface ResolveGateImagePinOptions {
|
|
|
17
19
|
poolImages: ReadonlyMap<string, readonly string[]>;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
interface PinnedGateImagePullDecision {
|
|
23
|
+
push: false;
|
|
24
|
+
imageRef: string;
|
|
25
|
+
tagDrift?: { event: 'image-tag-drift'; runId: string; tag: string; pinnedDigest: string; observedDigest: string | null; reason: 'digest-changed' | 'tag-unavailable' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PinnedGateImageSyncResult {
|
|
29
|
+
images: Map<string, { ok: true; action: 'fresh'; detail: string; ms: 0; imageRef: string }>;
|
|
30
|
+
tagDrifts: Array<{ event: 'image-tag-drift'; runId: string; tag: string; pinnedDigest: string;
|
|
31
|
+
observedDigest: string | null; reason: 'digest-changed' | 'tag-unavailable'; context: string }>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function imageRepository(image: string): string {
|
|
35
|
+
let repository = image.trim().replace(/@sha256:[a-f0-9]{64}$/i, '');
|
|
36
|
+
const firstSlash = repository.indexOf('/');
|
|
37
|
+
if (firstSlash > 0) {
|
|
38
|
+
const first = repository.slice(0, firstSlash);
|
|
39
|
+
if (first === 'localhost' || first.includes('.') || first.includes(':')) repository = repository.slice(firstSlash + 1);
|
|
40
|
+
}
|
|
41
|
+
return repository.replace(/:[^/:]+$/, '');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Build a Job image ref from the registry service visible inside a pool's Kubernetes cluster. */
|
|
45
|
+
function pinnedGateImagePullDecision(input: {
|
|
46
|
+
runId: string; registry: string; image: string; digest: string; observedTagDigest?: string | null;
|
|
47
|
+
}): PinnedGateImagePullDecision {
|
|
48
|
+
const digest = normalizeGateImageDigest(input.digest);
|
|
49
|
+
const registry = input.registry.trim().replace(/\/$/, '');
|
|
50
|
+
const repository = imageRepository(input.image);
|
|
51
|
+
if (!input.runId || !registry || !repository || repository.includes('@') || !digest) throw new Error('invalid pinned gate image pull identity');
|
|
52
|
+
const observed = normalizeGateImageDigest(input.observedTagDigest);
|
|
53
|
+
const tag = `${registry}/${repository}:${input.image.split(':').at(-1) ?? ''}`;
|
|
54
|
+
return {
|
|
55
|
+
push: false,
|
|
56
|
+
imageRef: `${registry}/${repository}@${digest}`,
|
|
57
|
+
...(!observed || observed !== digest ? { tagDrift: { event: 'image-tag-drift', runId: input.runId,
|
|
58
|
+
tag, pinnedDigest: digest, observedDigest: observed, reason: observed ? 'digest-changed' as const : 'tag-unavailable' as const } } : {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Convert every selected gate member to a digest ref; this path deliberately has no build/push operation. */
|
|
63
|
+
export function pinnedGateImageSync(input: {
|
|
64
|
+
runId: string; commit: string; digest: string; image: string;
|
|
65
|
+
members: readonly { context: string; registry: string }[];
|
|
66
|
+
probeTagDigest: (member: { context: string; registry: string }) => string | null;
|
|
67
|
+
}): PinnedGateImageSyncResult {
|
|
68
|
+
const repository = imageRepository(input.image);
|
|
69
|
+
if (!/^[0-9a-f]{40}$/i.test(input.commit) || !repository || repository.includes('@')) throw new Error('invalid pinned gate image identity');
|
|
70
|
+
const tag = `${repository}:${input.commit.slice(0, 12)}`;
|
|
71
|
+
const images = new Map<string, { ok: true; action: 'fresh'; detail: string; ms: 0; imageRef: string }>();
|
|
72
|
+
const tagDrifts: PinnedGateImageSyncResult['tagDrifts'] = [];
|
|
73
|
+
for (const member of input.members) {
|
|
74
|
+
const decision = pinnedGateImagePullDecision({ runId: input.runId, registry: member.registry, image: tag,
|
|
75
|
+
digest: input.digest, observedTagDigest: input.probeTagDigest(member) });
|
|
76
|
+
images.set(member.context, { ok: true, action: 'fresh', detail: 'run-pinned-digest; tag push skipped', ms: 0,
|
|
77
|
+
imageRef: decision.imageRef });
|
|
78
|
+
if (decision.tagDrift) tagDrifts.push({ ...decision.tagDrift, context: member.context });
|
|
79
|
+
}
|
|
80
|
+
return { images, tagDrifts };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function normalizeGateImageDigest(value: unknown): string | null {
|
|
21
84
|
if (typeof value !== 'string' || !/^sha256:[a-f0-9]{64}$/i.test(value.trim())) return null;
|
|
22
85
|
return value.trim().toLowerCase();
|
|
23
86
|
}
|
|
@@ -52,6 +115,57 @@ export function readGateImagePin(path: string, expectedRunId: string, expectedIm
|
|
|
52
115
|
return { runId: expectedRunId, digest: normalizeGateImageDigest(parsed.digest)!, image: expectedImage, commit: normalizedCommit };
|
|
53
116
|
}
|
|
54
117
|
|
|
118
|
+
/** Read a valid pin for this run and image repository while allowing its commit tag to be stale. */
|
|
119
|
+
export function readGateImagePinForRun(path: string, expectedRunId: string, expectedImage: string): GateImagePin | null {
|
|
120
|
+
if (!existsSync(path)) return null;
|
|
121
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8')) as { version?: unknown; runId?: unknown; digest?: unknown; image?: unknown; commit?: unknown };
|
|
122
|
+
const commit = typeof parsed.commit === 'string' && /^[0-9a-f]{40}$/i.test(parsed.commit) ? parsed.commit.toLowerCase() : null;
|
|
123
|
+
const image = typeof parsed.image === 'string' ? parsed.image : '';
|
|
124
|
+
const imageRepo = imageRepository(image);
|
|
125
|
+
if (parsed.version !== 2 || parsed.runId !== expectedRunId || !commit || !normalizeGateImageDigest(parsed.digest)
|
|
126
|
+
|| !imageRepo || imageRepo !== imageRepository(expectedImage) || image !== `${imageRepo}:${commit.slice(0, 12)}`)
|
|
127
|
+
throw new Error(`invalid gate image pin: ${path}`);
|
|
128
|
+
return { runId: expectedRunId, digest: normalizeGateImageDigest(parsed.digest)!, image, commit };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Preserve a valid old tip pin before a resumed gate establishes a new commit pin. */
|
|
132
|
+
export function supersedeGateImagePin(path: string, expectedRunId: string, expectedImage: string, expectedCommit: string): { pin: GateImagePin; archivePath: string } | null {
|
|
133
|
+
const prior = readGateImagePinForRun(path, expectedRunId, expectedImage);
|
|
134
|
+
if (!prior || prior.commit === expectedCommit.toLowerCase()) return null;
|
|
135
|
+
const stem = `${path}.superseded-${prior.commit.slice(0, 12)}-${process.pid}-${Date.now()}`;
|
|
136
|
+
let archivePath = stem;
|
|
137
|
+
for (let suffix = 1; ; suffix++) {
|
|
138
|
+
archivePath = suffix === 1 ? stem : `${stem}-${suffix}`;
|
|
139
|
+
try {
|
|
140
|
+
copyFileSync(path, archivePath, constants.COPYFILE_EXCL);
|
|
141
|
+
break;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
144
|
+
if (readFileSync(path).equals(readFileSync(archivePath))) break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { pin: prior, archivePath };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Archive the old tip and atomically replace the active pin without an absent-pin crash window. */
|
|
151
|
+
export function replaceGateImagePin(path: string, runId: string, digest: string, image: string, commit: string,
|
|
152
|
+
expectedImage: string, expectedPriorCommit: string): string {
|
|
153
|
+
const prior = readGateImagePinForRun(path, runId, expectedImage);
|
|
154
|
+
if (!prior || prior.commit !== expectedPriorCommit.toLowerCase()) throw new Error('stale gate image pin changed before replacement');
|
|
155
|
+
const archived = supersedeGateImagePin(path, runId, expectedImage, commit);
|
|
156
|
+
if (!archived) throw new Error('stale gate image pin could not be archived');
|
|
157
|
+
const normalized = normalizeGateImageDigest(digest);
|
|
158
|
+
if (!normalized || !runId || !image.trim() || !/^[0-9a-f]{40}$/i.test(commit)) throw new Error('invalid gate image pin identity');
|
|
159
|
+
const value = `${JSON.stringify({ version: 2, runId, digest: normalized, image, commit: commit.toLowerCase() }, null, 2)}\n`;
|
|
160
|
+
const tempPath = `${path}.pending-${randomUUID()}`;
|
|
161
|
+
try {
|
|
162
|
+
writeFileSync(tempPath, value, { mode: 0o600, flag: 'wx' });
|
|
163
|
+
// Keep the old active pin until the complete replacement is ready; rename is atomic on this filesystem.
|
|
164
|
+
renameSync(tempPath, path);
|
|
165
|
+
return archived.archivePath;
|
|
166
|
+
} finally { rmSync(tempPath, { force: true }); }
|
|
167
|
+
}
|
|
168
|
+
|
|
55
169
|
export function writeGateImagePin(path: string, runId: string, digest: string, image: string, commit: string): void {
|
|
56
170
|
const normalized = normalizeGateImageDigest(digest);
|
|
57
171
|
if (!runId || !normalized || !image.trim() || !/^[0-9a-f]{40}$/i.test(commit)) throw new Error('invalid gate image pin identity');
|