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
|
@@ -43,6 +43,11 @@ export interface SupervisorRound {
|
|
|
43
43
|
mainSyncRelaunchFeatures?: string[];
|
|
44
44
|
/** PR 없는 미분류 실패에 대해 실제 분해 실행기로 수복한 원래 골. 새 taskId에도 한 번 상한을 지킨다. */
|
|
45
45
|
selfHealDecomposeFeatures?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* NEEDS-HUMAN-REASON-REPAIR — 사유별 자가 수복 1회의 소진 기억(사유 → 그때 수복한 골 전문).
|
|
48
|
+
* 사유가 다르면 다른 시도다. 옛 원장엔 이 칸이 없다 = 「안 쟀다」이지 「시도했다」가 아니다.
|
|
49
|
+
*/
|
|
50
|
+
selfHealRepairFeatures?: Partial<Record<NeedsHumanRepairReason, string[]>>;
|
|
46
51
|
/**
|
|
47
52
|
* Tasks of this round that ended `status=failed` without a PR. Omitted when there are none — and on older
|
|
48
53
|
* history, which never measured it, so the no-PR streak guard reads it as «not measured» and stays off.
|
|
@@ -137,7 +142,96 @@ export interface SupervisorDecision {
|
|
|
137
142
|
};
|
|
138
143
|
oscillation?: { taskIds: string[]; helper: 'review-oscillation'; signature: string; repairGoals?: Record<string, string>; heldTaskIds?: string[] };
|
|
139
144
|
pendingDecision?: 'attempt-care-escalation';
|
|
140
|
-
selfHeal?: { reason:
|
|
145
|
+
selfHeal?: { reason: SelfHealReason; attempt: 1; taskIds: string[]; repairGoals?: Record<string, string> };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* NEEDS-HUMAN-REASON-REPAIR — needs-human 으로 접히기 «전»에 한 번 수복해 볼 사유.
|
|
150
|
+
* 각 사유의 수복은 다르다: 없는 경로 → 재접지 · 범위 확장 → 좁히기 · 시간 초과 → 좁은 시험 · 조각 없음 → 조각 재걸기.
|
|
151
|
+
*/
|
|
152
|
+
export type NeedsHumanRepairReason = 'missing-path' | 'scope-expansion' | 'step-timeout' | 'no-piece';
|
|
153
|
+
|
|
154
|
+
/** 선행 0.2.38 의 분해 수복 사유까지 포함한 자가 수복 사유 전체. */
|
|
155
|
+
export type SelfHealReason = 'supervisor-unclassified-decompose' | `supervisor-${NeedsHumanRepairReason}`;
|
|
156
|
+
|
|
157
|
+
const NEEDS_HUMAN_REPAIR_REASONS: readonly NeedsHumanRepairReason[] = ['missing-path', 'scope-expansion', 'step-timeout', 'no-piece'];
|
|
158
|
+
|
|
159
|
+
/** 파일 부재의 두 코드 — 없는 경로(ENOENT)와 중간 성분이 파일인 경로(ENOTDIR). */
|
|
160
|
+
const MISSING_PATH_ERROR_CODES: ReadonlySet<string> = new Set(['ENOENT', 'ENOTDIR']);
|
|
161
|
+
|
|
162
|
+
const NEEDS_HUMAN_REPAIR_INSTRUCTION: Record<NeedsHumanRepairReason, string> = {
|
|
163
|
+
'missing-path': '없는 경로를 다시 접지한다 — 저장소에 있는 파일이나 골에 명시된 대상 경로만 고르고, 새 파일은 골이 신설을 요구할 때만 만든다',
|
|
164
|
+
'scope-expansion': '범위 확장을 좁힌다 — 대상 경로 밖으로 나간 변경을 되돌리고 골의 대상·완료 경계 안에서만 구현한다',
|
|
165
|
+
'step-timeout': '단계 예산을 넘겼다 — 좁은 시험 하나로 판정선을 먼저 세우고 나머지 실행은 그 뒤로 미룬다',
|
|
166
|
+
'no-piece': '조각 없이 실패했다 — 같은 골을 다시 걸되 완료 경계를 한 조각 분량으로 잘라 건다',
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
function normalizedRepairPath(path: string): string {
|
|
170
|
+
return path.replace(/^\.\//u, '').replace(/[),.;:]+$/u, '');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** 경로가 범위 집합 안인가 — 정확 일치 · 디렉터리 접두 · (언급이 파일 이름뿐이면) 파일 이름 일치. */
|
|
174
|
+
function pathWithinScope(path: string, scope: readonly string[]): boolean {
|
|
175
|
+
const p = normalizedRepairPath(path);
|
|
176
|
+
return scope.some((raw) => {
|
|
177
|
+
const s = normalizedRepairPath(raw);
|
|
178
|
+
if (s === p) return true;
|
|
179
|
+
if (s.endsWith('/') ? p.startsWith(s) : p.startsWith(`${s}/`)) return true;
|
|
180
|
+
return !p.includes('/') && s.split('/').at(-1) === p;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 범위 확장 — «밖»이라고 잰 변경 전부.
|
|
186
|
+
* ⛔ 대상 경로를 모르면 `changedFiles` 로는 «밖»을 단정하지 않는다(둘 다 쟀을 때만).
|
|
187
|
+
* 다만 실행 범위 가드가 «대상 밖»으로 직접 잰 값(`outsideTargetFiles`)은 그 자체가 측정이다.
|
|
188
|
+
*/
|
|
189
|
+
function expandedBeyondTargetPaths(result: SupervisorJobResult): string[] {
|
|
190
|
+
const measured = result.outsideTargetFiles ?? [];
|
|
191
|
+
const changed = result.changedFiles;
|
|
192
|
+
const targets = result.targetPaths;
|
|
193
|
+
const byScope = changed !== undefined && targets !== undefined && targets.length > 0
|
|
194
|
+
? changed.filter((file) => !pathWithinScope(file, targets))
|
|
195
|
+
: [];
|
|
196
|
+
return [...new Set([...measured, ...byScope])];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* needs-human 앞의 수복 사유 discriminator — 결과에 이미 실리는 판정 재료만 본다:
|
|
201
|
+
* 단계(`timed-out`) · 오류 코드(ENOENT/ENOTDIR) · 변경 파일 vs 골 대상 경로 · 분해 제안 조각 수.
|
|
202
|
+
* PR 이 있는 결과(사람이 볼 PR)와 재시도 재료가 있는 결과는 여기 대상이 아니다(undefined).
|
|
203
|
+
*/
|
|
204
|
+
export function needsHumanRepairReason(result: SupervisorJobResult): NeedsHumanRepairReason | undefined {
|
|
205
|
+
if (result.status !== 'failed' || result.prNumber !== undefined || result.prUrl) return undefined;
|
|
206
|
+
if (result.stage === 'timed-out') return 'step-timeout';
|
|
207
|
+
if (result.error?.code !== undefined && MISSING_PATH_ERROR_CODES.has(result.error.code)) return 'missing-path';
|
|
208
|
+
if (expandedBeyondTargetPaths(result).length > 0) return 'scope-expansion';
|
|
209
|
+
if ((result.decomposeProposal?.pieces.length ?? 0) < 2) return 'no-piece';
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** 사유별 수복 골 원문 — 사유의 수복 지시 + 골의 대상 경로 + 관측된 원인 + 원래 골. */
|
|
214
|
+
export function needsHumanRepairGoal(result: SupervisorJobResult, reason: NeedsHumanRepairReason): string {
|
|
215
|
+
const outside = expandedBeyondTargetPaths(result);
|
|
216
|
+
const repairTargets = result.targetPaths?.length ? result.targetPaths : undefined;
|
|
217
|
+
return [
|
|
218
|
+
`[supervisor-needs-human-repair:${reason}] ${NEEDS_HUMAN_REPAIR_INSTRUCTION[reason]}`,
|
|
219
|
+
...(repairTargets?.length ? [`대상 경로: ${repairTargets.join(', ')}`] : []),
|
|
220
|
+
...(outside.length ? [`대상 경로 밖 변경: ${outside.join(', ')}`] : []),
|
|
221
|
+
...(result.error?.message ? [`이전 실패: ${result.error.message.slice(0, 200)}`] : []),
|
|
222
|
+
result.feature,
|
|
223
|
+
].join('\n');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** 수복 사유가 붙은 자가 수복인가 — 선행 분해 수복('supervisor-unclassified-decompose')과 갈라낸다. */
|
|
227
|
+
function needsHumanRepairDecisionReason(reason: SelfHealReason): NeedsHumanRepairReason | undefined {
|
|
228
|
+
return NEEDS_HUMAN_REPAIR_REASONS.find((candidate) => reason === `supervisor-${candidate}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** 사유별 소진 기억에 이 조각이 이미 있는가 — 새 taskId 여도 골 전문으로 짝을 맞춘다. */
|
|
232
|
+
function needsHumanRepairSpent(history: readonly SupervisorRound[], reason: NeedsHumanRepairReason, feature: string): boolean {
|
|
233
|
+
const key = resumeKey(feature);
|
|
234
|
+
return history.some((entry) => (entry.selfHealRepairFeatures?.[reason] ?? []).some((spent) => resumeKey(spent) === key));
|
|
141
235
|
}
|
|
142
236
|
|
|
143
237
|
export interface SupervisorLimits {
|
|
@@ -245,6 +339,11 @@ export type SupervisorJobResult = SelfDevJobResult & {
|
|
|
245
339
|
reviewReason?: string;
|
|
246
340
|
salvage?: 'launched' | 'parked';
|
|
247
341
|
next?: SupervisorNext;
|
|
342
|
+
/**
|
|
343
|
+
* NEEDS-HUMAN-REASON-REPAIR — 실행 범위 가드가 «대상 경로 밖»으로 직접 잰 변경.
|
|
344
|
+
* 골이 대상 경로를 안 선언했어도 이 값은 측정이다 — `changedFiles` 와 달리 «밖»을 단정할 수 있다.
|
|
345
|
+
*/
|
|
346
|
+
outsideTargetFiles?: readonly string[];
|
|
248
347
|
};
|
|
249
348
|
|
|
250
349
|
export function aggregateReviewTrend(results: readonly SelfDevJobResult[]): ReviewRework['trend'] | undefined {
|
|
@@ -360,6 +459,8 @@ export function decideNextRun(input: {
|
|
|
360
459
|
reviewMustFixTrend?: ReviewRework['trend'];
|
|
361
460
|
/** True: the rerun consumes the authored goal. False: it cannot, so oscillation stops for a human. Undefined: pure decision. */
|
|
362
461
|
repairGoalExecution?: boolean;
|
|
462
|
+
/** Separate opt-in for needs-human reason repairs; omitted keeps the new repair execution disabled. */
|
|
463
|
+
needsHumanReasonRepairExecution?: boolean;
|
|
363
464
|
/** 분해 제안을 실제 조각 실행으로 승격할 수 있는 supervisor 경로에만 true. */
|
|
364
465
|
decompositionExecution?: boolean;
|
|
365
466
|
}): SupervisorDecision {
|
|
@@ -550,7 +651,52 @@ export function decideNextRun(input: {
|
|
|
550
651
|
why: `supervisor-unclassified-decompose (attempt: 1/1) — PR 없는 미분류 조각 ${taskIds.length}개를 실증된 분해 제안으로 한 번 재걸기`,
|
|
551
652
|
};
|
|
552
653
|
}
|
|
654
|
+
// NEEDS-HUMAN-REASON-REPAIR — 사람에게 접기 «전»에 사유별로 한 번 수복한다. 수복 골은 rerun 이 그대로 실행한다.
|
|
655
|
+
// ⛔ 실행기가 선언되지 않았으면(repairGoalExecution !== true) 수복 대신 지금처럼 사람에게 간다.
|
|
656
|
+
if (input.repairGoalExecution === true && input.needsHumanReasonRepairExecution === true && round + 1 <= maxRounds) {
|
|
657
|
+
const repairable = activeResults.flatMap((result) => {
|
|
658
|
+
if (!t.needsHuman.includes(result.taskId)) return [];
|
|
659
|
+
if (!t.classifications.some((classification) => classification.taskId === result.taskId && classification.kind === 'unclassified')) return [];
|
|
660
|
+
const reason = needsHumanRepairReason(result);
|
|
661
|
+
if (reason === undefined || (result.targetPaths?.length ?? 0) === 0) return [];
|
|
662
|
+
return needsHumanRepairSpent(history, reason, result.feature) ? [] : [{ result, reason }];
|
|
663
|
+
});
|
|
664
|
+
const first = repairable[0];
|
|
665
|
+
const single = first !== undefined && repairable.length === 1 && t.needsHuman.every((id) => id === first.result.taskId)
|
|
666
|
+
? first : undefined;
|
|
667
|
+
if (single) {
|
|
668
|
+
const taskIds = [single.result.taskId];
|
|
669
|
+
return {
|
|
670
|
+
...base,
|
|
671
|
+
action: 'relaunch',
|
|
672
|
+
needsHuman: t.needsHuman.filter((id) => !taskIds.includes(id)),
|
|
673
|
+
selfHeal: {
|
|
674
|
+
reason: `supervisor-${single.reason}`,
|
|
675
|
+
attempt: 1,
|
|
676
|
+
taskIds,
|
|
677
|
+
repairGoals: { [single.result.taskId]: needsHumanRepairGoal(single.result, single.reason) },
|
|
678
|
+
},
|
|
679
|
+
why: `supervisor-${single.reason} (attempt: 1/1) — ${NEEDS_HUMAN_REPAIR_INSTRUCTION[single.reason]}`,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
}
|
|
553
683
|
if (t.needsHuman.length > 0) {
|
|
684
|
+
// 이미 한 번 수복했는데 같은 사유로 다시 섰다 — 사유·시도를 원문으로 남기고 사람에게 넘긴다.
|
|
685
|
+
const exhausted = activeResults.flatMap((result) => {
|
|
686
|
+
if (!t.needsHuman.includes(result.taskId)) return [];
|
|
687
|
+
const reason = needsHumanRepairReason(result);
|
|
688
|
+
if (reason === undefined || !needsHumanRepairSpent(history, reason, result.feature)) return [];
|
|
689
|
+
return [{ result, reason }];
|
|
690
|
+
});
|
|
691
|
+
if (exhausted.length > 0) {
|
|
692
|
+
return {
|
|
693
|
+
...base,
|
|
694
|
+
action: 'stop',
|
|
695
|
+
stopReason: 'needs-human',
|
|
696
|
+
why: withGoalPlanRevisionObservation(`${exhausted.map(({ result, reason }) =>
|
|
697
|
+
`supervisor-${reason} (attempt: 1/1) — ${NEEDS_HUMAN_REPAIR_INSTRUCTION[reason]} 을 한 번 시도했으나 같은 조각이 다시 실패했다(${result.taskId})`).join(' · ')} · 사람이 볼 것 ${t.needsHuman.length}`),
|
|
698
|
+
};
|
|
699
|
+
}
|
|
554
700
|
return {
|
|
555
701
|
...base,
|
|
556
702
|
action: 'stop',
|
|
@@ -802,6 +948,9 @@ export function appendRound(
|
|
|
802
948
|
if (result.durationMs === undefined) { unknownTimeTaskIds.add(result.taskId); continue; }
|
|
803
949
|
lostTimeMsByTask[result.taskId] = (lostTimeMsByTask[result.taskId] ?? 0) + result.durationMs;
|
|
804
950
|
}
|
|
951
|
+
const selfHealRepairReason = decision?.action !== 'stop' && decision?.selfHeal
|
|
952
|
+
? needsHumanRepairDecisionReason(decision.selfHeal.reason)
|
|
953
|
+
: undefined;
|
|
805
954
|
return [...history, {
|
|
806
955
|
round: history.length,
|
|
807
956
|
landed: countLanded(results),
|
|
@@ -826,6 +975,15 @@ export function appendRound(
|
|
|
826
975
|
return feature === undefined ? [] : [feature];
|
|
827
976
|
}),
|
|
828
977
|
} : {}),
|
|
978
|
+
// NEEDS-HUMAN-REASON-REPAIR — 사유별 수복 1회 소진을 회차 원장에 남긴다(사유가 다르면 다른 시도).
|
|
979
|
+
...(selfHealRepairReason !== undefined && decision?.selfHeal ? {
|
|
980
|
+
selfHealRepairFeatures: {
|
|
981
|
+
[selfHealRepairReason]: decision.selfHeal.taskIds.flatMap((id) => {
|
|
982
|
+
const feature = results.find((result) => result.taskId === id)?.feature;
|
|
983
|
+
return feature === undefined ? [] : [feature];
|
|
984
|
+
}),
|
|
985
|
+
},
|
|
986
|
+
} : {}),
|
|
829
987
|
...(decision?.action === 'add-repair-task' && decision.oscillation ? (() => {
|
|
830
988
|
// Each repaired task is recorded under its original goal feature and, when a rerun runs the authored goal as
|
|
831
989
|
// the piece's new feature (orchestrate), under that repair text too — so the repair's own oscillation stops.
|
|
@@ -1048,6 +1206,7 @@ export interface SuperviseRunOptions {
|
|
|
1048
1206
|
sweepPendingMerges?: typeof sweepFrozenMerges;
|
|
1049
1207
|
/** True only when rerun consumes `invocation.repairGoals`; omitted or false → a review oscillation stops for a human. */
|
|
1050
1208
|
repairGoalExecution?: boolean;
|
|
1209
|
+
needsHumanReasonRepairExecution?: boolean;
|
|
1051
1210
|
/**
|
|
1052
1211
|
* TASK-AGENT-SHADOW — 멈춤이 확정되면 판단부를 그림자로 부른다(기본 `recordTaskAgentShadowMove`).
|
|
1053
1212
|
* `false` 면 끈다. 던져도 런의 결말은 바뀌지 않는다(fail-soft).
|
|
@@ -1097,6 +1256,7 @@ export async function rejudgeTerminalTaskCard(runId: string | null, deps: {
|
|
|
1097
1256
|
export async function superviseRun(opts: SuperviseRunOptions): Promise<SupervisorJobResult[]> {
|
|
1098
1257
|
let results = [...opts.initial];
|
|
1099
1258
|
let history: SupervisorRound[] = [];
|
|
1259
|
+
const maxRounds = opts.limits?.maxRounds ?? DEFAULT_MAX_ROUNDS;
|
|
1100
1260
|
|
|
1101
1261
|
for (;;) {
|
|
1102
1262
|
try {
|
|
@@ -1144,6 +1304,7 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
|
|
|
1144
1304
|
decompositionExecution: opts.promoteDecomposition !== undefined,
|
|
1145
1305
|
// Undeclared = cannot run the repair goal: an add-repair-task would otherwise be a same-strategy relaunch.
|
|
1146
1306
|
repairGoalExecution: opts.repairGoalExecution === true,
|
|
1307
|
+
...(opts.needsHumanReasonRepairExecution === undefined ? {} : { needsHumanReasonRepairExecution: opts.needsHumanReasonRepairExecution }),
|
|
1147
1308
|
...(aggregateReviewTrend(results) ? { reviewMustFixTrend: aggregateReviewTrend(results) } : {}),
|
|
1148
1309
|
...(opts.limits ? { limits: opts.limits } : {}),
|
|
1149
1310
|
...(observed.deployFindings ? { deployFindings: observed.deployFindings } : {}),
|
|
@@ -1154,6 +1315,21 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
|
|
|
1154
1315
|
} : {}),
|
|
1155
1316
|
});
|
|
1156
1317
|
|
|
1318
|
+
const reasonRepairSkipped = decision.action !== 'stop' || decision.stopReason !== 'needs-human' || history.length + 1 > maxRounds
|
|
1319
|
+
? [] : results.flatMap((result) => {
|
|
1320
|
+
if (!decision.needsHuman.includes(result.taskId) || needsHumanRepairReason(result) === undefined) return [];
|
|
1321
|
+
if (!decision.classifications.some((classification) => classification.taskId === result.taskId && classification.kind === 'unclassified')) return [];
|
|
1322
|
+
const repairReason = needsHumanRepairReason(result)!;
|
|
1323
|
+
if (needsHumanRepairSpent(history, repairReason, result.feature)) return [];
|
|
1324
|
+
const reason = opts.repairGoalExecution !== true || opts.needsHumanReasonRepairExecution !== true
|
|
1325
|
+
? 'disabled' : 'no-target-paths';
|
|
1326
|
+
if (reason === 'no-target-paths' && (result.targetPaths?.length ?? 0) > 0) return [];
|
|
1327
|
+
return [{ taskId: result.taskId, reason }];
|
|
1328
|
+
});
|
|
1329
|
+
for (const skipped of reasonRepairSkipped) {
|
|
1330
|
+
try { opts.observe?.('supervisor.reason-repair-skipped', skipped); } catch { /* fail-soft */ }
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1157
1333
|
// The supervisor consumes knowhow when it judges a failed piece. Keep the child prompt untouched.
|
|
1158
1334
|
const failedPiece = results.find((result) => result.status === 'failed' && result.feature.trim());
|
|
1159
1335
|
if (failedPiece) {
|
|
@@ -1188,7 +1364,13 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
|
|
|
1188
1364
|
decomposePromotion = { attempted: true, reason: `shim-failed: ${String(error)}` };
|
|
1189
1365
|
}
|
|
1190
1366
|
}
|
|
1191
|
-
if (decision.selfHeal) {
|
|
1367
|
+
if (decision.selfHeal && needsHumanRepairDecisionReason(decision.selfHeal.reason) !== undefined) {
|
|
1368
|
+
// NEEDS-HUMAN-REASON-REPAIR — 수복 시도는 rerun 이 사유별 수복 골로 실행한다(아래 repairGoals).
|
|
1369
|
+
// 여기서는 «한 번 시도했다»를 관측하고 relaunch 를 유지한다 — 실패는 다음 라운드 판정이 사유·시도 원문으로 접는다.
|
|
1370
|
+
try { opts.observe?.('supervisor-self-heal', { runId, reason: decision.selfHeal.reason,
|
|
1371
|
+
attempt: decision.selfHeal.attempt, taskIds: decision.selfHeal.taskIds,
|
|
1372
|
+
outcome: 'relaunching', repairGoalTasks: Object.keys(decision.selfHeal.repairGoals ?? {}) }); } catch { /* fail-open */ }
|
|
1373
|
+
} else if (decision.selfHeal) {
|
|
1192
1374
|
const promoted = decomposePromotion.attempted && (decomposePromotion.pieceCount ?? 0) >= 2;
|
|
1193
1375
|
try { opts.observe?.('supervisor-self-heal', { runId, reason: decision.selfHeal.reason,
|
|
1194
1376
|
attempt: decision.selfHeal.attempt, taskIds: decision.selfHeal.taskIds,
|
|
@@ -1309,7 +1491,7 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
|
|
|
1309
1491
|
// but their results stay in the round so the human hand-off (and the final review-oscillating stop) keeps them.
|
|
1310
1492
|
const held = decision.oscillation?.heldTaskIds ?? [];
|
|
1311
1493
|
const heldResults = results.filter((result) => held.includes(result.taskId));
|
|
1312
|
-
const repairGoals = { ...decision.relaunchGoals, ...decision.oscillation?.repairGoals };
|
|
1494
|
+
const repairGoals = { ...decision.relaunchGoals, ...decision.selfHeal?.repairGoals, ...decision.oscillation?.repairGoals };
|
|
1313
1495
|
const rerunResults = await opts.rerun(held.length ? results.filter((result) => !held.includes(result.taskId)) : results,
|
|
1314
1496
|
{ relaunch: true, ...(Object.keys(repairGoals).length > 0 ? { repairGoals } : {}) });
|
|
1315
1497
|
results = [...rerunResults, ...heldResults.filter((heldResult) => !rerunResults.some((result) => result.taskId === heldResult.taskId))];
|
|
@@ -114,6 +114,9 @@ export interface SelfDevJobResult {
|
|
|
114
114
|
completionDisposition?: string;
|
|
115
115
|
/** Abandoned-run classification from the child. Independent of completionDisposition. */
|
|
116
116
|
failureClassification?: AbandonedClassification;
|
|
117
|
+
/** Basis and explicit terminal reason are kept separate from the classification label. */
|
|
118
|
+
classificationBasis?: string;
|
|
119
|
+
terminationReason?: string;
|
|
117
120
|
/** Provider failure evidence from the child result; absent when unobserved. */
|
|
118
121
|
providerErrors?: { count: number; provider: string; category: 'quota' | 'credential' | 'request' | 'other' };
|
|
119
122
|
/** Stable child run identity used to join its run-ledger proposal. */
|
|
@@ -78,6 +78,8 @@ export interface GateArtifactSummary extends GateArtifactCounts {
|
|
|
78
78
|
head40: string | null;
|
|
79
79
|
base40: string | null;
|
|
80
80
|
envKey: string;
|
|
81
|
+
/** Seat self-gate marker observed at process entry (true only for ELANOUS_TRAIN_GATE=1). */
|
|
82
|
+
trainGate?: boolean;
|
|
81
83
|
shards: number;
|
|
82
84
|
cohort: string[];
|
|
83
85
|
shardsDetail: GateArtifactShard[];
|
|
@@ -128,6 +130,7 @@ export interface GateArtifactInput {
|
|
|
128
130
|
head40: string | null;
|
|
129
131
|
base40: string | null;
|
|
130
132
|
envKey: string;
|
|
133
|
+
trainGate?: boolean;
|
|
131
134
|
testFiles: readonly string[];
|
|
132
135
|
verdict: string | null;
|
|
133
136
|
verdictLine?: string;
|
|
@@ -218,6 +221,7 @@ export function writeGateArtifacts(input: GateArtifactInput): { summaryPath: str
|
|
|
218
221
|
head40: input.head40,
|
|
219
222
|
base40: input.base40,
|
|
220
223
|
envKey: input.envKey,
|
|
224
|
+
...(input.trainGate !== undefined ? { trainGate: input.trainGate } : {}),
|
|
221
225
|
shards: input.sharded ? input.sharded.shards.length : 0,
|
|
222
226
|
cohort: sorted(input.testFiles),
|
|
223
227
|
shardsDetail,
|
|
@@ -251,12 +255,14 @@ export function writeRemoteUnavailableGateArtifacts(
|
|
|
251
255
|
reason: 'remote-unsupported' | 'remote-fetch-failed',
|
|
252
256
|
resolveRev: RevResolver = defaultRevResolver(cwd),
|
|
253
257
|
envKey: () => string = defaultGateEnvKey,
|
|
258
|
+
trainGate?: boolean,
|
|
254
259
|
): { summaryPath: string; junitFiles: string[] } {
|
|
255
260
|
return writeGateArtifacts({
|
|
256
261
|
dir: resolveArtifactDir(dir, cwd),
|
|
257
262
|
head40: resolveRev('HEAD'),
|
|
258
263
|
base40: baseRef ? resolveRev(baseRef) : null,
|
|
259
264
|
envKey: envKey(),
|
|
265
|
+
trainGate,
|
|
260
266
|
testFiles: [],
|
|
261
267
|
verdict: null,
|
|
262
268
|
exitCode,
|
|
@@ -266,6 +272,13 @@ export function writeRemoteUnavailableGateArtifacts(
|
|
|
266
272
|
});
|
|
267
273
|
}
|
|
268
274
|
|
|
275
|
+
/** The local train wrapper owns the receipt marker, including when artifacts came from a remote host. */
|
|
276
|
+
export function recordGateTrainMarker(summaryPath: string, trainGate: boolean): void {
|
|
277
|
+
const summary = JSON.parse(readFileSync(summaryPath, 'utf8')) as Record<string, unknown>;
|
|
278
|
+
summary.trainGate = trainGate;
|
|
279
|
+
writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
|
|
280
|
+
}
|
|
281
|
+
|
|
269
282
|
// ── 원격 산출 회수 (SIDE-VERIFY-GATE-SHARDS ②) ──────────────────────────────
|
|
270
283
|
// 원격 run 은 `$W` 임시 트리에서 돌고 끝나면 trap 이 `$W` 를 지운다(gate-remote.ts remoteScript). 그래서 원격 쪽
|
|
271
284
|
// `--artifact-dir` 는 `$W` «밖»의 호스트 디스크 경로(/var/tmp/elanous-gate-artifacts-<nonce>)로 준다 — run 이 끝나도 남고, 회수
|
|
@@ -4,7 +4,6 @@ import { tmpdir } from 'node:os';
|
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import { basename, join, resolve } from 'node:path/posix';
|
|
6
6
|
import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
|
|
7
|
-
import { audit as auditEntryBudget, entryBudgetAffected } from '../../scripts/ratchets/next-tui-entry-budget.js';
|
|
8
7
|
import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
|
|
9
8
|
import { runIsolationHardcodeGate } from '../../scripts/ci-isolation-hardcode-gate.js';
|
|
10
9
|
import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
|
|
@@ -58,6 +57,49 @@ export interface SelfGateCliOptions {
|
|
|
58
57
|
scenarioFile?: string;
|
|
59
58
|
/** SIDE-VERIFY — 조각별 지금/기준 JUnit ⊕ summary.json 을 이 디렉토리에 «쓰기만» 한다(판정·exit·기존 줄 불변). */
|
|
60
59
|
artifactDir?: string;
|
|
60
|
+
/** Marker captured by the process entry point; keeps receipts stable if the environment changes during dispatch. */
|
|
61
|
+
trainGate?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const SELF_GATE_SEAT_TRACKS = new Set(['OP', 'OPC', 'OPT', 'TC', 'UX', 'MK']);
|
|
65
|
+
|
|
66
|
+
interface SelfGateTrainMarker {
|
|
67
|
+
track: string | null;
|
|
68
|
+
received: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Capture and log the marker exactly as the self-gate process received it. */
|
|
72
|
+
export function observeSelfGateTrainMarker(): SelfGateTrainMarker {
|
|
73
|
+
const track = process.env.ELANOUS_TRACK?.trim() || null;
|
|
74
|
+
const received = process.env.ELANOUS_TRAIN_GATE === '1';
|
|
75
|
+
try { debug.log('self-gate', 'train-gate-marker', { track, received }); } catch { /* evidence logging must not change gate behavior */ }
|
|
76
|
+
return { track, received };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Seat invocations may only measure the pinned tree after the landing train has admitted the gate. */
|
|
80
|
+
export function refuseSeatSelfGateWithoutTrainMarker(marker = observeSelfGateTrainMarker()): { track: string; message: string } | undefined {
|
|
81
|
+
const { track, received } = marker;
|
|
82
|
+
if (!track || !SELF_GATE_SEAT_TRACKS.has(track) || received) return undefined;
|
|
83
|
+
try { debug.log('self-gate', 'seat-refused', { track, requiredMarker: 'ELANOUS_TRAIN_GATE=1' }); } catch { /* refusal must survive an unavailable observer */ }
|
|
84
|
+
return { track, message: 'gate 는 열차가 착지 때 1회 — land-enqueue.sh 로 줄에 올려라' };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A refused admission still writes the observed marker when an artifact directory was requested. */
|
|
88
|
+
export function writeSeatSelfGateRefusalArtifact(cwd: string, artifactDir: string, marker: SelfGateTrainMarker): string | undefined {
|
|
89
|
+
if (!artifactDir.trim()) return undefined;
|
|
90
|
+
const dir = resolveArtifactDir(artifactDir, cwd);
|
|
91
|
+
const written = writeGateArtifacts({
|
|
92
|
+
dir,
|
|
93
|
+
head40: defaultRevResolver(cwd)('HEAD'),
|
|
94
|
+
base40: null,
|
|
95
|
+
envKey: defaultGateEnvKey(),
|
|
96
|
+
trainGate: marker.received,
|
|
97
|
+
testFiles: [],
|
|
98
|
+
verdict: 'seat-refused',
|
|
99
|
+
verdictLine: `seat gate refused before dispatch (track=${marker.track ?? 'none'}; trainGate=${marker.received})`,
|
|
100
|
+
exitCode: 2,
|
|
101
|
+
});
|
|
102
|
+
return written.summaryPath;
|
|
61
103
|
}
|
|
62
104
|
|
|
63
105
|
interface ProcessResult {
|
|
@@ -125,7 +167,6 @@ interface SelfGateCliDeps {
|
|
|
125
167
|
/** iOS 순수-로직 시험 게이트 심(시험 주입용). */
|
|
126
168
|
runIosGate?: (out: GateOutput) => number;
|
|
127
169
|
runPwaGate?: (out: GateOutput) => number;
|
|
128
|
-
runEntryBudgetGate?: (cwd: string, changedFiles: readonly string[]) => { affected: boolean; errors: string[] };
|
|
129
170
|
listPrWorktrees?: (cwd: string) => PrWorktreeListEntry[] | { lookupFailed: string };
|
|
130
171
|
inspectWorktreeDirtiness?: (path: string) => { dirty: boolean } | { lookupFailed: string };
|
|
131
172
|
/** `--artifact-dir` 전용 심 — 커밋 sha 해석(실패 = null) · 환경 키. */
|
|
@@ -809,23 +850,25 @@ export function selectGateTestFiles(cwd: string, options: GateSelectionOptions =
|
|
|
809
850
|
|
|
810
851
|
export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): SelfGateCliResult {
|
|
811
852
|
const capture: GateArtifactCapture = {};
|
|
853
|
+
const trainGate = options.trainGate ?? process.env.ELANOUS_TRAIN_GATE === '1';
|
|
812
854
|
const result = runSelfGateCliCore(cwd, options, deps, capture, false) as SelfGateCliResult;
|
|
813
855
|
persistGateReceipt(cwd, capture, deps);
|
|
814
|
-
if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
|
|
856
|
+
if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps, trainGate);
|
|
815
857
|
return result;
|
|
816
858
|
}
|
|
817
859
|
|
|
818
860
|
/** Production path: shard bundles use async Bun children; all non-shard policy and timeout logic is shared. */
|
|
819
861
|
export async function runSelfGateCliAsync(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): Promise<SelfGateCliResult> {
|
|
820
862
|
const capture: GateArtifactCapture = {};
|
|
863
|
+
const trainGate = options.trainGate ?? process.env.ELANOUS_TRAIN_GATE === '1';
|
|
821
864
|
const result = await runSelfGateCliCore(cwd, options, deps, capture, true);
|
|
822
865
|
persistGateReceipt(cwd, capture, deps);
|
|
823
|
-
if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
|
|
866
|
+
if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps, trainGate);
|
|
824
867
|
return result;
|
|
825
868
|
}
|
|
826
869
|
|
|
827
870
|
/** 쓰기 실패는 «경고 한 줄»로만 접는다 — 판정·exit 코드는 그대로다. */
|
|
828
|
-
function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCliResult, capture: GateArtifactCapture, deps: SelfGateCliDeps): void {
|
|
871
|
+
function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCliResult, capture: GateArtifactCapture, deps: SelfGateCliDeps, trainGate: boolean): void {
|
|
829
872
|
if (!artifactDir.trim()) {
|
|
830
873
|
result.lines.push('⚠ artifacts: --artifact-dir 가 빈 경로라 안 썼다 (판정은 그대로다)');
|
|
831
874
|
return;
|
|
@@ -839,6 +882,7 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
|
|
|
839
882
|
head40: resolveRev('HEAD'),
|
|
840
883
|
base40: capture.baseRef ? resolveRev(capture.baseRef) : null,
|
|
841
884
|
envKey: (deps.envKey ?? defaultGateEnvKey)(),
|
|
885
|
+
trainGate,
|
|
842
886
|
testFiles: capture.testFiles ?? result.testFiles,
|
|
843
887
|
verdict: capture.verdict ?? null,
|
|
844
888
|
...(capture.verdictLine !== undefined ? { verdictLine: capture.verdictLine } : {}),
|
|
@@ -1210,20 +1254,6 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1210
1254
|
// 🍎 iOS 축 — 안드로이드와 «같은 자리»에 둔다(skipTestStep 앞). Swift 만 바뀐 PR 도 여기서 조기 리턴한다.
|
|
1211
1255
|
const iosPassed = runAdditionalGate('ios-gate', deps.runIosGate ?? runIosUnitTestGate, selection.files, cwd, lines);
|
|
1212
1256
|
const pwaPassed = runAdditionalGate('pwa-gate', deps.runPwaGate ?? runPwaBuildGate, selection.files, cwd, lines);
|
|
1213
|
-
let entryBudgetPassed = false;
|
|
1214
|
-
try {
|
|
1215
|
-
const budget = (deps.runEntryBudgetGate ?? ((dir, files) => {
|
|
1216
|
-
const affected = entryBudgetAffected(files);
|
|
1217
|
-
return { affected, errors: affected ? auditEntryBudget(dir).errors : [] };
|
|
1218
|
-
}))(cwd, selection.files);
|
|
1219
|
-
entryBudgetPassed = budget.errors.length === 0;
|
|
1220
|
-
lines.push(budget.affected
|
|
1221
|
-
? `next-tui-entry-budget: ${entryBudgetPassed ? 'pass' : `FAIL ${budget.errors.join('; ')}`}`
|
|
1222
|
-
: 'next-tui-entry-budget: skip (unrelated changes)');
|
|
1223
|
-
} catch (error) {
|
|
1224
|
-
lines.push(`next-tui-entry-budget: UNMEASURED ${error instanceof Error ? error.message : String(error)}`);
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
1257
|
if (receiptDecision?.mode === 'inherit' && testFiles.length === 0 && fullTestFiles.length > 0) {
|
|
1228
1258
|
capture.testReceiptMeasured = true;
|
|
1229
1259
|
capture.failedTestFiles = [];
|
|
@@ -1235,7 +1265,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1235
1265
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
1236
1266
|
logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
|
|
1237
1267
|
return {
|
|
1238
|
-
exitCode: policyPassed && androidPassed && iosPassed && pwaPassed &&
|
|
1268
|
+
exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && expose.passed ? 0 : 1,
|
|
1239
1269
|
lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
|
|
1240
1270
|
documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
|
|
1241
1271
|
alwaysIncludeMissing, importerTestsAdded,
|
|
@@ -1249,7 +1279,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1249
1279
|
capture.failedTestFiles = [];
|
|
1250
1280
|
logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
|
|
1251
1281
|
Object.assign(capture, { verdict: 'skipped', artifactsUnavailable: 'no-tests' } satisfies GateArtifactCapture);
|
|
1252
|
-
return { exitCode: androidPassed && iosPassed && pwaPassed &&
|
|
1282
|
+
return { exitCode: androidPassed && iosPassed && pwaPassed && policyPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
|
|
1253
1283
|
}
|
|
1254
1284
|
|
|
1255
1285
|
// The default direct Bun path has one process and one 300s limit. Route real child/PTY tests through
|
|
@@ -1339,7 +1369,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1339
1369
|
capture.verdictLine = lines[lines.length - 1];
|
|
1340
1370
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
1341
1371
|
return {
|
|
1342
|
-
exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !
|
|
1372
|
+
exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !expose.passed ? 1 : 0,
|
|
1343
1373
|
lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
|
|
1344
1374
|
documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
|
|
1345
1375
|
alwaysIncludeMissing, importerTestsAdded, ...(shardBaseline ? { baseline: shardBaseline } : {}),
|
|
@@ -1359,7 +1389,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1359
1389
|
Object.assign(capture, { verdict: 'passed', verdictLine: lines[lines.length - 1] } satisfies GateArtifactCapture);
|
|
1360
1390
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
1361
1391
|
logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
|
|
1362
|
-
return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed &&
|
|
1392
|
+
return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
|
|
1363
1393
|
}
|
|
1364
1394
|
|
|
1365
1395
|
if (worktreeLog.includes('deterministic environment setup failed')) lines.push(worktreeLog);
|
|
@@ -1394,7 +1424,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
1394
1424
|
verdictLine: lines[lines.length - 1],
|
|
1395
1425
|
} satisfies GateArtifactCapture);
|
|
1396
1426
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
1397
|
-
const exitCode = !androidPassed || !iosPassed || !pwaPassed || !
|
|
1427
|
+
const exitCode = !androidPassed || !iosPassed || !pwaPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
|
|
1398
1428
|
return { exitCode, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown, preconditionUnmet: report.preconditionUnmet } };
|
|
1399
1429
|
}
|
|
1400
1430
|
|
|
@@ -7,7 +7,7 @@ import { existsSync, lstatSync, realpathSync } from 'node:fs';
|
|
|
7
7
|
import { loadavg } from 'node:os';
|
|
8
8
|
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
9
9
|
import { debug } from '../debug/log.js';
|
|
10
|
-
import { gateHostReservationRoot, inspectReleaseGateHost } from '../release-loop/gate-host-reservation.js';
|
|
10
|
+
import { gateHostReservationRoot, inspectReleaseGateHost, readGateHostResourcesForHost, type GateHostResourceReading } from '../release-loop/gate-host-reservation.js';
|
|
11
11
|
import type { GateRemoteConfig } from '../user-config.js';
|
|
12
12
|
|
|
13
13
|
export type GateRemoteTool = 'self-gate' | 'ci-typecheck-changed' | 'public-export-test-run';
|
|
@@ -538,6 +538,8 @@ export interface DispatchDeps {
|
|
|
538
538
|
now?: () => number;
|
|
539
539
|
/** Test seam for gate.remote events; production defaults to the structured debug log. */
|
|
540
540
|
log?: (event: string, data: Record<string, unknown>) => void;
|
|
541
|
+
/** Read-only host-resource probe; production reads Pod pool ledgers, tests inject the same measured snapshot. */
|
|
542
|
+
readHostResources?: (host: string) => GateHostResourceReading;
|
|
541
543
|
write?: { out: (data: string | Uint8Array) => void; err: (data: string | Uint8Array) => void };
|
|
542
544
|
}
|
|
543
545
|
|
|
@@ -595,8 +597,24 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
595
597
|
const reservationRoot = opts.tool === 'self-gate' || opts.tool === 'ci-typecheck-changed'
|
|
596
598
|
? opts.reservationRoot ?? (deps.runner ? undefined : gateHostReservationRoot()) : undefined;
|
|
597
599
|
if (reservationRoot) {
|
|
600
|
+
const resourceStatus = (target: string) => {
|
|
601
|
+
if (!deps.readHostResources && deps.runner) return null; // fake runners keep tests hermetic unless the producer is explicitly exercised
|
|
602
|
+
return (deps.readHostResources ?? ((selected) => readGateHostResourcesForHost(selected, env)))(target.split('@').at(-1)!);
|
|
603
|
+
};
|
|
604
|
+
const inspect = (target: string) => {
|
|
605
|
+
const claim = inspectReleaseGateHost(reservationRoot, target);
|
|
606
|
+
const resources = resourceStatus(target);
|
|
607
|
+
if (!resources) return claim;
|
|
608
|
+
if (resources.status === 'unmeasurable') {
|
|
609
|
+
// Keep a concrete release owner visible even if the independent Pod ledgers cannot be read.
|
|
610
|
+
if (claim.status === 'reserved') return claim;
|
|
611
|
+
return { status: 'unknown' as const, reason: `resource probe unmeasurable: ${resources.reason}` };
|
|
612
|
+
}
|
|
613
|
+
if (!resources.empty) return { status: 'reserved' as const, reason: `Pod resource pool occupied (${resources.reservations} reservations)` };
|
|
614
|
+
return claim;
|
|
615
|
+
};
|
|
598
616
|
const reservationHost = host.split('@').at(-1)!;
|
|
599
|
-
const first =
|
|
617
|
+
const first = inspect(reservationHost);
|
|
600
618
|
if (first.status !== 'free') {
|
|
601
619
|
// A reserved host is never a reason to run this check locally (반증: 예약 상태에서 --local 무거운 시험 금지).
|
|
602
620
|
// Self gate first tries another remote host, then waits bounded for the release, then ends unmeasured with
|
|
@@ -609,7 +627,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
609
627
|
: `observed-at=${observedAt}`;
|
|
610
628
|
const alternates = opts.tool === 'self-gate'
|
|
611
629
|
? gateReservationAlternateHosts(reservationHost, opts.reservationAltHosts) : [];
|
|
612
|
-
const alternate = alternates.find((candidate) =>
|
|
630
|
+
const alternate = alternates.find((candidate) => inspect(candidate).status === 'free');
|
|
613
631
|
if (alternate) {
|
|
614
632
|
const rerouted = host.includes('@') ? `${host.slice(0, host.lastIndexOf('@'))}@${alternate}` : alternate;
|
|
615
633
|
debug.log('gate.remote', 'host-reserved-reroute', { tool: opts.tool, from: host, to: rerouted, owner, reason: first.reason, reservedAt: first.reservedAt, observedAt });
|
|
@@ -619,7 +637,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
619
637
|
const waitSeconds = opts.tool === 'self-gate' ? opts.reservationWaitSeconds ?? settings.slotWaitSeconds : 0;
|
|
620
638
|
const waitStart = now();
|
|
621
639
|
const deadline = waitStart + Math.max(0, waitSeconds) * 1000;
|
|
622
|
-
let latest =
|
|
640
|
+
let latest = inspect(reservationHost);
|
|
623
641
|
while (waitSeconds > 0 && latest.status !== 'free') {
|
|
624
642
|
const left = deadline - now();
|
|
625
643
|
if (left <= 0) break;
|
|
@@ -627,7 +645,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
627
645
|
const before = now();
|
|
628
646
|
await sleep(Math.min(15_000, left));
|
|
629
647
|
if (now() <= before) break; // a frozen test clock must not spin past the bound
|
|
630
|
-
latest =
|
|
648
|
+
latest = inspect(reservationHost);
|
|
631
649
|
}
|
|
632
650
|
const waitedMs = Math.max(0, now() - waitStart);
|
|
633
651
|
if (latest.status === 'free') {
|