elanous 0.2.40 → 0.2.41
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/README.md +7 -7
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
- package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 1178.1aa9cad0e7695427.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2829-734fe8bf2eee7347.js → 1197-54da59d250a6e476.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 1219.7e17964e0e7cd8e5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 1800.f7ff51dc4978a958.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 2073.689dcb2680113d76.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 2263.e09b6edea33bad2d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9069.657590a84afb8fac.js → 2743.5d3f76948be32b34.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{6624.981ef7caeb680560.js → 2773.0e80b9d325fb5635.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9992.07ce73c10bd5e6a1.js → 3097.864e92bdaa2f4d15.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 385e4574.e9886ab32759eda3.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8086.1ab9103c41be884f.js → 4156.ba4de4a3664f04b4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 4527.a69f2894d1bc9f4a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{8357.1aaa713b052a78b1.js → 4667.97e31aa38c95c475.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 4702.4a4adc1f16d7c93b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 5159.115f1c2ca471386c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{d8de0de2-dd0f4ac8e5ab1832.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 5471.1e611302ed3a7c53.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 5574.f35accf4f132b29d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{2066.a77257c8c350770a.js → 5744.b9415e18ad623100.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 5937.c2df9e3447e1f667.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 5947-135e26537d80a6b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 5964-7e21164a8f2cf0ce.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{2047.8f23e210995d4548.js → 6874.d5cf7eb8edb2cabe.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8050-9b364bdef8f71927.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{2281-b8cede695c6c650e.js → 8464-e24f10451b658aac.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5622.94893f5aea7185d0.js → 8880.64c445592f04acaf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1452.162bb2d9d699e82a.js → 8981.c706964c8ba27aff.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 9048.212083de42d25be3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 9507.7026657a2f47eb64.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7515.1ad6efe157fa4448.js → 9579.4a8169600fff2058.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{2499.02fbfd18126c10c0.js → 9834.63ab2bbc3153172e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → a0a01613.6d1cca322238d7fe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6cc1d1d6.9a98dd4622f1afc6.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ba957ff875a026a0.js → page-14949db884bfa672.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{c696986b.5dc8bb1143af16d1.js → b2271e54.c1de3347976e90b0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → c0c1a699.0ba79f97005965d4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.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 +6 -1
- package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
- package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
- package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
- package/graphs/demo/persona-teacher/recipes.yaml +17 -0
- package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
- package/graphs/overlays/stop-heal-ladder.yaml +23 -2
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/units/gate/gate.yaml +20 -0
- package/graphs/units/git/git.yaml +26 -0
- package/graphs/units/implement/implement.yaml +19 -0
- package/graphs/units/landing/landing.yaml +18 -0
- package/graphs/units/review/review.yaml +20 -0
- package/graphs/units/verbs/recipes.yaml +3 -0
- package/graphs/units/verbs/research.yaml +20 -0
- package/graphs/work/research-report.yaml +11 -1
- package/package.json +1 -1
- package/scripts/disk-steward.ts +46 -0
- package/scripts/fleet/node-setup.sh +50 -0
- package/scripts/graph-units/verbs/research.ts +55 -0
- package/scripts/llm-cost-ledger.ts +179 -8
- package/scripts/measure-nl-routing-corpus.ts +10 -2
- package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
- package/scripts/public-copy-lint.ts +163 -19
- package/scripts/ratchets/train-side-invariants.sh +0 -1
- package/scripts/release-loop/gate-autoheal.ts +117 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
- package/scripts/release-loop/gate-diff.ts +22 -3
- package/scripts/release-loop/gate-node.ts +205 -17
- package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
- package/scripts/release-loop/gate-triage-node.ts +70 -10
- package/scripts/release-loop/resume-release.ts +247 -15
- package/scripts/release-loop/traffic-node.ts +6 -3
- package/scripts/release-loop/unattended-release.ts +4 -2
- package/scripts/shadow-authoring-probe.ts +20 -0
- package/scripts/ux-sim.ts +19 -2
- package/src/acp/core-turn-bridge.ts +86 -4
- package/src/agent-substrate/self-review-cli.ts +91 -29
- package/src/auto-research/research-turn.ts +10 -1
- package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
- package/src/boot/daemon-tools/self-implement.ts +46 -9
- package/src/budget/shadow-arms.ts +52 -0
- package/src/chat/pickers/state.ts +7 -1
- package/src/cli/log-event-names.ts +5 -0
- package/src/cli/mcp-login.ts +8 -18
- package/src/cli/msg-cli.ts +57 -1
- package/src/cli/pr-land-heavy-remote.ts +15 -9
- package/src/cli/release-cli.ts +27 -1
- package/src/cli/sim-cli.ts +7 -1
- package/src/cli/tasks-cli.ts +5 -4
- package/src/codex/models.ts +30 -15
- package/src/core-turn/run-core-turn.ts +3 -0
- package/src/core-turn/run-goal-loop.ts +88 -2
- package/src/dashboard/acp-boot.ts +72 -3
- package/src/dashboard/index.ts +6 -0
- package/src/dashboard/turn-preamble.ts +12 -1
- package/src/disk-steward/judge.ts +73 -0
- package/src/disk-steward/ledger.ts +122 -0
- package/src/disk-steward/steward.ts +373 -0
- package/src/domains/guardian-tick.ts +191 -2
- package/src/graph-runner/graph-cli.ts +21 -0
- package/src/graph-runner/in-process-registry.ts +37 -0
- package/src/graph-runner/runner.ts +33 -3
- package/src/grounding/ref-index.ts +19 -0
- package/src/grounding/sources-cli.ts +9 -1
- package/src/harness/harness-cli-command.ts +267 -14
- package/src/harness/harness-incidents.ts +312 -7
- package/src/harness/harness-space.ts +15 -1
- package/src/harness/progress-worker-entry.ts +59 -0
- package/src/harness/progress-worker-runtime.ts +11 -0
- package/src/index.ts +18 -2
- package/src/instance/dev-project.ts +25 -0
- package/src/intelligence-map/model-alias.ts +6 -5
- package/src/intelligence-map/model-catalog.ts +59 -2
- package/src/llm/model-defaults.ts +4 -4
- package/src/llm.ts +42 -11
- package/src/loops/orchestrator/tick.ts +48 -0
- package/src/mcp/mcp-oauth.ts +3 -1
- package/src/model-tier/llm-tier-map.ts +9 -9
- package/src/model-tier/turn-tier.ts +1 -1
- package/src/msg/msg-mirror-github.ts +80 -0
- package/src/msg/msg-mirror-policy.ts +61 -0
- package/src/msg/msg-mirror-runner.ts +219 -0
- package/src/msg/msg-mirror-state.ts +33 -0
- package/src/msg/msg-store.ts +11 -0
- package/src/output-truncation.ts +41 -12
- package/src/project/project-store.ts +48 -1
- package/src/release-loop/gate-host-reservation.ts +144 -0
- package/src/release-loop/release-schedule.ts +90 -1
- package/src/research/bloom-exemplars.ts +135 -0
- package/src/self-dev/ask-launch-flow.ts +39 -25
- package/src/self-dev/dev-cli.ts +17 -17
- package/src/self-dev/graph-front-nodes.ts +23 -0
- package/src/self-dev/launch-preflight.ts +9 -4
- package/src/self-dev/orchestrate.ts +15 -0
- package/src/self-dev/run-supervisor.ts +185 -3
- package/src/self-dev/run-types.ts +3 -0
- package/src/self-implement/gate-artifacts.ts +13 -0
- package/src/self-implement/gate-cli.ts +54 -24
- package/src/self-implement/gate-remote.ts +23 -5
- package/src/self-implement/goal-author-clarification.ts +31 -12
- package/src/self-implement/goal-author.ts +77 -5
- package/src/self-implement/graph-stage-units.ts +172 -0
- package/src/self-implement/graph-templates.ts +162 -1
- package/src/self-implement/graph-variant.ts +37 -4
- package/src/self-implement/host-regate.ts +4 -4
- package/src/self-implement/knowhow-pack.ts +38 -0
- package/src/self-implement/orchestrator.ts +235 -21
- package/src/self-implement/run-ledger.ts +64 -6
- package/src/self-implement/run-stop.ts +21 -2
- package/src/self-implement/running-runs.ts +35 -12
- package/src/self-implement/self-implement-cli.ts +36 -4
- package/src/self-implement/stop-autoheal-operational.ts +43 -0
- package/src/self-implement/stop-autoheal.ts +15 -6
- package/src/session/chat.ts +31 -54
- package/src/session/request-size-guard.ts +123 -0
- package/src/sidetab-core/model.ts +136 -0
- package/src/task-agent/parent-host.ts +14 -1
- package/src/task-agent/task-hand.ts +4 -1
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +116 -16
- package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
- package/src/tui/entry.ts +10 -3
- package/src/tui/sidetab/list.ts +45 -0
- package/src/tui/sidetab/nl-tool.ts +2 -136
- package/src/tui/sidetab/peek.ts +52 -0
- package/src/tui-client/dashboard-session.ts +3 -0
- package/src/user-config.ts +11 -5
- package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
- package/src/ux-sim/fault-pod-child-result.ts +42 -0
- package/src/ux-sim/release-sim-rig.ts +262 -0
- package/src/ux-sim/seminar-rehearsal.ts +109 -0
- package/src/ux-sim/subagent-tools-device.ts +2 -2
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
- package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
- package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
- package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
- package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +0 -226
- package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
- package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
- package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
- package/apps/pwa/out/_next/static/chunks/3b355b3d.6f73c98bf6f9c749.js +0 -122
- package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
- package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
- package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
- package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
- package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
- package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
- package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
- /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
|
@@ -9,7 +9,7 @@ import { registerStandaloneLogSink } from '../../src/domains/standalone-log-sink
|
|
|
9
9
|
import { landingFreezeMessage, readLandingFreeze } from '../../src/release-loop/landing-freeze.js';
|
|
10
10
|
import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
|
|
11
11
|
import { getElanousConfigDirOverride } from '../../src/elanous-config-dir.js';
|
|
12
|
-
import { diffFailures, junitFailures, parseFailures, parseTimedOutFailures } from './gate-diff';
|
|
12
|
+
import { collapseGateFailureAttempts, diffFailures, GateFailureAttributionMismatch, junitFailures, parseFailureAttempts, parseFailures, parseTimedOutFailures } from './gate-diff';
|
|
13
13
|
import { loadEnvKnownFailures, splitKnownEnv } from './env-known-failures';
|
|
14
14
|
import { loadGateBatchSafe } from './gate-batch-safe';
|
|
15
15
|
import { observeGatePrewarmCutShadow, type GatePrewarmInput } from './gate-prewarm-plan.js';
|
|
@@ -52,6 +52,8 @@ import { runWithReleaseGateTraffic } from './gate-traffic-mode.js';
|
|
|
52
52
|
import { emitPodLifecycle, gatePodLifecycleEvent, gatePodOutcome } from '../../src/task-orchestrator/surfaces/pod-lifecycle-stages.js';
|
|
53
53
|
import { gateHostReservationRoot, reserveReleaseGateHosts } from '../../src/release-loop/gate-host-reservation.js';
|
|
54
54
|
import { normRoot } from '../../src/instance/resolve.js';
|
|
55
|
+
import { cleanRetryVerdict, junitFailedCaseIds, junitTestcaseCount, junitTestcaseFiles } from './gate-shard-load-flaky.js';
|
|
56
|
+
import { decideAndRecordGateAutoheal, gateAutohealCause, type GateAutohealDecision } from './gate-autoheal.js';
|
|
55
57
|
|
|
56
58
|
export interface WarmShadowObservation {
|
|
57
59
|
files: string[];
|
|
@@ -76,6 +78,10 @@ export function warmCommandMatchesRequest(command: WarmWorkerCommand, request: O
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
interface CommandResult { rc: number; output: string; passedIds?: string[]; stalledEnv?: Array<{ file: string; reason: 'no-output' }>; timedOut?: boolean;
|
|
81
|
+
/** Same-Pod per-file retry passed with complete log/JUnit evidence; these original ids are excluded from introduced. */
|
|
82
|
+
loadFlaky?: string[];
|
|
83
|
+
/** Files already given their one same-Pod retry; prevent the later timeout-only path from retrying them again. */
|
|
84
|
+
loadFlakyAttemptedFiles?: string[];
|
|
79
85
|
/** Identity and complete selected inventory of this Pod sweep; only the producer may issue it. */
|
|
80
86
|
podSweep?: { id: string; shards: number; files: string[] };
|
|
81
87
|
/** Complete, source-bound one-file Job result for shadow comparison; absent means unmeasured. */
|
|
@@ -331,6 +337,9 @@ export interface GateResult {
|
|
|
331
337
|
baselineSource?: 'ledger' | 'instance' | 'cut-logs' | 'swept';
|
|
332
338
|
/** GATE-BASELINE-CACHE — isolated baseline files answered from the ledger (hits) or run now (misses). */
|
|
333
339
|
baselineCache?: { hits: number; misses: number };
|
|
340
|
+
/** A residual summary/name mismatch triggers an explicit baseline rerun before the gate stays fail-closed. */
|
|
341
|
+
attributionRecheck?: { summary: number; observed: number; identified: number; collapsed: number;
|
|
342
|
+
targetFiles: string[]; baselineResult: 'completed' | 'failed' | 'timeout' };
|
|
334
343
|
/** GATE-SPEED A4 — a swept baseline ran only the cut's failing files that exist at the previous release. */
|
|
335
344
|
baselineDeferred?: { cutFiles: number; swept: number };
|
|
336
345
|
durationMs: number;
|
|
@@ -351,14 +360,16 @@ export interface GateResult {
|
|
|
351
360
|
partialFailures?: SweepFailures;
|
|
352
361
|
/** GATE-PARTIAL — this verdict re-ran only these files and carried the prior gate's results for the rest. */
|
|
353
362
|
partial?: { priorCommit: string; files: number };
|
|
354
|
-
/**
|
|
355
|
-
* {@link GATE_TIMEOUT_RECHECK_MS} per-test limit: a warning (flaky under load), not an introduced regression. */
|
|
363
|
+
/** A failure that passed an evidence-checked isolated re-run: warning (flaky under load), not an introduced regression. */
|
|
356
364
|
loadFlaky?: string[];
|
|
357
365
|
/** File-level unhandled errors that reproduced or could not be measured in isolation. They keep the gate red. */
|
|
358
366
|
unmeasuredErrors?: Array<{ file: string; reason: 'reproduced' | 'timeout' | 'unreadable'; ids: string[] }>;
|
|
359
367
|
/** Shard-only unhandled errors whose file-level replay completed cleanly. */
|
|
360
368
|
interferenceErrors?: string[];
|
|
361
369
|
rehearsalTui?: ExecutedTuiCheck;
|
|
370
|
+
/** Recovery recommendation is persisted with the failed graph node so the resume coordinator can act on it. */
|
|
371
|
+
autoheal?: GateAutohealDecision;
|
|
372
|
+
autoheals?: GateAutohealDecision[];
|
|
362
373
|
}
|
|
363
374
|
|
|
364
375
|
const sha = /^[0-9a-f]{7,40}$/i;
|
|
@@ -768,7 +779,8 @@ export function gateShardShell(o: { parts: readonly (readonly string[])[]; cdpPa
|
|
|
768
779
|
// run_part body changes the shell hash once for this feature; keeping the
|
|
769
780
|
// multi-file invocation unchanged avoids another cache-key change.
|
|
770
781
|
const warmFile = part.length === 1 ? `WARM_REFERENCE_FILE=${quote(part[0]!)} ` : '';
|
|
771
|
-
|
|
782
|
+
const manifest = `printf '%s\\n' ${part.map(quote).join(' ')} > "$O/part-${index}.files"; `;
|
|
783
|
+
return `${manifest}${warmFile}run_part ${index} ${[...runner, ...(o.testTimeoutMs !== undefined ? ['--timeout', String(o.testTimeoutMs)] : spawnParts.includes(index) ? ['--timeout=120000'] : []), ...ignores, ...part.map(asPath)].map(quote).join(' ')}`;
|
|
772
784
|
});
|
|
773
785
|
// Only file-isolation batches use this path. A bounded group shares one clone/install, but every test process gets
|
|
774
786
|
// its own HOME, state and tmp directory; part logs/JUnit remain separate and the existing artifact reader judges them.
|
|
@@ -826,6 +838,24 @@ export function gateShardShell(o: { parts: readonly (readonly string[])[]; cdpPa
|
|
|
826
838
|
...(spawnParts.length ? [' local test_start; test_start=$(date +%s)'] : []),
|
|
827
839
|
` { if [ -n "\${WARM_REFERENCE_FILE:-}" ]; then printf "[warm-worker] file=%s\\n" "$WARM_REFERENCE_FILE"; ${o.sourceBinding ? `printf "[warm-worker] cut=%s attempt=%s\\n" ${quote(o.sourceBinding.cutSha)} ${quote(o.sourceBinding.attemptId)}; ` : ''}fi; "\${run_env[@]}" timeout -k 10 "$left" "$@" --reporter=junit --reporter-outfile="$O/part-$i.junit.xml"; } > "$O/part-$i.log" 2>&1`,
|
|
828
840
|
' local prc=$?',
|
|
841
|
+
' if [ -s "$O/part-$i.junit.xml" ]; then',
|
|
842
|
+
' if bun run scripts/release-loop/gate-shard-load-flaky.ts "$O/part-$i.junit.xml" "$O/part-$i.retry-files" "$O/part-$i.files"; then',
|
|
843
|
+
' local retry_index=0 retry_left retry_rc retry_file',
|
|
844
|
+
' while IFS= read -r retry_file; do',
|
|
845
|
+
' [ -n "$retry_file" ] || continue',
|
|
846
|
+
' retry_left=$(( gate_end - $(date +%s) ))',
|
|
847
|
+
' [ "$retry_left" -gt 0 ] || break',
|
|
848
|
+
' [ "$retry_left" -le 120 ] || retry_left=120',
|
|
849
|
+
' stage "part-$i-retry-$retry_index-start"',
|
|
850
|
+
' : > "$O/part-$i.retry-$retry_index.started"',
|
|
851
|
+
' timeout -k 10 "$retry_left" "${run_env[@]}" bun run scripts/test-deterministic.ts "$retry_file" --timeout 120000 --reporter=junit --reporter-outfile="$O/part-$i.retry-$retry_index.junit.xml" > "$O/part-$i.retry-$retry_index.log" 2>&1',
|
|
852
|
+
' retry_rc=$?',
|
|
853
|
+
' echo "$retry_rc" > "$O/part-$i.retry-$retry_index.rc"',
|
|
854
|
+
' stage "part-$i-retry-$retry_index-end"',
|
|
855
|
+
' retry_index=$(( retry_index + 1 ))',
|
|
856
|
+
' done < "$O/part-$i.retry-files"',
|
|
857
|
+
' fi',
|
|
858
|
+
' fi',
|
|
829
859
|
' if [ -n "${WARM_REFERENCE_FILE:-}" ] && [ -f "$O/part-$i.junit.xml" ]; then',
|
|
830
860
|
' local junit_sha; junit_sha=$(sha256sum "$O/part-$i.junit.xml" 2>/dev/null | awk \'{print $1}\')',
|
|
831
861
|
' if [ -z "$junit_sha" ]; then junit_sha=$(shasum -a 256 "$O/part-$i.junit.xml" 2>/dev/null | awk \'{print $1}\'); fi',
|
|
@@ -1136,6 +1166,10 @@ export interface ShardArtifacts {
|
|
|
1136
1166
|
finished: string[];
|
|
1137
1167
|
/** Raw logs of the parts that did not finish (diagnostics · last started file). */
|
|
1138
1168
|
unfinishedLog?: string;
|
|
1169
|
+
/** Original failure ids whose one same-Pod standalone retry completed cleanly. */
|
|
1170
|
+
loadFlaky?: string[];
|
|
1171
|
+
/** Files for which a same-Pod retry completed, even if it remained failing. */
|
|
1172
|
+
loadFlakyAttemptedFiles?: string[];
|
|
1139
1173
|
}
|
|
1140
1174
|
/** Reads a shard Pod's outbox: the part layout ({@link gateShardShell}) or the older single-run one (shard.log · shard.rc · junit.xml). */
|
|
1141
1175
|
export function readShardArtifacts(dir: string, parts: readonly (readonly string[])[]): ShardArtifacts {
|
|
@@ -1150,12 +1184,17 @@ export function readShardArtifacts(dir: string, parts: readonly (readonly string
|
|
|
1150
1184
|
}
|
|
1151
1185
|
const timedOut = read('shard.timeout') !== undefined;
|
|
1152
1186
|
if (installRc !== 0) return { output: install, ...(installRc !== undefined ? { rc: installRc } : {}), timedOut, finished: [] };
|
|
1153
|
-
const good: Array<{ log: string; junit?: string; rc: 0 | 1; files: readonly string[] }> = [];
|
|
1187
|
+
const good: Array<{ log: string; junit?: string; rc: 0 | 1; files: readonly string[]; loadFlaky?: string[]; loadFlakyAttemptedFiles?: string[] }> = [];
|
|
1154
1188
|
const bad: string[] = [];
|
|
1155
1189
|
const exitAnomaly: string[] = [];
|
|
1190
|
+
const attemptedFiles = new Set<string>();
|
|
1156
1191
|
let otherBad = false;
|
|
1157
1192
|
let badRc: number | undefined;
|
|
1158
1193
|
parts.forEach((files, index) => {
|
|
1194
|
+
const retryManifest = (read(`part-${index}.retry-files`) ?? '').split(/\r?\n/).filter(Boolean);
|
|
1195
|
+
retryManifest.forEach((file, retryIndex) => {
|
|
1196
|
+
if (files.includes(file) && read(`part-${index}.retry-${retryIndex}.started`) !== undefined) attemptedFiles.add(file);
|
|
1197
|
+
});
|
|
1159
1198
|
const log = read(`part-${index}.log`);
|
|
1160
1199
|
const rc = rcOf(read(`part-${index}.rc`));
|
|
1161
1200
|
const clean = log?.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
|
|
@@ -1166,9 +1205,32 @@ export function readShardArtifacts(dir: string, parts: readonly (readonly string
|
|
|
1166
1205
|
otherBad = true;
|
|
1167
1206
|
return;
|
|
1168
1207
|
}
|
|
1169
|
-
|
|
1208
|
+
const summary = clean === undefined ? undefined : lastMatch(clean, /Ran (\d+) tests? across (\d+) files?/);
|
|
1209
|
+
const summaryTests = Number(summary?.[1] ?? NaN);
|
|
1210
|
+
const summaryPass = clean === undefined ? NaN : summaryCount(clean, 'pass');
|
|
1211
|
+
const summaryFail = clean === undefined ? NaN : summaryCount(clean, 'fail');
|
|
1212
|
+
const summaryErrors = clean === undefined ? NaN : summaryCount(clean, 'error');
|
|
1213
|
+
const partJunit = read(`part-${index}.junit.xml`) ?? '';
|
|
1214
|
+
const testcaseFiles = junitTestcaseFiles(partJunit);
|
|
1215
|
+
const expectedFiles = [...files].sort();
|
|
1216
|
+
const timedOutComplete = rc === 124 && summary !== undefined && summary !== null && Number(summary[2]) === files.length
|
|
1217
|
+
&& summaryPass + summaryFail + (Number.isNaN(summaryErrors) ? 0 : summaryErrors) === summaryTests
|
|
1218
|
+
&& junitTestcaseCount(partJunit) === summaryTests
|
|
1219
|
+
&& testcaseFiles !== null && testcaseFiles.length === expectedFiles.length && expectedFiles.every((file, fileIndex) => testcaseFiles[fileIndex] === file);
|
|
1220
|
+
if (clean !== undefined && ((rc === 0 || rc === 1) || timedOutComplete) && summary) {
|
|
1170
1221
|
const junit = read(`part-${index}.junit.xml`);
|
|
1171
|
-
|
|
1222
|
+
const retryFiles = retryManifest;
|
|
1223
|
+
const loadFlaky = retryFiles.flatMap((file, retryIndex) => {
|
|
1224
|
+
if (!files.includes(file)) return [];
|
|
1225
|
+
const retryRc = rcOf(read(`part-${index}.retry-${retryIndex}.rc`));
|
|
1226
|
+
const retryLog = read(`part-${index}.retry-${retryIndex}.log`);
|
|
1227
|
+
const retryJunit = read(`part-${index}.retry-${retryIndex}.junit.xml`);
|
|
1228
|
+
const originalFailures = (junitFailedCaseIds(junit ?? '') ?? []).filter((id) => fileOf(id) === file);
|
|
1229
|
+
const verdict = cleanRetryVerdict(retryRc, retryLog, retryJunit, file, originalFailures);
|
|
1230
|
+
if (!verdict.clean) return [];
|
|
1231
|
+
return originalFailures;
|
|
1232
|
+
});
|
|
1233
|
+
good.push({ log: clean, rc: rc === 0 ? 0 : 1, files, ...(junit !== undefined ? { junit } : {}), ...(loadFlaky.length ? { loadFlaky } : {}) });
|
|
1172
1234
|
return;
|
|
1173
1235
|
}
|
|
1174
1236
|
if (log !== undefined) bad.push(`# part ${index} (${rc === undefined ? 'unfinished' : `rc=${rc}`})\n${log}`);
|
|
@@ -1194,6 +1256,9 @@ export function readShardArtifacts(dir: string, parts: readonly (readonly string
|
|
|
1194
1256
|
...(rc !== undefined ? { rc } : {}),
|
|
1195
1257
|
timedOut: !complete && timedOut && badRc === undefined,
|
|
1196
1258
|
finished: good.flatMap((part) => [...part.files]),
|
|
1259
|
+
...([ ...new Set(good.flatMap((part) => part.loadFlaky ?? [])) ].length
|
|
1260
|
+
? { loadFlaky: [...new Set(good.flatMap((part) => part.loadFlaky ?? []))].sort() } : {}),
|
|
1261
|
+
...(attemptedFiles.size ? { loadFlakyAttemptedFiles: [...attemptedFiles].sort() } : {}),
|
|
1197
1262
|
...(bad.length ? { unfinishedLog: bad.join('\n') } : {}),
|
|
1198
1263
|
...(exitAnomaly.length && !otherBad ? { exitCodeOnly: exitAnomaly } : {}),
|
|
1199
1264
|
};
|
|
@@ -1290,7 +1355,6 @@ function failuresOf(run: CommandResult, label: string): SweepFailures {
|
|
|
1290
1355
|
const errorCount = subruns?.error ?? (Number.isNaN(reportedErrors) ? 0 : reportedErrors);
|
|
1291
1356
|
const incomplete = (reason: string) => new Error(`${label} incomplete (rc=${run.rc}; Ran=${ran ? ran[0] : 'missing'}; errors=${subruns || !Number.isNaN(reportedErrors) ? errorCount : 'missing'}; ${reason})\n${tail40(output)}`);
|
|
1292
1357
|
const count = subruns?.fail ?? summaryCount(output, 'fail');
|
|
1293
|
-
const failures = parseFailures(output);
|
|
1294
1358
|
// Bun repeats failed test names under "N tests failed:". A validated Pod sweep joins
|
|
1295
1359
|
// separately checked shards, so a summary in one shard can precede real failures
|
|
1296
1360
|
// from later shards. Remove each repeated block, not everything after the last one.
|
|
@@ -1301,6 +1365,11 @@ function failuresOf(run: CommandResult, label: string): SweepFailures {
|
|
|
1301
1365
|
? output.replace(/^\d+ tests? failed:\r?\n(?:\(fail\)[^\r\n]*(?:\r?\n|$))*(?:[ \t]*\r?\n)*/gm, '')
|
|
1302
1366
|
: failureSummary ? output.slice(0, failureSummary.index) : output;
|
|
1303
1367
|
const occurrences = [...executionOutput.matchAll(/^[ \t]*\(fail\)[ \t]+.+?(?:[ \t]+\[[\d.]+(?:ms|s)\])?[ \t]*\r?$/gm)].length;
|
|
1368
|
+
const collapsed = collapseGateFailureAttempts(parseFailureAttempts(executionOutput));
|
|
1369
|
+
const failures = collapsed.failures;
|
|
1370
|
+
if (collapsed.collapsed > 0) debug.log('release-loop.gate', 'failure-attribution-deduplicated', {
|
|
1371
|
+
label, summary: count, observed: occurrences, identified: collapsed.failures.length, collapsed: collapsed.collapsed,
|
|
1372
|
+
});
|
|
1304
1373
|
// A test that leaves process.exitCode set leaks a non-zero exit into a run whose own summary is complete and clean
|
|
1305
1374
|
// (0.2.7 gate: agent-cli at v0.2.6 · 12 pass · 0 fail · rc 2). The summary is the verdict; read that exit as clean.
|
|
1306
1375
|
const leakedExit = !!ran && run.rc !== 0 && run.rc !== 1 && count === 0 && errorCount === 0 && occurrences === 0
|
|
@@ -1319,7 +1388,11 @@ function failuresOf(run: CommandResult, label: string): SweepFailures {
|
|
|
1319
1388
|
}
|
|
1320
1389
|
}
|
|
1321
1390
|
if (errors.length !== errorCount) throw incomplete(`error attribution identified=${errors.length}`);
|
|
1322
|
-
|
|
1391
|
+
const retryDuplicatesExplainCount = occurrences > count && collapsed.observed === occurrences && failures.length === count;
|
|
1392
|
+
if (Number.isFinite(count) && (failures.length !== count || (occurrences !== count && !retryDuplicatesExplainCount))) {
|
|
1393
|
+
throw new GateFailureAttributionMismatch(label, count, occurrences, failures.length, collapsed.collapsed, failures);
|
|
1394
|
+
}
|
|
1395
|
+
if (!Number.isFinite(count) || (count > 0 && failures.length === 0)
|
|
1323
1396
|
|| (rc === 1 && count === 0 && errorCount === 0) || (rc === 0 && count + errorCount > 0)) {
|
|
1324
1397
|
throw incomplete(`failure attribution incomplete: summary=${count}, identified=${failures.length}`);
|
|
1325
1398
|
}
|
|
@@ -1408,6 +1481,7 @@ class SettledRecheckFailures extends Error {
|
|
|
1408
1481
|
|
|
1409
1482
|
/** Isolated re-runs (host stall re-run · cut and baseline re-checks) are time-limited; sweeps and installs keep their full time. */
|
|
1410
1483
|
export const GATE_ISOLATED_TIMEOUT_MS = 300_000;
|
|
1484
|
+
export const GATE_ATTRIBUTION_RECHECK_FILE_LIMIT = 64;
|
|
1411
1485
|
/** Default final recheck window size; overflow continues in later windows. */
|
|
1412
1486
|
export const GATE_HOST_RECHECK_FILE_LIMIT = 32;
|
|
1413
1487
|
/** Two isolated test processes in each of four Pods = eight at most, with one checkout/install per eight files. */
|
|
@@ -1832,7 +1906,7 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
1832
1906
|
return { ...(podName ? { podName } : {}), ...(termination ? { termination } : {}), ...(logs?.status === 0 ? { logTail: logs.stdout } : {}),
|
|
1833
1907
|
...(errors.length ? { error: `수거 실패 · ${errors.join(' · ')}` } : {}) };
|
|
1834
1908
|
});
|
|
1835
|
-
type ShardRun = { output: string; rc: number; pass: number; fail: number; errors: number; ran: number; files: number; passedIds: string[] };
|
|
1909
|
+
type ShardRun = { output: string; rc: number; pass: number; fail: number; errors: number; ran: number; files: number; passedIds: string[]; loadFlaky?: string[]; loadFlakyAttemptedFiles?: string[] };
|
|
1836
1910
|
type ShardReason = NonNullable<GateResult['stalledShards']>[number]['reason'];
|
|
1837
1911
|
// 깊이 끝 OOM 조각은 «조각 전체»를 파일 하나씩 격리한다 — 상한 40 이면 나머지가 못 잰 채 남았다(09-30 ① 7번 조각 110 파일).
|
|
1838
1912
|
const isolationRemaining = shards.map((item) => item.files.length);
|
|
@@ -2005,6 +2079,8 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2005
2079
|
let batchArtifactsComplete = true;
|
|
2006
2080
|
let junit: string | undefined;
|
|
2007
2081
|
let rc: number | undefined;
|
|
2082
|
+
let shardLoadFlaky: string[] = [];
|
|
2083
|
+
let shardLoadFlakyAttemptedFiles: string[] = [];
|
|
2008
2084
|
let jobExitCode: number | undefined;
|
|
2009
2085
|
let batchArtifactDir: string | undefined;
|
|
2010
2086
|
let lastFile: string | undefined;
|
|
@@ -2135,6 +2211,31 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2135
2211
|
if (job.exitCode !== 0) captureFailure();
|
|
2136
2212
|
batchArtifactDir = job.artifactsDir;
|
|
2137
2213
|
const read = readShardArtifacts(job.artifactsDir, parts);
|
|
2214
|
+
if (logDir) {
|
|
2215
|
+
mkdirSync(logDir, { recursive: true });
|
|
2216
|
+
let retryArtifactIndex = 0;
|
|
2217
|
+
const retryEvidence = parts.flatMap((files, partIndex) => {
|
|
2218
|
+
const path = join(job.artifactsDir, `part-${partIndex}.retry-files`);
|
|
2219
|
+
if (!existsSync(path)) return [];
|
|
2220
|
+
const retryFiles = readFileSync(path, 'utf8').split(/\r?\n/).filter((file) => file && files.includes(file));
|
|
2221
|
+
return retryFiles.map((file, retryIndex) => {
|
|
2222
|
+
const prefix = `part-${partIndex}.retry-${retryIndex}`;
|
|
2223
|
+
const persisted: Record<string, unknown> = { file, started: existsSync(join(job.artifactsDir, `${prefix}.started`)), rc: existsSync(join(job.artifactsDir, `${prefix}.rc`))
|
|
2224
|
+
? readFileSync(join(job.artifactsDir, `${prefix}.rc`), 'utf8').trim() : null };
|
|
2225
|
+
for (const suffix of ['log', 'junit.xml'] as const) {
|
|
2226
|
+
const source = join(job.artifactsDir, `${prefix}.${suffix}`);
|
|
2227
|
+
if (!existsSync(source)) continue;
|
|
2228
|
+
const targetName = `pod-${shard}${branch}.retry-${retryArtifactIndex}.${suffix}`;
|
|
2229
|
+
copyFileSync(source, join(logDir, targetName)); chmodSync(join(logDir, targetName), 0o600);
|
|
2230
|
+
persisted[suffix === 'log' ? 'log' : 'junit'] = targetName;
|
|
2231
|
+
}
|
|
2232
|
+
retryArtifactIndex++;
|
|
2233
|
+
return persisted;
|
|
2234
|
+
});
|
|
2235
|
+
});
|
|
2236
|
+
if (retryEvidence.length) writeFileSync(join(logDir, `pod-${shard}${branch}.retries.json`), JSON.stringify(retryEvidence, null, 2) + '\n', { mode: 0o600 });
|
|
2237
|
+
else rmSync(join(logDir, `pod-${shard}${branch}.retries.json`), { force: true });
|
|
2238
|
+
}
|
|
2138
2239
|
batchArtifactsComplete = !batchIsolation || parts.every((_, index) =>
|
|
2139
2240
|
['rc', 'log', 'junit.xml'].every((suffix) => existsSync(join(job.artifactsDir, `part-${index}.${suffix}`))));
|
|
2140
2241
|
const stagesPath = join(job.artifactsDir, 'stages.tsv');
|
|
@@ -2149,6 +2250,8 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2149
2250
|
}
|
|
2150
2251
|
}
|
|
2151
2252
|
stamp('artifactsRead');
|
|
2253
|
+
shardLoadFlaky = read.loadFlaky ?? [];
|
|
2254
|
+
shardLoadFlakyAttemptedFiles = read.loadFlakyAttemptedFiles ?? [];
|
|
2152
2255
|
({ output, junit, rc, timedOut, finished, unfinishedLog, exitCodeOnly } = read);
|
|
2153
2256
|
// A stall counts only when the Job also left no verdict (a failed stop can let a late shard finish after all).
|
|
2154
2257
|
const stalledAt = watch?.stalled();
|
|
@@ -2201,6 +2304,8 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2201
2304
|
if (unfinishedLog !== undefined) writeFileSync(unfinishedDestination, unfinishedLog, { mode: 0o600 });
|
|
2202
2305
|
else rmSync(unfinishedDestination, { force: true });
|
|
2203
2306
|
writeFileSync(join(logDir, `pod-${shard}${branch}.json`), JSON.stringify({ completed: true, jobName: jobNameForCapture, durationMs, rc: rc ?? null,
|
|
2307
|
+
...(shardLoadFlakyAttemptedFiles.length ? { samePodRetryFiles: shardLoadFlakyAttemptedFiles } : {}),
|
|
2308
|
+
...(shardLoadFlaky.length ? { loadFlaky: shardLoadFlaky } : {}),
|
|
2204
2309
|
...(stall ? { reason: 'stall', finishedFiles: 0, stallSeconds: stall.seconds, sinceCheckoutMs: stall.sinceCheckoutMs } : timedOut ? { reason: 'timeout', finishedFiles: finished.length } : {}), files: paths, plannedSeconds: estimated(paths), deadlineSeconds: shardDeadline, shardCount: shards.length, sweepId, commit, runKey, attemptId, ...(parentAttempt ? { parentAttempt } : {}), jobExitCode: jobExitCode ?? null, jobFailed, ...(placedOn ? { host: placedOn } : {}),
|
|
2205
2310
|
...(Object.keys(phaseTimes).length ? { phaseTimes } : {}), ...(podStages ? { podStages } : {}),
|
|
2206
2311
|
...(podLifecycle && Object.keys(podLifecycle).length ? { podLifecycle } : {}),
|
|
@@ -2448,7 +2553,9 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2448
2553
|
if (reused) debug.log('release-loop.gate', 'pod-shard-resumed', { shard, branch, files: paths.length, rc, durationMs: reused.durationMs ?? null });
|
|
2449
2554
|
return { runs: [{ output: clean!, rc: rc!, pass: passes, fail: fails,
|
|
2450
2555
|
errors: Number.isNaN(errors) ? 0 : errors,
|
|
2451
|
-
ran: Number(ran![1]), files: Number(ran![2]), passedIds: junit ? junitPassedIds(junit) : []
|
|
2556
|
+
ran: Number(ran![1]), files: Number(ran![2]), passedIds: junit ? junitPassedIds(junit) : [],
|
|
2557
|
+
...(shardLoadFlaky.length ? { loadFlaky: shardLoadFlaky } : {}),
|
|
2558
|
+
...(shardLoadFlakyAttemptedFiles.length ? { loadFlakyAttemptedFiles: shardLoadFlakyAttemptedFiles } : {}) }], stalled: [] };
|
|
2452
2559
|
};
|
|
2453
2560
|
const runShard = async (...args: Parameters<typeof runShardImpl>): ReturnType<typeof runShardImpl> => {
|
|
2454
2561
|
const [paths, shard, depth = 0, branch = '', , , parentAttempt, hostRetries = 0] = args;
|
|
@@ -2618,6 +2725,10 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
2618
2725
|
return { rc: total.fail + total.errors ? 1 : 0, output: outputs.join('\n') + `\n${total.pass} pass\n${total.fail} fail\n${total.errors} errors\nRan ${total.ran} tests across ${total.files} files.\n`, validatedShards: true,
|
|
2619
2726
|
podSweep: { id: sweepId, shards: shards.length, files: assignable },
|
|
2620
2727
|
passedIds: [...new Set(measured.flatMap((run) => run.passedIds))].sort(),
|
|
2728
|
+
...(measured.some((run) => run.loadFlaky?.length)
|
|
2729
|
+
? { loadFlaky: [...new Set(measured.flatMap((run) => run.loadFlaky ?? []))].sort() } : {}),
|
|
2730
|
+
...(measured.some((run) => run.loadFlakyAttemptedFiles?.length)
|
|
2731
|
+
? { loadFlakyAttemptedFiles: [...new Set(measured.flatMap((run) => run.loadFlakyAttemptedFiles ?? []))].sort() } : {}),
|
|
2621
2732
|
stalledEnv: stalledShards.flatMap((item) => item.files.map((file) => ({ file, reason: 'no-output' as const }))),
|
|
2622
2733
|
...(abortedShards ? { abortedShards } : {}),
|
|
2623
2734
|
...(riskLane ? { riskLane } : {}) };
|
|
@@ -3248,7 +3359,45 @@ export async function judgeGate(opts: GateOptions, runner: GateRunner = createGa
|
|
|
3248
3359
|
debug.log('release-loop.gate', 'pod-shard-stalled-env', { files: stalled.map(({ file, reason }) => ({ file, reason })), local });
|
|
3249
3360
|
return measured;
|
|
3250
3361
|
};
|
|
3251
|
-
|
|
3362
|
+
let measuredCut: SweepFailures;
|
|
3363
|
+
try {
|
|
3364
|
+
measuredCut = cutRun ? await localStalled(cutRun, cutTree, opts.commit, 'cut') : { failures: [], errors: [] };
|
|
3365
|
+
} catch (error) {
|
|
3366
|
+
if (!(error instanceof GateFailureAttributionMismatch) || error.label !== 'cut sweep') throw error;
|
|
3367
|
+
const targetFiles = [...new Set(error.failures.map(fileOf))].sort();
|
|
3368
|
+
const attribution = { summary: error.summary, observed: error.observed, identified: error.identified,
|
|
3369
|
+
collapsed: error.collapsed, targetFiles,
|
|
3370
|
+
baselineResult: 'failed' as 'completed' | 'failed' | 'timeout' };
|
|
3371
|
+
result.attributionRecheck = attribution;
|
|
3372
|
+
debug.log('release-loop.gate', 'failure-attribution-baseline-recheck', { ...attribution, phase: 'started' });
|
|
3373
|
+
try {
|
|
3374
|
+
if (!targetFiles.length || targetFiles.length > GATE_ATTRIBUTION_RECHECK_FILE_LIMIT)
|
|
3375
|
+
throw new Error(`baseline recheck target count ${targetFiles.length} outside safe bound 1..${GATE_ATTRIBUTION_RECHECK_FILE_LIMIT}`);
|
|
3376
|
+
if (!work) throw new Error('gate workspace missing before baseline attribution recheck');
|
|
3377
|
+
const recheckTree = join(work, 'baseline-attribution-recheck');
|
|
3378
|
+
trees.push(recheckTree);
|
|
3379
|
+
const baseShaForRecheck = opts.baselineCommit ?? baselineReleaseCommit(opts.baselineVersion);
|
|
3380
|
+
await runner.add(recheckTree, baseShaForRecheck);
|
|
3381
|
+
for (const dir of [recheckTree, join(recheckTree, 'apps/pwa')])
|
|
3382
|
+
check(await runner.command('bun', ['install'], dir), `bun install ${dir}`);
|
|
3383
|
+
const rechecked = await runner.sweep(recheckTree,
|
|
3384
|
+
join(root, 'release', opts.version, 'gate-logs', 'baseline-attribution-recheck'),
|
|
3385
|
+
opts.pod ? { ...opts.pod, durationSource } : undefined,
|
|
3386
|
+
targetFiles);
|
|
3387
|
+
if (rechecked.timedOut || rechecked.abortedShards || rechecked.stalledEnv?.length) {
|
|
3388
|
+
attribution.baselineResult = 'timeout';
|
|
3389
|
+
throw new Error('baseline sweep timed out or stalled');
|
|
3390
|
+
}
|
|
3391
|
+
failuresOf(rechecked, 'baseline attribution recheck');
|
|
3392
|
+
attribution.baselineResult = 'completed';
|
|
3393
|
+
} catch (recheckError) {
|
|
3394
|
+
debug.log('release-loop.gate', 'failure-attribution-baseline-recheck', { ...attribution, phase: 'failed', error: String(recheckError) });
|
|
3395
|
+
throw new Error(`baseline recheck ${attribution.baselineResult}; cut attribution unresolved (summary=${attribution.summary}, identified=${attribution.identified})`);
|
|
3396
|
+
}
|
|
3397
|
+
debug.log('release-loop.gate', 'failure-attribution-baseline-recheck', { ...attribution, phase: 'completed',
|
|
3398
|
+
disposition: 'cut names remain unresolved; baseline success cannot identify unnamed cut failures; fail closed' });
|
|
3399
|
+
throw new Error(`baseline recheck completed; cut attribution still unresolved (summary=${attribution.summary}, identified=${attribution.identified})`);
|
|
3400
|
+
}
|
|
3252
3401
|
// A between-tests error proves only that the shared process failed. Re-run each affected file by itself using the
|
|
3253
3402
|
// same isolated path as ordinary new-failure rechecks, even when the error was present in the baseline ledger.
|
|
3254
3403
|
// Replace that file's shard observations with its isolated observations before the existing regression comparison.
|
|
@@ -3289,6 +3438,21 @@ export async function judgeGate(opts: GateOptions, runner: GateRunner = createGa
|
|
|
3289
3438
|
}
|
|
3290
3439
|
}
|
|
3291
3440
|
const cut = partial ? mergePartialFailures(partial, measuredCut) : measuredCut;
|
|
3441
|
+
const samePodFlaky = [...new Set(cutRun?.loadFlaky ?? [])].sort();
|
|
3442
|
+
if (samePodFlaky.length) {
|
|
3443
|
+
const flaky = new Set(samePodFlaky);
|
|
3444
|
+
cut.failures = cut.failures.filter((id) => !flaky.has(id));
|
|
3445
|
+
cut.errors = cut.errors.filter((id) => !flaky.has(id));
|
|
3446
|
+
result.loadFlaky = [...new Set([...(result.loadFlaky ?? []), ...samePodFlaky])].sort();
|
|
3447
|
+
debug.log('release-loop.gate', 'same-pod-load-flaky', { ids: samePodFlaky, files: [...new Set(samePodFlaky.map(fileOf))].sort() });
|
|
3448
|
+
try {
|
|
3449
|
+
const path = loadFlakyCensusPath(ledger);
|
|
3450
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
3451
|
+
const at = new Date().toISOString();
|
|
3452
|
+
appendFileSync(path, samePodFlaky.map((id) => JSON.stringify({ at, version: opts.version, commit: opts.commit, id,
|
|
3453
|
+
host: opts.pod ? `pod:${opts.pod.pool}` : opts.remote ?? 'local', retry: 'same-pod-standalone' }) + '\n').join(''), { mode: 0o600 });
|
|
3454
|
+
} catch (error) { debug.log('release-loop.gate', 'load-flaky-census-write-failed', { ids: samePodFlaky, error: String(error) }); }
|
|
3455
|
+
}
|
|
3292
3456
|
if (partial) result.partial = { priorCommit: partial.priorCommit, files: partial.files.length };
|
|
3293
3457
|
cutFailures = cut;
|
|
3294
3458
|
const baseSha = opts.baselineCommit ?? baselineReleaseCommit(opts.baselineVersion);
|
|
@@ -3432,7 +3596,8 @@ export async function judgeGate(opts: GateOptions, runner: GateRunner = createGa
|
|
|
3432
3596
|
// per-test limit, on the same runner (node-b when the gate is remote). Passing there = flaky under load (warning);
|
|
3433
3597
|
// an assertion failure, a failure again, or a run that cannot be read stays introduced.
|
|
3434
3598
|
const timedOut = cutCheck === undefined ? new Set<string>() : new Set(parseTimedOutFailures(stripPodRepoRoot(cutCheck.output)));
|
|
3435
|
-
const
|
|
3599
|
+
const samePodRetried = new Set(cutRun?.loadFlakyAttemptedFiles ?? []);
|
|
3600
|
+
const shaped = candidates.filter((id) => timedOut.has(id) && isolatedCut.failures.includes(id) && !samePodRetried.has(fileOf(id)));
|
|
3436
3601
|
if (shaped.length) {
|
|
3437
3602
|
const relaxed = opts.pod && runner.recheckPod
|
|
3438
3603
|
? await runner.recheckPod(file, opts.commit, { ...opts.pod, warmCutSha: opts.commit, warmBaselineSha: baseSha,
|
|
@@ -3651,11 +3816,13 @@ export async function judgeGate(opts: GateOptions, runner: GateRunner = createGa
|
|
|
3651
3816
|
...(result.interferenceErrors?.length ? { interferenceErrors: [...result.interferenceErrors].sort() } : {}),
|
|
3652
3817
|
};
|
|
3653
3818
|
const observed = { ...(result.selectionMs !== undefined ? { selectionMs: result.selectionMs } : {}),
|
|
3654
|
-
...(result.warmShadow?.length ? { warmShadow: result.warmShadow } : {})
|
|
3819
|
+
...(result.warmShadow?.length ? { warmShadow: result.warmShadow } : {}),
|
|
3820
|
+
...(result.attributionRecheck ? { attributionRecheck: result.attributionRecheck } : {}) };
|
|
3655
3821
|
// Receipt is advisory for a later radius gate. Missing identity makes reuse invalid, never this gate's verdict.
|
|
3656
3822
|
const baselineReceipt = gateBaselineReceipt({ root, version: opts.version, commit: opts.commit,
|
|
3657
3823
|
graphPins: gateGraphPins(root, opts.graphRunId) ?? (opts.rehearsalBaseline ? gateSourcePins(repo, opts.commit) : null),
|
|
3658
3824
|
envFingerprint: gateEnvFingerprint(process.env),
|
|
3825
|
+
...(result.attributionRecheck ? { attributionRecheck: result.attributionRecheck } : {}),
|
|
3659
3826
|
fullSweep: result.outcome === 'ok' && cutSweepUsable && !result.partial && !!cutFailures
|
|
3660
3827
|
&& !result.rcNonzeroNoFailures.length && !result.stalledShards?.length && !result.stalledEnv.length
|
|
3661
3828
|
&& !result.unmeasuredRecheckFiles?.length && !result.unmeasuredErrors?.length });
|
|
@@ -3736,7 +3903,7 @@ export function graphGateResult(result: GateResult, graph: boolean) {
|
|
|
3736
3903
|
summary: (result.partial ? `부분 재검 ${result.partial.files}파일(앞 게이트 ${result.partial.priorCommit.slice(0, 9)} 결과 이음) · ` : '')
|
|
3737
3904
|
+ (result.outcome === 'ok' ? `새 회귀 ${result.introduced.length} · 기존 ${result.preexisting} · 고침 ${result.fixed ?? '못 셈(기준선 미루기)'}` : `게이트 ${result.outcome}: ${result.error ?? result.introduced.length + ' new regressions'}`) + ` · 환경 알려진 실패 ${result.knownEnv}`
|
|
3738
3905
|
+ (result.rcNonzeroNoFailures.length ? ` · ⚠ 종료코드만 비영 ${result.rcNonzeroNoFailures.length}` : '')
|
|
3739
|
-
+ (result.loadFlaky?.length ? ` · ⚠ 부하 흔들림 ${result.loadFlaky.length}(
|
|
3906
|
+
+ (result.loadFlaky?.length ? ` · ⚠ 부하 흔들림 ${result.loadFlaky.length}(독립 재실행 통과 · 막지 않음)` : '')
|
|
3740
3907
|
+ (result.stalledEnv.length ? ` · 환경 멈춤 ${result.stalledEnv.length} (Pod 밖 통과 ${result.stalledEnv.filter((item) => item.local === 'passed').length})` : '')
|
|
3741
3908
|
+ (result.abortedShards ? ` · 중단 조각 ${result.abortedShards}(중간 매달림 · 시험만 끊고 재확인)` : '') };
|
|
3742
3909
|
}
|
|
@@ -3889,10 +4056,13 @@ export function parseOptions(args: string[], env: NodeJS.ProcessEnv): GateOption
|
|
|
3889
4056
|
/** The node's run: judge, emit the graph result line, and return the process exit code (ok 0 · regression 1 · else 2).
|
|
3890
4057
|
* `runner` is a seam for tests; the process entry passes none. */
|
|
3891
4058
|
export async function runGateNode(argv: string[], env: NodeJS.ProcessEnv, runner?: GateRunner,
|
|
3892
|
-
judge: (opts: GateOptions, runner?: GateRunner) => Promise<GateResult> = judgeGate
|
|
4059
|
+
judge: (opts: GateOptions, runner?: GateRunner, imageProbe?: typeof preflightGateImageDigest) => Promise<GateResult> = judgeGate,
|
|
4060
|
+
imageProbe: typeof preflightGateImageDigest = preflightGateImageDigest): Promise<number> {
|
|
3893
4061
|
const start = Date.now();
|
|
3894
4062
|
let result: GateResult;
|
|
3895
4063
|
let version = '';
|
|
4064
|
+
let graphRunId: string | null = null;
|
|
4065
|
+
let autohealStoreRoot = '';
|
|
3896
4066
|
let placement: { executor: string | null; host: string | null } | undefined;
|
|
3897
4067
|
try {
|
|
3898
4068
|
const parsed = parseOptions(argv, env);
|
|
@@ -3911,8 +4081,10 @@ export async function runGateNode(argv: string[], env: NodeJS.ProcessEnv, runner
|
|
|
3911
4081
|
return 0;
|
|
3912
4082
|
}
|
|
3913
4083
|
version = opts.version;
|
|
4084
|
+
autohealStoreRoot = opts.ledgerRoot ?? releaseLedgerRoot();
|
|
3914
4085
|
// The graph's existing gate-node execution path delegates verdict classification and persistence here.
|
|
3915
4086
|
const context = usesGraphContext(argv, env) ? readGraphContext(env) : undefined;
|
|
4087
|
+
graphRunId = context?.runId ?? null;
|
|
3916
4088
|
// Let the gate's existing SSH host validation report an invalid host before any reservation is published.
|
|
3917
4089
|
const hosts = opts.remote && !/^(?:[\w.-]+@)?[\w.-]+$/.test(opts.remote) ? [] : reservedGateHosts(opts);
|
|
3918
4090
|
const reservationRoot = context ? gateHostReservationRoot() : undefined;
|
|
@@ -3920,12 +4092,28 @@ export async function runGateNode(argv: string[], env: NodeJS.ProcessEnv, runner
|
|
|
3920
4092
|
throw new Error('release gate host reservation requires graph runId and pinned state root');
|
|
3921
4093
|
const releaseHosts = context && hosts.length
|
|
3922
4094
|
? reserveReleaseGateHosts(reservationRoot!, context.runId!, hosts) : () => undefined;
|
|
3923
|
-
try { result = await judge(context?.runId ? { ...opts, graphRunId: context.runId } : opts, runner); }
|
|
4095
|
+
try { result = await judge(context?.runId ? { ...opts, graphRunId: context.runId } : opts, runner, imageProbe); }
|
|
3924
4096
|
finally { releaseHosts(); }
|
|
3925
4097
|
} catch (error) {
|
|
3926
4098
|
result = { outcome: 'error', commit: '', introduced: [], preexisting: 0, fixed: 0, knownEnv: 0, knownEnvCleared: [], stalledEnv: [], rcNonzeroNoFailures: [], durationMs: Date.now() - start, error: String(error) };
|
|
3927
4099
|
placement ??= requestedGateExecutor(argv, env);
|
|
3928
4100
|
}
|
|
4101
|
+
if (versionPattern.test(version) && result.stalledShards?.length) {
|
|
4102
|
+
result.autoheals = result.stalledShards.map((shard, index) => {
|
|
4103
|
+
const shardKey = `pod-${shard.shard}`;
|
|
4104
|
+
const signature = createHash('sha256').update(JSON.stringify({ shard: shard.shard,
|
|
4105
|
+
files: [...shard.files].sort(), reason: shard.reason })).digest('hex');
|
|
4106
|
+
const cause = gateAutohealCause({ outcome: result.outcome, introduced: result.introduced, durationMs: result.durationMs,
|
|
4107
|
+
error: result.error, stalledShards: [shard], interferenceErrors: result.interferenceErrors, loadFlaky: result.loadFlaky }) ?? 'environment';
|
|
4108
|
+
const decision = decideAndRecordGateAutoheal({ cause, signature, version, runId: graphRunId ?? 'direct', shardKey,
|
|
4109
|
+
shardKeys: [shardKey], shardElapsedMs: result.durationMs,
|
|
4110
|
+
overallElapsedMs: index === 0 ? result.durationMs : 0,
|
|
4111
|
+
storeRoot: autohealStoreRoot || releaseLedgerRoot() });
|
|
4112
|
+
debug.log('release-loop.gate-autoheal', 'decision', { runId: graphRunId, version, ...decision });
|
|
4113
|
+
return decision;
|
|
4114
|
+
});
|
|
4115
|
+
result.autoheal = result.autoheals.find((decision) => decision.action === 'hitl') ?? result.autoheals[0];
|
|
4116
|
+
}
|
|
3929
4117
|
if (result.error) console.error(result.error);
|
|
3930
4118
|
debug.log('release-loop.gate', 'result', { version, outcome: result.outcome, ...(placement ?? {}) });
|
|
3931
4119
|
emitNodeResult({ ...graphGateResult(result, !!env.ELANOUS_GRAPH_CONTEXT), ...(placement ?? {}) });
|