elanous 0.2.32 → 0.2.34
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/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
- package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
- package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
- package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
- package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
- package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
- package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
- package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
- package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
- package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
- package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-8c66a3b24a745630.js → page-398c0faa173203f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-df3445b207ceceab.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
- package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.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/bin/elanous.mjs +9 -2
- package/docs/goal-context/README.md +1 -0
- package/graphs/default-loop.yaml +20 -3
- package/graphs/document-loop.yaml +21 -2
- package/graphs/implement-loop.yaml +6 -0
- package/graphs/journey/SCENARIOS.md +33 -0
- package/graphs/journey/recipes.yaml +1 -0
- package/graphs/journey/ta-journey.yaml +84 -0
- package/graphs/journey/units/author/author.yaml +20 -0
- package/graphs/journey/units/author/recipes.yaml +2 -0
- package/graphs/journey/units/green/green.yaml +20 -0
- package/graphs/journey/units/green/recipes.yaml +2 -0
- package/graphs/journey/units/pr/pr.yaml +20 -0
- package/graphs/journey/units/pr/recipes.yaml +2 -0
- package/graphs/journey/units/remember/recipes.yaml +2 -0
- package/graphs/journey/units/remember/remember.yaml +20 -0
- package/graphs/operate-loop.yaml +21 -2
- package/graphs/overlays/stop-heal-ladder.yaml +1 -1
- package/graphs/release-rehearsal/recipes.yaml +1 -1
- package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
- package/graphs/research-loop.yaml +23 -2
- package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
- package/graphs/units/dispatch-pod/recipes.yaml +14 -0
- package/graphs/units/entry/entry.yaml +50 -0
- package/graphs/units/entry/recipes.yaml +14 -0
- package/graphs/units/harvest/harvest.yaml +25 -0
- package/graphs/units/harvest/recipes.yaml +4 -0
- package/graphs/units/land/land.yaml +45 -0
- package/graphs/units/land/recipes.yaml +3 -0
- package/graphs/units/recipes.yaml +7 -0
- package/graphs/units/recover.yaml +39 -0
- package/graphs/units/reflect/recipes.yaml +3 -0
- package/graphs/units/reflect/reflect.yaml +15 -0
- package/graphs/units/task-agent-recover-review.yaml +17 -0
- package/graphs/units/task-agent-recover-wait.yaml +17 -0
- package/graphs/units/verbs/make-doc.yaml +34 -0
- package/graphs/units/verbs/recipes.yaml +33 -0
- package/graphs/units/verbs/verify.yaml +55 -0
- package/graphs/work/recipes.yaml +2 -0
- package/graphs/work/research-report.yaml +28 -0
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +69 -16
- package/scripts/docs/generate-graph-anatomy.ts +19 -2
- package/scripts/graph-harvest-unit.ts +22 -0
- package/scripts/graph-units/journey-stub.ts +6 -0
- package/scripts/graph-units/land-enqueue.ts +78 -0
- package/scripts/graph-units/recover-plan.ts +15 -0
- package/scripts/graph-units/reflect-node.ts +88 -0
- package/scripts/graph-units/ta-journey-observe.ts +109 -0
- package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
- package/scripts/graph-units/verbs/verify-stage.ts +75 -0
- package/scripts/graph-units/verbs-envelope.ts +139 -0
- package/scripts/hq/standby-snapshot.ts +25 -0
- package/scripts/public-export.ts +43 -1
- package/scripts/ratchets/train-side-invariants.sh +45 -0
- package/scripts/release-loop/auto-approve-node.ts +30 -16
- package/scripts/release-loop/gate-closure.ts +5 -1
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-node.ts +498 -31
- package/scripts/release-loop/gate-partial.ts +3 -3
- package/scripts/release-loop/gate-radius-shadow.ts +138 -0
- package/scripts/release-loop/gate-traffic-mode.ts +128 -0
- package/scripts/release-loop/gate-triage-node.ts +5 -2
- package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
- package/scripts/release-loop/known-issues-node.ts +77 -8
- package/scripts/release-loop/preflight.ts +93 -7
- package/scripts/release-loop/publish-node.ts +60 -9
- package/scripts/release-loop/resume-cap.ts +56 -0
- package/scripts/release-loop/resume-release.ts +114 -15
- package/scripts/release-loop/resume.ts +24 -1
- package/scripts/release-loop/tui-sim-node.ts +8 -2
- package/scripts/release-loop/unattended-release.ts +8 -2
- package/src/acp/core-turn-bridge.ts +20 -5
- package/src/acp/reasoning-thought-buffer.ts +45 -0
- package/src/agent-substrate/acp-reviewer.ts +52 -12
- package/src/agent-substrate/review-finding-key.ts +53 -0
- package/src/agent-substrate/self-review-cli.ts +126 -5
- package/src/ask-user-question/pending-questions.ts +1 -1
- package/src/autopilot/pr-manager.ts +192 -43
- package/src/chat/tool-render/dispatch.ts +62 -10
- package/src/cli/control-cli.ts +24 -7
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/light-entry-route.ts +35 -0
- package/src/cli/llm-detect-cli.ts +23 -1
- package/src/cli/pr-cli.ts +76 -12
- package/src/cli/pr-land-base-read.ts +2 -0
- package/src/cli/pr-land-overlap-evidence.ts +154 -16
- package/src/cli/pr-land-recovery.ts +64 -0
- package/src/cli/pty-takeover-cli.ts +6 -5
- package/src/cli/release-cli.ts +120 -33
- package/src/cli/release-run-if-ready.ts +29 -28
- package/src/cli/release-single-flight.ts +178 -0
- package/src/cli/seat-cli.ts +37 -0
- package/src/cli/setup-cli.ts +40 -1
- package/src/cli/tasks-cli.ts +149 -5
- package/src/control/control-status.ts +8 -3
- package/src/control-plane/ledger.ts +5 -3
- package/src/control-plane/server.ts +5 -3
- package/src/core-turn/short-question.ts +5 -1
- package/src/dashboard/index.ts +36 -67
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/seat-autowake.ts +56 -3
- package/src/dashboard/seat-boot-preamble.ts +1 -1
- package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
- package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
- package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
- package/src/dashboard/turn-preamble.ts +47 -1
- package/src/dashboard/turn-stream-formatter.ts +34 -1
- package/src/dashboard/turn-stream-runtime.ts +2 -0
- package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
- package/src/domains/guardian-tick.ts +54 -2
- package/src/domains/outbound-alert.ts +3 -2
- package/src/extractors.ts +3 -1
- package/src/git-fs/retry.ts +4 -0
- package/src/git-fs/runner.ts +2 -0
- package/src/graph-runner/runner.ts +114 -44
- package/src/grok/credential.ts +5 -0
- package/src/harness/harness-cli-command.ts +39 -10
- package/src/harness/harness-incidents.ts +4 -0
- package/src/harness/harness-pod-dispatch.ts +38 -1
- package/src/harness/harness-salvage-cli.ts +14 -2
- package/src/index.ts +192 -8
- package/src/intake-plane/already-built-hint.ts +89 -0
- package/src/knowhow/pack.ts +199 -0
- package/src/light-cli.ts +95 -0
- package/src/llm.ts +55 -9
- package/src/loops/budget.ts +95 -0
- package/src/loops/msg-wake.ts +8 -2
- package/src/loops/orchestrator/traffic.ts +132 -1
- package/src/mss/logging/log-store.ts +4 -5
- package/src/nexus/api/graphs-api.ts +22 -3
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +12 -0
- package/src/oauth/claude-pty-maturity.ts +66 -0
- package/src/oauth/codex-access-mirror.ts +55 -0
- package/src/oauth/fallback-chain.ts +1 -1
- package/src/onboarding/first-run.ts +5 -3
- package/src/onboarding/non-interactive.ts +64 -13
- package/src/onboarding.ts +10 -2
- package/src/ops/overview-collect.ts +36 -1
- package/src/ops/overview.ts +11 -0
- package/src/pr-tool/census.ts +23 -5
- package/src/pr-tool/inflight-registry.ts +160 -7
- package/src/prompt-library/gpt6-family-addendum.ts +14 -1
- package/src/pty-shell/herdr-agent-report.ts +442 -0
- package/src/pty-shell/pty-control-ipc.ts +5 -5
- package/src/pty-shell/pty-write-outcome.ts +24 -6
- package/src/pty-shell/tui-run-state.ts +117 -3
- package/src/release-loop/checklist.ts +79 -5
- package/src/release-loop/feature-store.ts +19 -2
- package/src/release-loop/placement.ts +10 -3
- package/src/release-loop/rehearsal.ts +205 -25
- package/src/release-loop/rubric.ts +16 -2
- package/src/self-dev/draft-sweep.ts +52 -3
- package/src/self-dev/graph-journey-nodes.ts +10 -6
- package/src/self-dev/graph-journey-route.ts +60 -6
- package/src/self-dev/orchestrate.ts +79 -3
- package/src/self-dev/run-supervisor.ts +107 -12
- package/src/self-dev/run-types.ts +5 -1
- package/src/self-implement/gate-baseline.ts +49 -5
- package/src/self-implement/gate-remote.ts +9 -5
- package/src/self-implement/goal-author-identity.ts +66 -0
- package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
- package/src/self-implement/goal-author.ts +4 -120
- package/src/self-implement/graph-overlay-yaml.ts +17 -2
- package/src/self-implement/graph-unit-flatten.ts +103 -0
- package/src/self-implement/graph-unit-resolver.ts +107 -0
- package/src/self-implement/graph-yaml.ts +151 -1
- package/src/self-implement/headless-elanous-driver.ts +1 -0
- package/src/self-implement/knowhow-pack.ts +103 -0
- package/src/self-implement/orchestrator.ts +8 -0
- package/src/self-implement/pod-warm-pool-profile.ts +45 -0
- package/src/self-implement/review-mustfix-class.ts +203 -0
- package/src/self-implement/run-stop.ts +8 -2
- package/src/self-implement/seams.ts +32 -1
- package/src/self-implement/stop-autoheal.ts +25 -1
- package/src/session/chat.ts +27 -0
- package/src/session-runtime/retry-policy.ts +2 -1
- package/src/skills/tools/schedule-wakeup.ts +66 -17
- package/src/steward/release-day.ts +7 -3
- package/src/steward/triage.ts +37 -4
- package/src/task-agent/harvest-unit.ts +141 -0
- package/src/task-agent/live-moves.ts +98 -12
- package/src/task-agent/parent-host.ts +93 -3
- package/src/task-agent/postland-card.ts +80 -1
- package/src/task-agent/rejudge-on-head.ts +112 -26
- package/src/task-agent/repair-branch-cas.ts +4 -1
- package/src/task-agent/repair-cycle.ts +16 -3
- package/src/task-agent/run-identity.ts +4 -3
- package/src/task-agent/shadow.ts +12 -2
- package/src/task-agent/task-hand.ts +54 -7
- package/src/task-agent/work-order-build.ts +22 -0
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
- package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +26 -3
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +223 -38
- package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
- package/src/tool-runtime/truncation-store.ts +4 -0
- package/src/tui-client/dashboard-session.ts +10 -1
- package/src/user-config/coercion.ts +36 -0
- package/src/user-config.ts +18 -41
- package/src/ux-sim/scenario.ts +72 -13
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
- package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
- package/src/cli/g6a-registration-probe.ts +0 -16
- /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
|
@@ -6,6 +6,16 @@ import { join } from 'node:path';
|
|
|
6
6
|
import { emitNodeResult, readGraphContext, runCommand, type CommandRunner, type GraphContext } from './node-verdict.js';
|
|
7
7
|
|
|
8
8
|
const FALLBACK = 'Known issues have been reported for this release.';
|
|
9
|
+
const APPROVED_0233_INPUT = JSON.parse(readFileSync(join(import.meta.dir, 'known-issues-0.2.33-approved.json'), 'utf8')) as Issue[];
|
|
10
|
+
const APPROVED_0233_BY_ID = new Map(APPROVED_0233_INPUT.map((issue) => [issue.id, issue.note]));
|
|
11
|
+
const APPROVED_0233_BULLETS = new Map([
|
|
12
|
+
['KI-0233-REGRESSIONS · 0.2.33: 사용자 영향은 bot routine dry-run 루틴 사용 금지. 격리 시험은 검증되지 않았으며 0.2.34에서 복원·재검증한다.', 'Bot routine dry runs must not be used in this release.'],
|
|
13
|
+
['KI-0233-REGRESSIONS · 0.2.33: 이 경로의 검증 공백이다. 기능이 검증됐다고 간주하지 말고 0.2.34에서 수리·시험 복원 뒤 재검증한다.', 'Some paths remain unverified in this release.'],
|
|
14
|
+
['KI-0233-REGRESSIONS · 0.2.33: 옛 판 오프너 경보가 지연되거나 누락될 수 있다. 0.2.34에서 독립 fixture와 Linux Pod 실물 검증 후 복원한다.', 'Old version opener alerts may be delayed or missed in this release.'],
|
|
15
|
+
]);
|
|
16
|
+
function acceptedNoteFallback(issue: Issue, approvedBatch: boolean): string | null {
|
|
17
|
+
return approvedBatch ? APPROVED_0233_BULLETS.get(issue.note ?? '') ?? null : null;
|
|
18
|
+
}
|
|
9
19
|
// No fix schedule is promised here — the inputs do not carry one (review R2).
|
|
10
20
|
const INTRO = 'The following issues are known in this release.';
|
|
11
21
|
// A known-issues bullet describes a problem that is still there; «fixed / resolved» wording turns it into a false claim.
|
|
@@ -14,6 +24,11 @@ const unsafe = /[^\x20-\x7e]|#\d+|\/Users\/|\.test\.ts\b|\[(?:TC|MK|OP|UX|S|T|F|
|
|
|
14
24
|
|
|
15
25
|
type Issue = { id: string; title?: string; evidence?: string; note?: string };
|
|
16
26
|
|
|
27
|
+
// Accepted regressions with the same public note describe one issue, even if several gates recorded it.
|
|
28
|
+
function issueGroup(issue: Issue, checklistIssues: ReadonlySet<Issue>): string {
|
|
29
|
+
return checklistIssues.has(issue) ? `checklist:${issue.id}` : `accepted:${issue.note}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
function issues(value: unknown, kind: 'checklist' | 'accepted'): Issue[] {
|
|
18
33
|
if (value === undefined) return [];
|
|
19
34
|
if (!Array.isArray(value) || !value.every((item) => item && typeof item === 'object'
|
|
@@ -57,7 +72,12 @@ function coversIssue(bullet: string, issue: Issue, others: Issue[]): boolean {
|
|
|
57
72
|
// A source with no English words to compare (e.g. a Korean checklist title) is covered structurally —
|
|
58
73
|
// one bullet per input ID — instead of blocking the release (review R2).
|
|
59
74
|
if (words.length === 0) return true;
|
|
60
|
-
|
|
75
|
+
// Korean accepted notes may share their only English token (a tracking label) across
|
|
76
|
+
// distinct note groups. In that case the ID-to-original-note mapping and the distinct,
|
|
77
|
+
// safe public bullet per group are the available coverage proof; there is no English
|
|
78
|
+
// term that can identify either group by lexical comparison.
|
|
79
|
+
if (issue.note !== undefined && others.length > 0 && distinctive.length === 0 && /[^\x00-\x7f]/.test(source)) return true;
|
|
80
|
+
return distinctive.length > 0 && distinctive.some((word) => publicWords.has(word));
|
|
61
81
|
}
|
|
62
82
|
|
|
63
83
|
function cleanBullet(text: string): string | null {
|
|
@@ -112,17 +132,25 @@ export function runKnownIssues(context: GraphContext = readGraphContext(), run:
|
|
|
112
132
|
if (!existsSync(notes)) throw new Error(`release notes missing: ${notes}`);
|
|
113
133
|
const checklist = issues(context.outputs['checklist-gate']?.knownIssues, 'checklist');
|
|
114
134
|
const accepted = issues(context.input.acceptedRegressions, 'accepted');
|
|
135
|
+
const approved0233Batch = version === '0.2.33' && accepted.length === APPROVED_0233_INPUT.length
|
|
136
|
+
&& new Set(accepted.map((issue) => issue.id)).size === accepted.length
|
|
137
|
+
&& accepted.every((issue) => APPROVED_0233_BY_ID.get(issue.id) === issue.note);
|
|
115
138
|
const sources = { checklist: checklist.length, accepted: accepted.length };
|
|
116
139
|
if (!checklist.length && !accepted.length) return { outcome: 'ok' as const, verdict: 'pass' as const, summary: '알려진 문제 없음', count: 0, bullets: [] as string[], sources, fallbackUsed: false };
|
|
117
140
|
|
|
118
141
|
let bullets: string[];
|
|
119
142
|
let fallbackUsed = false;
|
|
120
|
-
const
|
|
143
|
+
const groupByBullet = new Map<string, string>();
|
|
144
|
+
const sourceGroupByRawBullet = new Map<string, string>();
|
|
145
|
+
const checklistIssues = new Set<Issue>(checklist);
|
|
121
146
|
// The persisted failed-node waiver, not a claimed output or an ID prefix, is the public-note provenance.
|
|
122
147
|
const waiverIssues = recordedWaivers(context, accepted);
|
|
123
|
-
const
|
|
148
|
+
const waiverNotes = new Set(waiverIssues.map((issue) => issue.note));
|
|
149
|
+
// A verified waiver's public reason represents every accepted ID with that same note.
|
|
150
|
+
const acceptedForModel = accepted.filter((issue) => !waiverNotes.has(issue.note));
|
|
151
|
+
const modelIssues = [...checklist, ...acceptedForModel];
|
|
124
152
|
const sourceIds = modelIssues.map((issue) => issue.id);
|
|
125
|
-
const prompt = `Write public English release-note bullets for these known issues. Describe only user-visible impact; include a one-line workaround when available. No internal names, test paths, track names, PR numbers, or people. Each bullet must have at most two sentences. Return ONLY a JSON array with exactly one object {"id":"input ID","bullet":"English public sentence"} for each input, using each input ID exactly once. Do not include IDs in bullet text. Input: ${JSON.stringify({ checklist, acceptedRegressions:
|
|
153
|
+
const prompt = `Write public English release-note bullets for these known issues. Describe only user-visible impact; include a one-line workaround when available. No internal names, test paths, track names, PR numbers, or people. Each bullet must have at most two sentences. Return ONLY a JSON array with exactly one object {"id":"input ID","bullet":"English public sentence"} for each input, using each input ID exactly once. Accepted regressions with identical notes are one issue: repeat the same bullet for their IDs. Do not include IDs in bullet text. Input: ${JSON.stringify({ checklist, acceptedRegressions: acceptedForModel })}`;
|
|
126
154
|
let response: ReturnType<CommandRunner> = { status: 0, stdout: JSON.stringify({ reply: '[]' }), stderr: '' };
|
|
127
155
|
if (modelIssues.length) {
|
|
128
156
|
try {
|
|
@@ -136,20 +164,54 @@ export function runKnownIssues(context: GraphContext = readGraphContext(), run:
|
|
|
136
164
|
fallbackUsed = true;
|
|
137
165
|
} else {
|
|
138
166
|
try {
|
|
167
|
+
const fallbackGroups = new Set<string>();
|
|
139
168
|
bullets = generatedBullets(response.stdout, sourceIds).map((line, index) => {
|
|
169
|
+
const issue = modelIssues[index]!;
|
|
170
|
+
const group = issueGroup(issue, checklistIssues);
|
|
171
|
+
const raw = line.trim();
|
|
172
|
+
const previousGroup = sourceGroupByRawBullet.get(raw);
|
|
173
|
+
if (previousGroup && previousGroup !== group) throw new Error('known issues response repeats or splits an issue instead of covering each input');
|
|
174
|
+
sourceGroupByRawBullet.set(raw, group);
|
|
140
175
|
const safe = cleanBullet(line);
|
|
141
176
|
if (!safe) {
|
|
142
177
|
fallbackUsed = true;
|
|
143
178
|
return FALLBACK;
|
|
144
179
|
}
|
|
145
|
-
if (resolved.test(safe))
|
|
146
|
-
|
|
180
|
+
if (resolved.test(safe)) {
|
|
181
|
+
if (checklistIssues.has(issue) || !/[^\x00-\x7f]/.test(issue.note ?? '')) throw new Error(`bullet for ${sourceIds[index]} claims the issue is resolved`);
|
|
182
|
+
const replacement = acceptedNoteFallback(issue, approved0233Batch);
|
|
183
|
+
if (!replacement) throw new Error(`deterministic public bullet unavailable for ${sourceIds[index]}`);
|
|
184
|
+
fallbackUsed = true;
|
|
185
|
+
fallbackGroups.add(group);
|
|
186
|
+
return replacement;
|
|
187
|
+
}
|
|
188
|
+
if (!coversIssue(safe, issue, modelIssues.filter((other, otherIndex) => otherIndex !== index && issueGroup(other, checklistIssues) !== group))) {
|
|
189
|
+
if (!checklistIssues.has(issue) && /[^\x00-\x7f]/.test(issue.note ?? '')) {
|
|
190
|
+
const replacement = acceptedNoteFallback(issue, approved0233Batch);
|
|
191
|
+
if (!replacement) throw new Error(`deterministic public bullet unavailable for ${sourceIds[index]}`);
|
|
192
|
+
fallbackUsed = true;
|
|
193
|
+
fallbackGroups.add(group);
|
|
194
|
+
return replacement;
|
|
195
|
+
}
|
|
147
196
|
throw new Error(`bullet does not identify input ${sourceIds[index]}`);
|
|
148
197
|
}
|
|
149
198
|
return safe;
|
|
150
199
|
});
|
|
151
|
-
|
|
152
|
-
|
|
200
|
+
// One accepted note is one public issue. A failed ID cannot leave a mixed model/fallback group.
|
|
201
|
+
bullets = bullets.map((bullet, index) => fallbackGroups.has(issueGroup(modelIssues[index]!, checklistIssues))
|
|
202
|
+
? acceptedNoteFallback(modelIssues[index]!, approved0233Batch)! : bullet);
|
|
203
|
+
const bulletByGroup = new Map<string, string>();
|
|
204
|
+
for (const [index, bullet] of bullets.entries()) {
|
|
205
|
+
const group = issueGroup(modelIssues[index]!, checklistIssues);
|
|
206
|
+
if (bulletByGroup.has(group) && bulletByGroup.get(group) !== bullet) {
|
|
207
|
+
throw new Error('known issues response repeats or splits an issue instead of covering each input');
|
|
208
|
+
}
|
|
209
|
+
bulletByGroup.set(group, bullet);
|
|
210
|
+
if (bullet === FALLBACK) continue;
|
|
211
|
+
if (groupByBullet.has(bullet) && groupByBullet.get(bullet) !== group) {
|
|
212
|
+
throw new Error('known issues response repeats or splits an issue instead of covering each input');
|
|
213
|
+
}
|
|
214
|
+
groupByBullet.set(bullet, group);
|
|
153
215
|
}
|
|
154
216
|
bullets = [...new Set(bullets)];
|
|
155
217
|
} catch (error) {
|
|
@@ -157,10 +219,17 @@ export function runKnownIssues(context: GraphContext = readGraphContext(), run:
|
|
|
157
219
|
}
|
|
158
220
|
}
|
|
159
221
|
// A waiver's supplied public impact must survive even when the model omits it or is unavailable.
|
|
222
|
+
// The generic fallback may aggregate model issues, but it cannot also stand in for a distinct waiver group.
|
|
223
|
+
if (bullets.includes(FALLBACK)) groupByBullet.set(FALLBACK, 'fallback-aggregate');
|
|
160
224
|
for (const issue of waiverIssues) {
|
|
161
225
|
const bullet = cleanBullet(issue.note ?? '');
|
|
162
226
|
if (!bullet || resolved.test(bullet)) throw new Error(`unsafe public waiver reason for ${issue.id}`);
|
|
163
227
|
const publicBullet = /[.!?]$/.test(bullet) ? bullet : `${bullet}.`;
|
|
228
|
+
const group = issueGroup(issue, checklistIssues);
|
|
229
|
+
if (groupByBullet.has(publicBullet) && groupByBullet.get(publicBullet) !== group) {
|
|
230
|
+
throw new Error(`known issues coverage not verified: waiver bullet repeats another issue for ${issue.id}`);
|
|
231
|
+
}
|
|
232
|
+
groupByBullet.set(publicBullet, group);
|
|
164
233
|
if (!bullets.includes(publicBullet)) bullets.push(publicBullet);
|
|
165
234
|
}
|
|
166
235
|
const original = readFileSync(notes, 'utf8');
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
// `elanous release preflight` — 컷 30분
|
|
1
|
+
// `elanous release preflight` — 컷 −30분 운영 점검 + 컷 −60분 main export 사전 점검.
|
|
2
2
|
//
|
|
3
3
|
// 🩸 계기(10-06 실측): 0.2.17 릴리스 런이 첫 노드(checklist-gate)에서 멎었다 — «발행 뒤» 칸(POSTPUB-VERIFY)이 그 판에
|
|
4
|
-
// 남아 있었고 게이트가 그것을 미완으로 셌다.
|
|
4
|
+
// 남아 있었고 게이트가 그것을 미완으로 셌다. 컷 전 체크리스트 점검은 착지 마감 컷 −30분, F9 export 는 main HEAD 에서 컷 −60분 수동 실행.
|
|
5
5
|
// ⛔ 읽기 전용 — 칸을 옮기지도, 동결을 바꾸지도, push 하지도 않는다. 옮길 것은 «명령»으로 제안만 한다.
|
|
6
6
|
// ⛔ 게이트 규칙을 다시 쓰지 않는다 — checklist-gate 노드 · release run 진입 검사 · 예약 시작 준비 검사(releaseReadiness, #24557)가
|
|
7
7
|
// 함께 쓰는 단 하나의 판정 cutChecklistGate 를 그대로 부르고, 예약 시작 경로는 releaseReadiness 를 CLI 와 같은 인자로 부른다.
|
|
8
|
-
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, mkdtempSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
11
|
+
import { spawnSync } from 'node:child_process';
|
|
10
12
|
import { cutChecklistGate, listChecklist, type ChecklistItem } from '../../src/release-loop/checklist.js';
|
|
11
13
|
import { getSchedule, formatKst, type ReleaseSchedule } from '../../src/release-loop/release-schedule.js';
|
|
12
14
|
import { readLandingFreeze, landingFreezeMessage, type LandingFreeze } from '../../src/release-loop/landing-freeze.js';
|
|
@@ -14,9 +16,10 @@ import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
|
14
16
|
import { debug } from '../../src/debug/log.js';
|
|
15
17
|
import { releaseReadiness } from './release-readiness.js';
|
|
16
18
|
import { latestPublishedPreviousVersion, runUnattendedRelease, type UnattendedReleaseDeps } from './unattended-release.js';
|
|
19
|
+
import { loadExportConfig, run as runPublicExport, selectExportFiles } from '../public-export.js';
|
|
17
20
|
|
|
18
21
|
export type PreflightLevel = 'ok' | 'warn' | 'block';
|
|
19
|
-
export type PreflightCheck = 'checklist' | 'postpub' | 'run-input' | 'freeze' | 'schedule';
|
|
22
|
+
export type PreflightCheck = 'checklist' | 'postpub' | 'run-input' | 'freeze' | 'schedule' | 'export';
|
|
20
23
|
export interface PreflightFinding { level: PreflightLevel; check: PreflightCheck; id?: string; message: string; suggestion?: string }
|
|
21
24
|
export interface GateMeasure { version: string; runId: string; gateSeconds: number; toPublishSeconds?: number }
|
|
22
25
|
const compareStable = (a: string, b: string) => { const x = a.split('.').map(Number), y = b.split('.').map(Number); return x[0]! - y[0]! || x[1]! - y[1]! || x[2]! - y[2]!; };
|
|
@@ -27,7 +30,8 @@ export interface PreflightResult {
|
|
|
27
30
|
blockers: number;
|
|
28
31
|
warnings: number;
|
|
29
32
|
findings: PreflightFinding[];
|
|
30
|
-
schedule: { cutAt: string; landBy: string | null; publishAt: string | null; publishAtSource: 'option' | 'schedule' | 'cadence' | null } | null;
|
|
33
|
+
schedule: { cutAt: string; landBy: string | null; publishAt: string | null; publishAtSource: 'option' | 'schedule' | 'cadence' | null; exportCheckAt: string } | null;
|
|
34
|
+
exportCheck: { mainSha: string; files: number; leaks: number; codeLiterals: number } | null;
|
|
31
35
|
/** The immediately previous release (by version order) whose gate is compared. */
|
|
32
36
|
previousVersion: string | null;
|
|
33
37
|
gateMeasure: GateMeasure | null;
|
|
@@ -46,6 +50,72 @@ export interface PreflightDeps {
|
|
|
46
50
|
releaseRunDeps?: UnattendedReleaseDeps;
|
|
47
51
|
/** The immediately previous release; default = the run input's previousVersion (release ledger). */
|
|
48
52
|
previousVersion?: string;
|
|
53
|
+
/** Injectable for deterministic preflight tests. Production pins origin/main and scans a disposable checkout. */
|
|
54
|
+
exportCheck?: () => Promise<{ mainSha: string; files: number; leaks: number; codeLiterals: number }>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function runGit(cwd: string, args: string[]): string {
|
|
58
|
+
const result = spawnSync('git', args, { cwd, encoding: 'utf8', maxBuffer: 16 << 20 });
|
|
59
|
+
if (result.status !== 0) throw new Error(`git ${args.join(' ')} 실패 rc=${result.status}: ${(result.stderr ?? '').trim().slice(0, 300)}`);
|
|
60
|
+
return (result.stdout ?? '').trim();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Read-only main snapshot: all checkout and cleanup writes are contained in a disposable temp directory. */
|
|
64
|
+
export async function scanOriginMainExport(): Promise<{ mainSha: string; files: number; leaks: number; codeLiterals: number }> {
|
|
65
|
+
const repoRoot = runGit(process.cwd(), ['rev-parse', '--show-toplevel']);
|
|
66
|
+
const mainSha = runGit(repoRoot, ['rev-parse', '--verify', 'origin/main^{commit}']);
|
|
67
|
+
const temp = mkdtempSync(join(tmpdir(), 'release-preflight-main-'));
|
|
68
|
+
const snapshot = join(temp, 'checkout');
|
|
69
|
+
try {
|
|
70
|
+
runGit(temp, ['clone', '--shared', '--no-checkout', '--quiet', repoRoot, snapshot]);
|
|
71
|
+
runGit(snapshot, ['read-tree', mainSha]);
|
|
72
|
+
const tracked = runGit(snapshot, ['ls-files', '-z']).split('\0').filter(Boolean);
|
|
73
|
+
const trackedSet = new Set(tracked);
|
|
74
|
+
// `git check-ignore --no-index` applies every nested ignore file, including ones below selected paths.
|
|
75
|
+
const needed = new Set(tracked.filter((file) => file === '.gitignore' || file.endsWith('/.gitignore')));
|
|
76
|
+
needed.add('release/public-export.yaml');
|
|
77
|
+
// Read only the paths the pinned manifest can inspect; the full tracked-path index stays at mainSha.
|
|
78
|
+
const manifestPath = join(snapshot, 'release/public-export.yaml');
|
|
79
|
+
const manifest = spawnSync('git', ['-C', snapshot, 'show', `${mainSha}:release/public-export.yaml`], { encoding: 'utf8', maxBuffer: 4 << 20 });
|
|
80
|
+
if (manifest.status !== 0) throw new Error(`origin/main public export manifest 읽기 실패: ${(manifest.stderr ?? '').trim()}`);
|
|
81
|
+
mkdirSync(join(snapshot, 'release'), { recursive: true });
|
|
82
|
+
writeFileSync(manifestPath, manifest.stdout ?? '');
|
|
83
|
+
const config = loadExportConfig(snapshot);
|
|
84
|
+
const selected = selectExportFiles(tracked, config);
|
|
85
|
+
for (const file of selected) needed.add(file);
|
|
86
|
+
for (const source of Object.values(config.replace)) needed.add(source);
|
|
87
|
+
if (config.skills) {
|
|
88
|
+
needed.add('catalog/resources.yaml');
|
|
89
|
+
needed.add('src/video-pipeline/capabilities.ts');
|
|
90
|
+
for (const file of tracked) if (/^skills\/[^/]+\/SKILL\.md$/u.test(file)) needed.add(file);
|
|
91
|
+
for (const file of tracked) {
|
|
92
|
+
const skill = /^skills\/([^/]+)\//u.exec(file)?.[1];
|
|
93
|
+
if (skill) mkdirSync(join(snapshot, 'skills', skill), { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const checkout = spawnSync('git', ['-C', snapshot, 'checkout-index', '--stdin', '-z', '-f'], {
|
|
97
|
+
input: `${[...needed].filter((file) => trackedSet.has(file)).join('\0')}\0`, encoding: 'utf8', maxBuffer: 16 << 20,
|
|
98
|
+
});
|
|
99
|
+
if (checkout.status !== 0) throw new Error(`origin/main export 입력 파일 준비 실패 rc=${checkout.status}: ${(checkout.stderr ?? '').trim().slice(0, 300)}`);
|
|
100
|
+
let output = '';
|
|
101
|
+
const originalLog = console.log;
|
|
102
|
+
const originalError = console.error;
|
|
103
|
+
console.log = (...args: unknown[]) => { output += `${args.map(String).join(' ')}\n`; };
|
|
104
|
+
console.error = () => {};
|
|
105
|
+
let code: number;
|
|
106
|
+
try { code = runPublicExport(['--leak-check', '--json'], snapshot); }
|
|
107
|
+
finally { console.log = originalLog; console.error = originalError; }
|
|
108
|
+
const report = JSON.parse(output.trim()) as {
|
|
109
|
+
files?: number; leaks?: number; hits?: Array<{ marker: string }>; codeLiterals?: { hits?: number };
|
|
110
|
+
privateRedactions?: { loaded?: boolean };
|
|
111
|
+
};
|
|
112
|
+
if (report.privateRedactions?.loaded !== true) throw new Error('개인 치환표를 읽지 못해 export 누수 검사를 완결할 수 없다');
|
|
113
|
+
if (typeof report.files !== 'number' || typeof report.leaks !== 'number') throw new Error('public-export 검사 결과가 완전하지 않다');
|
|
114
|
+
if (code !== (report.leaks > 0 ? 1 : 0)) throw new Error(`public-export 종료 코드와 누수 결과 불일치: rc=${code} leaks=${report.leaks}`);
|
|
115
|
+
return { mainSha, files: report.files, leaks: report.leaks, codeLiterals: report.codeLiterals?.hits ?? 0 };
|
|
116
|
+
} finally {
|
|
117
|
+
rmSync(temp, { recursive: true, force: true });
|
|
118
|
+
}
|
|
49
119
|
}
|
|
50
120
|
|
|
51
121
|
const POSTPUB_ID = /^POSTPUB-/i;
|
|
@@ -127,6 +197,7 @@ export async function releasePreflight(version: string, deps: PreflightDeps = {}
|
|
|
127
197
|
const now = deps.now ?? new Date();
|
|
128
198
|
const next = nextPatch(version);
|
|
129
199
|
const findings: PreflightFinding[] = [];
|
|
200
|
+
let exportCheck: PreflightResult['exportCheck'] = null;
|
|
130
201
|
const moveHint = (id: string) => `elanous release checklist move ${id} --from ${version} --to ${next} --reason "발행 뒤 칸 — 다음 판에서 확인"`;
|
|
131
202
|
|
|
132
203
|
// 1·2. Checklist gate simulation «at the cut» (the node and the run entry both judge after land-by) ⊕ post-publish cells.
|
|
@@ -176,6 +247,17 @@ export async function releasePreflight(version: string, deps: PreflightDeps = {}
|
|
|
176
247
|
for (const p of gate.parity ?? []) findings.push({ level: 'warn', check: 'checklist', id: p.id, message: `${p.id} — 화면 짝 경고: ${p.why}` });
|
|
177
248
|
if (!blockReason.size) findings.push({ level: 'ok', check: 'checklist', message: `체크리스트 게이트 모의 통과 — ${data.items.length}칸 · 이월 ${gate.moved.length} · 알려진 문제 ${gate.knownIssues.length}` });
|
|
178
249
|
|
|
250
|
+
// 3a. Public export leakage is measured against one pinned origin/main commit, never this possibly dirty branch.
|
|
251
|
+
try {
|
|
252
|
+
exportCheck = await (deps.exportCheck ?? scanOriginMainExport)();
|
|
253
|
+
findings.push(exportCheck.leaks
|
|
254
|
+
? { level: 'block', check: 'export', message: `origin/main ${exportCheck.mainSha.slice(0, 12)} 공개 export 누수 ${exportCheck.leaks}건 · ${exportCheck.files} 파일 검사` }
|
|
255
|
+
: { level: 'ok', check: 'export', message: `origin/main ${exportCheck.mainSha.slice(0, 12)} 공개 export 누수 0건 · ${exportCheck.files} 파일 검사` });
|
|
256
|
+
if (exportCheck.codeLiterals) findings.push({ level: 'warn', check: 'export', message: `코드 리터럴 표지 ${exportCheck.codeLiterals}건은 문서/주석 누수에서 분리해 기록` });
|
|
257
|
+
} catch (error) {
|
|
258
|
+
findings.push({ level: 'block', check: 'export', message: `origin/main 공개 export 검사를 완료하지 못했다 — ${error instanceof Error ? error.message : String(error)}` });
|
|
259
|
+
}
|
|
260
|
+
|
|
179
261
|
// 3. The same input check `release run --dry-run` makes.
|
|
180
262
|
let runPrevious: string | undefined;
|
|
181
263
|
try {
|
|
@@ -209,7 +291,11 @@ export async function releasePreflight(version: string, deps: PreflightDeps = {}
|
|
|
209
291
|
// --publish-at > the stored schedule publish time (`release schedule set --publish-at`) > the October cadence.
|
|
210
292
|
const publishAtSource = deps.publishAt ? 'option' : schedule.publishAt ? 'schedule' : 'cadence';
|
|
211
293
|
const publishAt = deps.publishAt ? new Date(deps.publishAt).toISOString() : schedule.publishAt ?? cadencePublishAt(schedule.cutAt);
|
|
212
|
-
|
|
294
|
+
const exportCheckAt = new Date(cut - 60 * 60_000).toISOString();
|
|
295
|
+
scheduleOut = { cutAt: schedule.cutAt, landBy: schedule.landBy, publishAt, publishAtSource, exportCheckAt };
|
|
296
|
+
findings.push(Date.parse(now.toISOString()) < Date.parse(exportCheckAt)
|
|
297
|
+
? { level: 'warn', check: 'schedule', message: `main export 검사 시각 ${formatKst(exportCheckAt)}(컷 − 60분)보다 이르다 · OP가 그 시각에 수동 실행` }
|
|
298
|
+
: { level: 'ok', check: 'schedule', message: `main export 검사 시각 ${formatKst(exportCheckAt)}(컷 − 60분) · 자동 예약 없음` });
|
|
213
299
|
if (!schedule.landBy) findings.push({ level: 'warn', check: 'schedule', message: `착지 마감 없음 — 컷 ${formatKst(schedule.cutAt)} · 규칙은 컷 − 30분` });
|
|
214
300
|
else if (cut - Date.parse(schedule.landBy) < 30 * 60_000) findings.push({ level: 'warn', check: 'schedule', message: `착지 마감 ${formatKst(schedule.landBy)} 이 컷 − 30분보다 늦다(컷 ${formatKst(schedule.cutAt)})` });
|
|
215
301
|
else findings.push({ level: 'ok', check: 'schedule', message: `일정 — 착지 마감 ${formatKst(schedule.landBy)} · 컷 ${formatKst(schedule.cutAt)}` });
|
|
@@ -233,7 +319,7 @@ export async function releasePreflight(version: string, deps: PreflightDeps = {}
|
|
|
233
319
|
const blockers = findings.filter((f) => f.level === 'block').length;
|
|
234
320
|
const warnings = findings.filter((f) => f.level === 'warn').length;
|
|
235
321
|
debug.log('release.preflight', 'checked', { version, blockers, warnings });
|
|
236
|
-
return { version, next, verdict: blockers ? 'block' : warnings ? 'warn' : 'ok', blockers, warnings, findings, schedule: scheduleOut, previousVersion, gateMeasure, fallbackGateMeasure };
|
|
322
|
+
return { version, next, verdict: blockers ? 'block' : warnings ? 'warn' : 'ok', blockers, warnings, findings, schedule: scheduleOut, exportCheck, previousVersion, gateMeasure, fallbackGateMeasure };
|
|
237
323
|
}
|
|
238
324
|
|
|
239
325
|
const ICON: Record<PreflightLevel, string> = { ok: '✅', warn: '⚠️', block: '⛔' };
|
|
@@ -1,14 +1,55 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { WARNING_ONLY } from './auto-approve-node.js';
|
|
5
|
+
import { BLOCKING_METRIC_NAMES, WARNING_ONLY } from './auto-approve-node.js';
|
|
6
6
|
import { beginLandingMerge, landingFreezeMessage } from '../../src/release-loop/landing-freeze.js';
|
|
7
7
|
import { debug } from '../../src/debug/log.js';
|
|
8
8
|
import { registerStandaloneLogSink } from '../../src/domains/standalone-log-sink.js';
|
|
9
|
+
import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
9
10
|
import { prereleaseKind } from './release-version.js';
|
|
10
11
|
import { publishAtError } from './publish-at.js';
|
|
11
|
-
import {
|
|
12
|
+
import { validatedTuiRegress } from './tui-node-checks.js';
|
|
13
|
+
import { errorResult, finishNode, lastResult, nodeOutput, readGraphContext, runCommand, type CommandRunner, type GraphContext } from './node-verdict.js';
|
|
14
|
+
|
|
15
|
+
/** The approval output alone is not authority: the runner also stores a one-winner decision claim for this visit. */
|
|
16
|
+
export function hasRecordedPublishApproval(context: GraphContext, root: string): boolean {
|
|
17
|
+
const runId = context.runId;
|
|
18
|
+
const approval = context.outputs['approve-publish'];
|
|
19
|
+
if (!runId || !/^[A-Za-z0-9_-]+$/.test(runId) || approval?.outcome !== 'approved'
|
|
20
|
+
|| approval.graphId !== 'release-loop' || approval.runId !== runId || approval.nodeId !== 'approve-publish'
|
|
21
|
+
|| typeof approval.decidedAt !== 'string' || Number.isNaN(Date.parse(approval.decidedAt))) return false;
|
|
22
|
+
try {
|
|
23
|
+
const statePath = join(root, 'graph-runs', 'release-loop', `${runId}.json`);
|
|
24
|
+
const state = JSON.parse(readFileSync(statePath, 'utf8')) as {
|
|
25
|
+
graphId?: string; runId?: string; path?: string[];
|
|
26
|
+
nodes?: Array<{ nodeId?: string; ok?: boolean; output?: unknown; decidedAt?: string }>;
|
|
27
|
+
};
|
|
28
|
+
const visit = state.path?.lastIndexOf('approve-publish') ?? -1;
|
|
29
|
+
if (state.graphId !== 'release-loop' || state.runId !== runId || state.path?.at(-1) !== 'publish'
|
|
30
|
+
|| visit < 0 || !Array.isArray(state.nodes)) return false;
|
|
31
|
+
const node = state.nodes.filter((item) => item.nodeId === 'approve-publish').at(-1);
|
|
32
|
+
const output = typeof node?.output === 'string' ? JSON.parse(node.output) as Record<string, unknown> : null;
|
|
33
|
+
if (!node?.ok || node.decidedAt !== approval.decidedAt || output?.runId !== runId
|
|
34
|
+
|| output?.decidedAt !== approval.decidedAt || output?.outcome !== 'approved') return false;
|
|
35
|
+
const claim = JSON.parse(readFileSync(`${statePath}.${visit + 1}.decision.json`, 'utf8')) as Record<string, unknown>;
|
|
36
|
+
return claim.nodeId === 'approve-publish' && claim.decision === 'approved'
|
|
37
|
+
&& claim.decidedAt === approval.decidedAt;
|
|
38
|
+
} catch { return false; }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Warning rows may be repeated, but each of the eight fixed gates must occur exactly once in its declared order. */
|
|
42
|
+
export function hasMeasuredApprovalMetrics(metrics: unknown): boolean {
|
|
43
|
+
if (!Array.isArray(metrics) || !metrics.every((row: unknown) => row && typeof row === 'object'
|
|
44
|
+
&& typeof (row as Record<string, unknown>).name === 'string'
|
|
45
|
+
&& (row as Record<string, unknown>).verdict === 'pass')) return false;
|
|
46
|
+
const rows = metrics as Array<{ name: string; verdict: string }>;
|
|
47
|
+
const fixed = rows.filter((row) => !WARNING_ONLY.has(row.name));
|
|
48
|
+
return fixed.length === BLOCKING_METRIC_NAMES.length
|
|
49
|
+
&& BLOCKING_METRIC_NAMES.every((name, index) => fixed[index]?.name === name)
|
|
50
|
+
&& rows.some((row) => row.name === 'tui-regress')
|
|
51
|
+
&& rows.some((row) => row.name === 'mac-smoke');
|
|
52
|
+
}
|
|
12
53
|
|
|
13
54
|
export function publicNotes(markdown: string, pages: { pages: Array<{ id: string; slug?: string; source?: string }> }): string {
|
|
14
55
|
if (!Array.isArray(pages.pages)) throw new Error('invalid public pages registry');
|
|
@@ -46,7 +87,8 @@ export function waitForAssets(run: CommandRunner, repo: string, tag: string, nam
|
|
|
46
87
|
}
|
|
47
88
|
|
|
48
89
|
export function runPublish(run: CommandRunner = runCommand, prodFreezeRoot?: string,
|
|
49
|
-
clock: { now: () => number; sleep: (ms: number) => void } = { now: Date.now, sleep: Bun.sleepSync }
|
|
90
|
+
clock: { now: () => number; sleep: (ms: number) => void } = { now: Date.now, sleep: Bun.sleepSync },
|
|
91
|
+
approvalRoot = effectiveInstanceRoot()) {
|
|
50
92
|
const context = readGraphContext();
|
|
51
93
|
// A resumed graph once invoked this irreversible node at npm-publish, docs-land, and failed.
|
|
52
94
|
// The runner's context is the authority: only the publish visit may publish.
|
|
@@ -54,12 +96,21 @@ export function runPublish(run: CommandRunner = runCommand, prodFreezeRoot?: str
|
|
|
54
96
|
const version = context.input.version;
|
|
55
97
|
// A measured automatic decision or the existing human approval must authorize publication.
|
|
56
98
|
const auto = context.outputs['auto-approve'];
|
|
57
|
-
|
|
99
|
+
const regress = validatedTuiRegress(context.outputs.tui?.regress);
|
|
100
|
+
const approvedForRun = hasRecordedPublishApproval(context, approvalRoot);
|
|
101
|
+
if (!approvedForRun &&
|
|
58
102
|
!(auto?.outcome === 'ok' && auto.decidedBy === 'release-loop metrics'
|
|
59
|
-
|
|
60
|
-
&&
|
|
61
|
-
&& auto.
|
|
62
|
-
&& auto.
|
|
103
|
+
&& !('unmeasured' in regress) && regress.pass === 7 && regress.fail === 0
|
|
104
|
+
&& typeof context.runId === 'string' && context.runId.length > 0 && auto.runId === context.runId
|
|
105
|
+
&& auto.tuiSubcheck && typeof auto.tuiSubcheck === 'object'
|
|
106
|
+
&& (auto.tuiSubcheck as Record<string, unknown>).runId === context.runId
|
|
107
|
+
&& (auto.tuiSubcheck as Record<string, unknown>).level === 'ok'
|
|
108
|
+
&& (auto.tuiSubcheck as Record<string, unknown>).fail === 0
|
|
109
|
+
&& Array.isArray((auto.tuiSubcheck as Record<string, unknown>).failedCheckIds)
|
|
110
|
+
&& ((auto.tuiSubcheck as Record<string, unknown>).failedCheckIds as unknown[]).length === 0
|
|
111
|
+
&& (auto.tuiSubcheck as Record<string, unknown>).approvalRequired === false
|
|
112
|
+
// Eight fixed metrics; the TUI subcheck is outside that count but its fail/unmeasured verdict still blocks auto-publish.
|
|
113
|
+
&& hasMeasuredApprovalMetrics(auto.metrics))) {
|
|
63
114
|
return { outcome: 'fail' as const, verdict: 'fail' as const, summary: 'publish blocked: neither auto-approve nor approve-publish approved' };
|
|
64
115
|
}
|
|
65
116
|
for (const node of ['gate', 'pwa', 'upgrade', 'tui', 'prepare', 'docs']) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { DecisionLedger } from '../../src/decisions/decision-ledger.js';
|
|
5
|
+
import type { GraphRunState } from '../../src/graph-runner/runner.js';
|
|
6
|
+
import { isReleaseVersion } from './release-version.js';
|
|
7
|
+
|
|
8
|
+
export const RELEASE_RESUME_LIMIT = 2;
|
|
9
|
+
|
|
10
|
+
/** Called under the OP seat flock, before any branch-tip or graph-run mutation. */
|
|
11
|
+
export function reserveReleaseResumeAttempt(state: GraphRunState, root: string, options: {
|
|
12
|
+
now?: () => Date;
|
|
13
|
+
openCard?: (version: string, runId: string, reason: string) => string;
|
|
14
|
+
/** Under the OP flock, check capacity before tip preflight without consuming an attempt. */
|
|
15
|
+
checkOnly?: boolean;
|
|
16
|
+
/** A dry-run reports the cap without creating an OP decision card. */
|
|
17
|
+
noDecision?: boolean;
|
|
18
|
+
} = {}): { attempt: number; path: string } {
|
|
19
|
+
const version = (state.input as { version?: unknown } | undefined)?.version;
|
|
20
|
+
if (typeof version !== 'string' || !isReleaseVersion(version) || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(state.runId))
|
|
21
|
+
throw new Error('release resume cap requires a valid saved version and run id');
|
|
22
|
+
const path = join(root, 'release', version, 'resume-attempts', `${state.runId}.json`);
|
|
23
|
+
const card = options.openCard ?? ((v: string, id: string, reason: string) => {
|
|
24
|
+
const ref = `release-resume-cap:${v}:${id}`;
|
|
25
|
+
return new DecisionLedger({ stateDir: root, now: options.now }).raiseOnce({
|
|
26
|
+
title: `${v} release resume limit: ${id}`, category: 'scope',
|
|
27
|
+
scqa: { s: `Release ${v} run ${id} has reached its two-resume limit.`, c: reason,
|
|
28
|
+
q: 'Should this release be deferred or moved to the next version?' },
|
|
29
|
+
options: [{ key: 'a', label: 'Defer this release', consequence: 'Stop this run and reschedule the release.' },
|
|
30
|
+
{ key: 'b', label: 'Move to next version', consequence: 'Stop this run and carry the work to a new release.' }],
|
|
31
|
+
recommendation: { skipped: true, reason: 'OP must choose the release disposition.' },
|
|
32
|
+
raisedBy: { agent: 'release-resume-cap', track: 'TC' }, refs: [ref],
|
|
33
|
+
}, ref).id;
|
|
34
|
+
});
|
|
35
|
+
const blocked = (reason: string): never => {
|
|
36
|
+
if (options.noDecision) throw new Error(`release resume limit reached: ${reason}`);
|
|
37
|
+
throw new Error(`release resume limit reached — decision ${card(version, state.runId, reason)}: ${reason}`);
|
|
38
|
+
};
|
|
39
|
+
if (options.noDecision && !options.checkOnly) throw new Error('noDecision requires checkOnly');
|
|
40
|
+
if (!existsSync(path) && state.resume) blocked('saved run was resumed before attempt counting; prior count is unknown');
|
|
41
|
+
const prior = existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) as unknown : { version, runId: state.runId, attempts: [] };
|
|
42
|
+
if (!prior || typeof prior !== 'object' || Array.isArray(prior)) throw new Error('release resume attempts ledger invalid');
|
|
43
|
+
const saved = prior as { version?: unknown; runId?: unknown; attempts?: unknown };
|
|
44
|
+
if (saved.version !== version || saved.runId !== state.runId || !Array.isArray(saved.attempts)
|
|
45
|
+
|| saved.attempts.some(value => typeof value !== 'string' || !Number.isFinite(Date.parse(value))))
|
|
46
|
+
throw new Error('release resume attempts ledger invalid');
|
|
47
|
+
if (saved.attempts.length >= RELEASE_RESUME_LIMIT) blocked(`${saved.attempts.length} resumes already recorded`);
|
|
48
|
+
if (options.checkOnly) return { attempt: saved.attempts.length + 1, path };
|
|
49
|
+
const at = (options.now ?? (() => new Date()))().toISOString();
|
|
50
|
+
const next = { version, runId: state.runId, attempts: [...saved.attempts, at] };
|
|
51
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
52
|
+
const temp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
53
|
+
try { writeFileSync(temp, `${JSON.stringify(next)}\n`, { mode: 0o600 }); renameSync(temp, path); }
|
|
54
|
+
finally { try { unlinkSync(temp); } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; } }
|
|
55
|
+
return { attempt: next.attempts.length, path };
|
|
56
|
+
}
|