elanous 0.2.36 → 0.2.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
- package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/drafts/recipes.yaml +27 -7
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/graphs/work/draft-close.yaml +54 -0
- package/graphs/work/green-close.yaml +37 -0
- package/graphs/work/recipes.yaml +46 -1
- package/graphs/work/run-research.yaml +35 -0
- package/package.json +1 -1
- package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/boundary-proof-mapping-audit.ts +88 -0
- package/scripts/brand/check.ts +13 -4
- package/scripts/codex-fallback-live-probe.ts +17 -15
- package/scripts/fleet/node-setup.sh +32 -2
- package/scripts/fleet/run-light-worker.sh +9 -0
- package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +546 -0
- package/scripts/goals/authoring-metrics.ts +258 -0
- package/scripts/graph-units/draft-close-node.ts +222 -0
- package/scripts/hook-order-sweep.ts +7 -4
- package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- package/scripts/release-loop/docs-node.ts +140 -0
- package/scripts/release-loop/gate-closure.ts +48 -0
- package/scripts/release-loop/gate-diff.ts +2 -1
- package/scripts/release-loop/gate-node.ts +161 -25
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- package/scripts/release-loop/known-issues-node.ts +6 -4
- package/scripts/release-loop/notes-repair.ts +216 -0
- package/scripts/release-loop/prepare-node.ts +61 -5
- package/scripts/release-loop/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +406 -7
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +109 -15
- package/scripts/train/green-leg.ts +176 -0
- package/scripts/tui-continue-real-evidence.ts +47 -0
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +12 -1
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +537 -57
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/autopilot/lineage/sources.ts +1 -1
- package/src/autopilot/pr-manager.ts +64 -13
- package/src/boot/daemon-runtime.ts +35 -3
- package/src/boot/daemon-tools/pty-shell.ts +2 -1
- package/src/bots/screen-probe.ts +1 -1
- package/src/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/capture/tui-self-report.ts +42 -5
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/autopilot-cli.ts +24 -9
- package/src/cli/decisions-cli.ts +7 -4
- package/src/cli/doctor-cli.ts +116 -7
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- package/src/cli/logs-cli.ts +357 -2
- package/src/cli/memory-cli.ts +30 -1
- package/src/cli/msg-cli.ts +15 -11
- package/src/cli/pr-granularity.ts +5 -3
- package/src/cli/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +58 -5
- package/src/cli/release-checklist-read-cli.ts +112 -4
- package/src/cli/release-cli.ts +89 -18
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +24 -6
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +370 -33
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/context-now.ts +86 -2
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +5 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +115 -30
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- package/src/display/coordinator.ts +45 -12
- package/src/display/resize-listener.ts +41 -20
- package/src/display/synchronized-output-region.ts +60 -0
- package/src/domains/guardian-tick.ts +9 -0
- package/src/domains/surface-events.ts +80 -1
- package/src/exec-requests/planner.ts +37 -2
- package/src/execution-loop/launch-gate.ts +4 -3
- package/src/git-fs/cli-stderr.ts +45 -0
- package/src/git-fs/gh-cli.ts +6 -3
- package/src/git-fs/git-cli.ts +11 -5
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +34 -7
- package/src/graph-wizard/generate.ts +29 -6
- package/src/grok/credential.ts +107 -36
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +151 -18
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +55 -0
- package/src/llm.ts +203 -21
- package/src/loops/checker.ts +100 -0
- package/src/loops/consensus.ts +26 -2
- package/src/loops/loop-cli.ts +9 -4
- package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +55 -7
- package/src/maturity/feature-maturity.ts +1 -0
- package/src/model-tier/llm-tier-map.ts +12 -17
- package/src/msg/msg-store.ts +17 -0
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -1
- package/src/nexus/api/graph-wizard-api.ts +27 -2
- package/src/nexus/api/grid.ts +24 -4
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +14 -6
- package/src/nexus/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -6
- package/src/nexus/state/state.ts +7 -1
- package/src/oauth/codex-account-store.ts +34 -1
- package/src/ops/loops-map.ts +46 -0
- package/src/ops/overview-cache.ts +22 -4
- package/src/ops/overview.ts +41 -5
- package/src/patents/ledger.ts +18 -1
- package/src/policy/llm-policy.ts +3 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +9 -4
- package/src/pty-shell/availability.ts +7 -0
- package/src/pty-shell/herdr-agent-report.ts +40 -31
- package/src/pty-shell/herdr-prune-stale.ts +17 -0
- package/src/pty-shell/herdr-sequence-lease.ts +60 -0
- package/src/pty-shell/pty-control-ipc.ts +187 -18
- package/src/pty-shell/pty-manifest.ts +16 -2
- package/src/pty-shell/registry.ts +25 -15
- package/src/pty-shell/tui-run-state.ts +235 -1
- package/src/release-loop/checklist.ts +50 -5
- package/src/release-loop/feature-store.ts +9 -9
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +18 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- package/src/seat-loop/seat-report.ts +1 -0
- package/src/self-dev/ask-launch-flow.ts +86 -10
- package/src/self-dev/decompose-proposal.ts +29 -18
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +254 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +310 -6
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +108 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +99 -1
- package/src/self-implement/gate-cli.ts +231 -82
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +30 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +407 -21
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +110 -27
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +125 -12
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +369 -33
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- package/src/self-implement/review-round-brief.ts +300 -0
- package/src/self-implement/rework-policy.ts +14 -0
- package/src/self-implement/run-ledger.ts +428 -6
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/running-runs.ts +17 -3
- package/src/self-implement/seams.ts +45 -16
- package/src/self-implement/self-implement-cli.ts +26 -2
- package/src/self-implement/stop-autoheal.ts +1 -0
- package/src/self-implement/test-seams.ts +13 -1
- package/src/self-implement/train-reach-grouping.ts +8 -2
- package/src/session/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +10 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +6 -0
- package/src/session-runtime/index.ts +18 -23
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/pty.ts +5 -0
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- package/src/status/metrics.ts +12 -1
- package/src/steward/rejudge-tick.ts +12 -5
- package/src/steward/resync-tick.ts +31 -4
- package/src/storage/file-lock.ts +17 -4
- package/src/task-agent/actions.ts +199 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/boundary-proof-mapping.ts +12 -0
- package/src/task-agent/boundary-proof-producer.ts +147 -0
- package/src/task-agent/completion-evidence.ts +2 -1
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/green-close-recipe.ts +239 -0
- package/src/task-agent/green-sweep.ts +64 -10
- package/src/task-agent/live-moves.ts +48 -3
- package/src/task-agent/map-host-adapter.ts +134 -0
- package/src/task-agent/map-reduce.ts +158 -0
- package/src/task-agent/map-run-ledger.ts +226 -0
- package/src/task-agent/parent-host.ts +74 -17
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +108 -8
- package/src/task-agent/repair-next-move.ts +12 -2
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/review-prior-fix.ts +12 -2
- package/src/task-agent/shadow.ts +188 -5
- package/src/task-agent/task-hand.ts +253 -20
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +40 -5
- package/src/task-agent/work-order.ts +53 -2
- package/src/task-orchestrator/dispatcher.ts +46 -1
- package/src/task-orchestrator/generator-prompt.ts +6 -0
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
- package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +722 -30
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +38 -35
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +72 -0
- package/src/tui-client/local-chat-turn.ts +31 -9
- package/src/user-config.ts +30 -3
- package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
- package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
- package/src/ux-sim/fake-gh.ts +174 -0
- package/src/ux-sim/fake-kubectl.ts +142 -0
- package/src/ux-sim/fake-llm.ts +17 -6
- package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
- package/src/ux-sim/resume-picker-device.ts +173 -0
- package/src/ux-sim/session-id-seed.ts +60 -0
- package/src/ux-sim/skills-tools-shell-device.ts +156 -0
- package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
- package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
- package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
- package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
- package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
- package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
- package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
- package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
- package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
- package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
- package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
- package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
- package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
- package/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
|
@@ -374,6 +374,21 @@ export function decideNextRun(input: {
|
|
|
374
374
|
const deployFindings = input.deployFindings === undefined ? undefined
|
|
375
375
|
: new Map([...input.deployFindings].filter(([taskId]) => !handedOffIds.has(taskId)));
|
|
376
376
|
const t = triageRun(activeResults, deployFindings, observation === 'failed', undefined, mainSyncRelaunchSpent(history));
|
|
377
|
+
const revisionUnobserved = activeResults.filter((result) => result.harvestable === true && !!result.branch
|
|
378
|
+
&& result.goalPlanRevision?.status !== 'read');
|
|
379
|
+
const revisionUnobservedIds = new Set(revisionUnobserved.map((result) => result.taskId));
|
|
380
|
+
for (const classification of t.classifications) {
|
|
381
|
+
if (classification.kind !== 'main-sync-blocked' || classification.action !== 'relaunch-on-main'
|
|
382
|
+
|| !revisionUnobservedIds.has(classification.taskId)) continue;
|
|
383
|
+
// Keep history's «already spent» predicate separate from this independent safety block.
|
|
384
|
+
classification.action = 'needs-human';
|
|
385
|
+
t.relaunchOnMain = t.relaunchOnMain.filter((taskId) => taskId !== classification.taskId);
|
|
386
|
+
if (!t.needsHuman.includes(classification.taskId)) t.needsHuman.push(classification.taskId);
|
|
387
|
+
}
|
|
388
|
+
t.actionable = countActionable(t) > 0;
|
|
389
|
+
const revisionHoldNote = revisionUnobserved.length > 0
|
|
390
|
+
? ` · 골 개정 관측 미확인 — 같은 골 재발사 보류(${revisionUnobserved.map((result) => result.taskId).join(', ')})`
|
|
391
|
+
: '';
|
|
377
392
|
const relaunchGoals: Record<string, string> = Object.fromEntries(activeResults.flatMap((result) =>
|
|
378
393
|
t.relaunchOnMain.includes(result.taskId) && result.branch
|
|
379
394
|
? [[result.taskId, mainSyncRelaunchGoal(result.feature, result.branch)]] : []));
|
|
@@ -438,7 +453,7 @@ export function decideNextRun(input: {
|
|
|
438
453
|
...base,
|
|
439
454
|
action: 'stop',
|
|
440
455
|
stopReason: 'harvestable-awaiting-human',
|
|
441
|
-
why: withGoalPlanRevisionObservation(`구현 완료 · 수확 대기 — ${harvestable.map((result) => result.branch).join(' · ')}`)
|
|
456
|
+
why: `${withGoalPlanRevisionObservation(`구현 완료 · 수확 대기 — ${harvestable.map((result) => result.branch).join(' · ')}`)}${revisionHoldNote}`,
|
|
442
457
|
};
|
|
443
458
|
}
|
|
444
459
|
|
|
@@ -604,7 +619,7 @@ export function decideNextRun(input: {
|
|
|
604
619
|
...base,
|
|
605
620
|
action: 'stop',
|
|
606
621
|
stopReason: 'no-progress',
|
|
607
|
-
why: withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 — base=${completionBase ?? 'main'} 기준 완료 ${baseCompleted} · 착지 ${landed} · 남은 조각도 안 줄었다(${actionable}). 골·불변식을 의심할 자리`)
|
|
622
|
+
why: `${withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 — base=${completionBase ?? 'main'} 기준 완료 ${baseCompleted} · 착지 ${landed} · 남은 조각도 안 줄었다(${actionable}). 골·불변식을 의심할 자리`)}${revisionHoldNote}`,
|
|
608
623
|
};
|
|
609
624
|
}
|
|
610
625
|
}
|
|
@@ -733,10 +748,10 @@ export function decideNextRun(input: {
|
|
|
733
748
|
...(action === 'add-repair-task' && held.length ? { heldTaskIds: held } : {}) },
|
|
734
749
|
pendingDecision: 'attempt-care-escalation',
|
|
735
750
|
why: fresh.length === 0
|
|
736
|
-
? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
|
|
751
|
+
? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}${revisionHoldNote}`
|
|
737
752
|
: cannotRepair
|
|
738
|
-
? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
|
|
739
|
-
: `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${repairedHeld.length ? ` · 이미 수리한 조각 ${repairedHeld.join(', ')} 은 사람 결정 대기` : ''}${classHeld.length ? ` · 분류로 보류한 조각 ${classHeld.join(', ')}` : ''}${heldReasonSuffix}`,
|
|
753
|
+
? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}${revisionHoldNote}`
|
|
754
|
+
: `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${repairedHeld.length ? ` · 이미 수리한 조각 ${repairedHeld.join(', ')} 은 사람 결정 대기` : ''}${classHeld.length ? ` · 분류로 보류한 조각 ${classHeld.join(', ')}` : ''}${heldReasonSuffix}${revisionHoldNote}`,
|
|
740
755
|
};
|
|
741
756
|
}
|
|
742
757
|
|
|
@@ -746,14 +761,14 @@ export function decideNextRun(input: {
|
|
|
746
761
|
return {
|
|
747
762
|
...base,
|
|
748
763
|
action: 'add-repair-task',
|
|
749
|
-
why: `수리 조각을 붙인다 — 수리 ${t.repairable.length} · 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 라운드 ${round + 1}/${maxRounds}`,
|
|
764
|
+
why: `수리 조각을 붙인다 — 수리 ${t.repairable.length} · 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 라운드 ${round + 1}/${maxRounds}${revisionHoldNote}`,
|
|
750
765
|
};
|
|
751
766
|
}
|
|
752
767
|
|
|
753
768
|
return {
|
|
754
769
|
...base,
|
|
755
770
|
action: 'relaunch',
|
|
756
|
-
why: `다시 건다 — 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 수리 ${t.repairable.length}${t.relaunchOnMain.length > 0 ? ` · main 위 재발사 ${t.relaunchOnMain.length}` : ''} · 라운드 ${round + 1}/${maxRounds}`,
|
|
771
|
+
why: `다시 건다 — 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 수리 ${t.repairable.length}${t.relaunchOnMain.length > 0 ? ` · main 위 재발사 ${t.relaunchOnMain.length}` : ''} · 라운드 ${round + 1}/${maxRounds}${revisionHoldNote}`,
|
|
757
772
|
};
|
|
758
773
|
}
|
|
759
774
|
|
|
@@ -105,3 +105,51 @@ export function planFixedGateTestShards(files: readonly string[], shardCount: nu
|
|
|
105
105
|
}
|
|
106
106
|
return groups.map((group, index) => ({ id: `shard-${index + 1}`, files: group, plannedRssMb: 0, plannedSeconds: 0 }));
|
|
107
107
|
}
|
|
108
|
+
|
|
109
|
+
/** GATE-REMOTE-SHARD-PLAN — one remote shard carrying its orchestration identity; introducedFiles are this shard's own
|
|
110
|
+
* files, so introduced attribution stays file-level (a shard never inherits another shard's introduced files). */
|
|
111
|
+
export interface GateRemoteShard {
|
|
112
|
+
orchestrationId: string;
|
|
113
|
+
shardId: string;
|
|
114
|
+
totalShards: number;
|
|
115
|
+
position: number;
|
|
116
|
+
files: string[];
|
|
117
|
+
introducedFiles: string[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Deterministic orchestration id for a changed-file list: same files in any order produce the same id, so re-plans stay joinable. */
|
|
121
|
+
export function shardPlanOrchestrationId(files: readonly string[]): string {
|
|
122
|
+
const sorted = [...new Set(files)].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
123
|
+
let hash = 0x811c9dc5;
|
|
124
|
+
for (const file of sorted) {
|
|
125
|
+
for (let index = 0; index < file.length; index += 1) {
|
|
126
|
+
hash ^= file.charCodeAt(index);
|
|
127
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return `gate-${sorted.length}-${hash.toString(16).padStart(8, '0')}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Split a changed-file list (e.g. 183 files) into identity-carrying shards; every file is introduced by its own shard.
|
|
134
|
+
* Contiguous slices keep each shard's files in input order, so concatenating shards reproduces the input list. */
|
|
135
|
+
export function planGateRemoteShards(files: readonly string[], shardCount: number, orchestrationId: string): GateRemoteShard[] {
|
|
136
|
+
if (!Number.isSafeInteger(shardCount) || shardCount < 1) throw new Error('invalid shard count');
|
|
137
|
+
const sorted = [...new Set(files)].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
138
|
+
if (!sorted.length) throw new Error('no files to shard');
|
|
139
|
+
if (shardCount > sorted.length) throw new Error(`shard count ${shardCount} exceeds file count ${sorted.length}`);
|
|
140
|
+
const base = Math.floor(sorted.length / shardCount);
|
|
141
|
+
const extra = sorted.length % shardCount;
|
|
142
|
+
return Array.from({ length: shardCount }, (_, index) => {
|
|
143
|
+
const start = index * base + Math.min(index, extra);
|
|
144
|
+
const size = base + (index < extra ? 1 : 0);
|
|
145
|
+
const shardFiles = sorted.slice(start, start + size);
|
|
146
|
+
return {
|
|
147
|
+
orchestrationId,
|
|
148
|
+
shardId: `${orchestrationId}/shard-${index + 1}`,
|
|
149
|
+
totalShards: shardCount,
|
|
150
|
+
position: index + 1,
|
|
151
|
+
files: shardFiles,
|
|
152
|
+
introducedFiles: [...shardFiles],
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statfsSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { availableParallelism, freemem, tmpdir } from 'node:os';
|
|
2
|
+
import { availableParallelism, freemem, loadavg, tmpdir, totalmem } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { debug, redactSecretText } from '../debug/log.js';
|
|
5
5
|
import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
|
|
6
6
|
import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
|
|
7
|
-
import { withBaselineWorktree } from '../self-implement/gate-baseline.js';
|
|
7
|
+
import { withBaselineWorktree, withBaselineWorktreeAsync } from '../self-implement/gate-baseline.js';
|
|
8
8
|
import { aggregateGateTestShards, type GateShardAttempt, type GateShardAggregate } from './shard-aggregate.js';
|
|
9
9
|
import { GateShardCapacityError, planFixedGateTestShards, planSelfGateSpawnSeparatedShards, type GateTestShard } from './shard-plan.js';
|
|
10
10
|
import { isGateSpawnLaneFile } from './spawn-lane-files.js';
|
|
@@ -27,6 +27,15 @@ export interface ShardRunResult {
|
|
|
27
27
|
unmeasuredByShard?: Record<string, string>;
|
|
28
28
|
/** git stderr tail (redacted · ≤2KB · one line) when the baseline worktree could not be added. */
|
|
29
29
|
baselineStderrTail?: string;
|
|
30
|
+
/** Effective live pool width and its host-load/memory decision, for gate artifacts and diagnosis. */
|
|
31
|
+
concurrency?: number;
|
|
32
|
+
concurrencyReason?: string;
|
|
33
|
+
/** Wall time spent in singleton RSS samples and current+baseline bundles, respectively. */
|
|
34
|
+
measurementMs?: number;
|
|
35
|
+
bundleMs?: number;
|
|
36
|
+
/** Sum of process wall times across bundles (overlaps under concurrency). */
|
|
37
|
+
currentProcessMs?: number;
|
|
38
|
+
baselineProcessMs?: number;
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
/** What a failed shard process leaves behind so «test failure vs runner error» can be told apart after the fact. */
|
|
@@ -50,7 +59,19 @@ export interface ShardRunMode {
|
|
|
50
59
|
/** OP FU — sorted round-robin into `count` shards, zero pre-measurement runs. Default off: the measured planner. */
|
|
51
60
|
fixedDistribution?: boolean;
|
|
52
61
|
/** Measured on the executing host; override only for deterministic planning tests. */
|
|
53
|
-
hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number };
|
|
62
|
+
hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number; load1?: number };
|
|
63
|
+
/** Observation after each bundle's first current+baseline attempt; never controls retries or verdict. */
|
|
64
|
+
onShardComplete?: (progress: ShardRunProgress) => void;
|
|
65
|
+
/** Maximum concurrently active shard bundles. The default is three, bounded to one through four. */
|
|
66
|
+
concurrency?: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ShardRunProgress {
|
|
70
|
+
shardId: string;
|
|
71
|
+
completedShards: number;
|
|
72
|
+
totalShards: number;
|
|
73
|
+
completedFiles: number;
|
|
74
|
+
totalFiles: number;
|
|
54
75
|
}
|
|
55
76
|
|
|
56
77
|
function hostResources(): ShardRunMode['hostResources'] | undefined {
|
|
@@ -63,14 +84,37 @@ function hostResources(): ShardRunMode['hostResources'] | undefined {
|
|
|
63
84
|
const availableKiB = /^MemAvailable:\s+(\d+)\s+kB/m.exec(readFileSync('/proc/meminfo', 'utf8'))?.[1];
|
|
64
85
|
if (availableKiB) freeMemoryGiB = Number(availableKiB) / (1024 ** 2);
|
|
65
86
|
}
|
|
87
|
+
if (process.platform === 'darwin') {
|
|
88
|
+
// macOS freemem excludes reclaimable cache; node-b reported 5 GiB free of 512 GiB while
|
|
89
|
+
// memory_pressure reported 91% available. A freemem cap would silently serialize the gate.
|
|
90
|
+
const pressure = Bun.spawnSync(['memory_pressure', '-Q'], { stdout: 'pipe', stderr: 'ignore', timeout: 2_000 });
|
|
91
|
+
const percent = /System-wide memory free percentage:\s*(\d+(?:\.\d+)?)%/.exec(Buffer.from(pressure.stdout).toString('utf8'))?.[1];
|
|
92
|
+
if (pressure.exitCode === 0 && percent !== undefined && Number(percent) >= 0 && Number(percent) <= 100) {
|
|
93
|
+
freeMemoryGiB = totalmem() / (1024 ** 3) * Number(percent) / 100;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
66
96
|
return {
|
|
67
97
|
cores: availableParallelism(),
|
|
68
98
|
freeMemoryGiB,
|
|
69
99
|
freeTmpGiB: Number(tmp.bavail) * Number(tmp.bsize) / (1024 ** 3),
|
|
100
|
+
load1: loadavg()[0],
|
|
70
101
|
};
|
|
71
102
|
} catch { return undefined; }
|
|
72
103
|
}
|
|
73
104
|
|
|
105
|
+
/** A conservative snapshot taken before sampling. Explicit 1 preserves the old serial child order. */
|
|
106
|
+
export function resolveShardConcurrency(configured: number | undefined, resources: ShardRunMode['hostResources'], budgetGiB: number): { count: number; reason: string } {
|
|
107
|
+
if (!resources || !Number.isFinite(resources.cores) || resources.cores < 1) return { count: Math.max(1, Math.min(4, configured ?? 3)), reason: configured === undefined ? 'default; host load unavailable' : 'configured; host load unavailable' };
|
|
108
|
+
const loadRatio = Number.isFinite(resources.load1) ? resources.load1! / resources.cores : null;
|
|
109
|
+
const target = configured ?? (loadRatio !== null && loadRatio >= 0.8 ? 2
|
|
110
|
+
: loadRatio !== null && loadRatio <= 0.35 && resources.cores >= 8 ? 4 : 3);
|
|
111
|
+
const cpuCap = Math.max(1, Math.floor(resources.cores));
|
|
112
|
+
const memoryCap = Number.isFinite(resources.freeMemoryGiB) && Number.isFinite(budgetGiB) && budgetGiB > 0
|
|
113
|
+
? Math.max(1, Math.floor(resources.freeMemoryGiB / budgetGiB)) : 4;
|
|
114
|
+
const count = Math.max(1, Math.min(4, target, cpuCap, memoryCap));
|
|
115
|
+
return { count, reason: `${configured === undefined ? 'adaptive' : `configured ${configured}`} · host load/cores ${loadRatio === null ? '?' : loadRatio.toFixed(2)} · free ${resources.freeMemoryGiB.toFixed(1)} GiB · shard budget ${budgetGiB} GiB` };
|
|
116
|
+
}
|
|
117
|
+
|
|
74
118
|
/** One expansion slot needs one CPU, one shard memory budget, and 1 GiB of free tmp space.
|
|
75
119
|
* Explicitly requested shards remain the caller's choice; this only limits automatic growth. */
|
|
76
120
|
export function maxAutomaticShardCount(requested: number, budgetGiB: number, resources: ShardRunMode['hostResources']): number {
|
|
@@ -94,6 +138,7 @@ export type ShardProcess = (cwd: string, files: readonly string[]) => {
|
|
|
94
138
|
/** Present only when the process failed (exit≠0 · signal · no JUnit) — observation only, never part of the verdict. */
|
|
95
139
|
failure?: ShardFailureOutput;
|
|
96
140
|
};
|
|
141
|
+
export type AsyncShardProcess = (cwd: string, files: readonly string[]) => Promise<ReturnType<ShardProcess>>;
|
|
97
142
|
|
|
98
143
|
export const SHARD_FAILURE_TAIL_BYTES = 64 * 1024;
|
|
99
144
|
|
|
@@ -103,6 +148,29 @@ function outputTail(bytes: Uint8Array | undefined): string {
|
|
|
103
148
|
return redactSecretText(Buffer.from(tail).toString('utf8'));
|
|
104
149
|
}
|
|
105
150
|
|
|
151
|
+
/** Drain a child pipe without retaining its entire output. Diagnostics need the opening context and failure tail. */
|
|
152
|
+
async function boundedChildOutput(stream: ReadableStream<Uint8Array>, abort: AbortSignal): Promise<Uint8Array> {
|
|
153
|
+
const reader = stream.getReader();
|
|
154
|
+
const cancel = () => { void reader.cancel('child output drain timed out').catch(() => {}); };
|
|
155
|
+
abort.addEventListener('abort', cancel, { once: true });
|
|
156
|
+
const headLimit = 1024;
|
|
157
|
+
let head = new Uint8Array(0);
|
|
158
|
+
let tail = new Uint8Array(0);
|
|
159
|
+
let total = 0;
|
|
160
|
+
try {
|
|
161
|
+
for (;;) {
|
|
162
|
+
const { done, value } = await reader.read();
|
|
163
|
+
if (done) break;
|
|
164
|
+
total += value.byteLength;
|
|
165
|
+
if (head.byteLength < headLimit) head = Buffer.concat([head, value.subarray(0, headLimit - head.byteLength)]);
|
|
166
|
+
tail = value.byteLength >= SHARD_FAILURE_TAIL_BYTES
|
|
167
|
+
? value.slice(-SHARD_FAILURE_TAIL_BYTES)
|
|
168
|
+
: Buffer.concat([tail, value]).subarray(-SHARD_FAILURE_TAIL_BYTES);
|
|
169
|
+
}
|
|
170
|
+
} finally { abort.removeEventListener('abort', cancel); reader.releaseLock(); }
|
|
171
|
+
return total <= SHARD_FAILURE_TAIL_BYTES ? tail : Buffer.concat([head, tail]);
|
|
172
|
+
}
|
|
173
|
+
|
|
106
174
|
/** `<shardId>.failure.json` per failed shard (shard ids are already `shard-<n>`). Top level = the latest current-side
|
|
107
175
|
* failure (else the latest baseline one); `failures` keeps every failed side/attempt. Returns the written paths. */
|
|
108
176
|
export function writeShardFailureEvidence(dir: string, evidence: readonly ShardFailureEvidence[]): string[] {
|
|
@@ -162,7 +230,7 @@ export function runShardedGateTests(
|
|
|
162
230
|
try { fixed = planFixedGateTestShards(files, count); }
|
|
163
231
|
catch (error) { return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [], reason: String(error), distribution: 'fixed' }; }
|
|
164
232
|
debug.log('self-dev.shard', 'fixed-distribution', { shards: fixed.length, files: fixed.reduce((sum, shard) => sum + shard.files.length, 0) });
|
|
165
|
-
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed' };
|
|
233
|
+
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed' };
|
|
166
234
|
}
|
|
167
235
|
const rss = new Map<string, number>();
|
|
168
236
|
const seconds = new Map<string, number>();
|
|
@@ -199,7 +267,7 @@ export function runShardedGateTests(
|
|
|
199
267
|
const fixed = planFixedGateTestShards(files, maxCount);
|
|
200
268
|
debug.log('self-dev.shard', 'host-cap-fixed-fallback', { requested: count, cap: maxCount,
|
|
201
269
|
files: new Set(files).size, reason, measurementFailures: measurementFailures ?? 0 });
|
|
202
|
-
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed-cap-fallback',
|
|
270
|
+
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed-cap-fallback',
|
|
203
271
|
fallbackReason: reason, ...(measurementFailures ? { measurementFailures } : {}) };
|
|
204
272
|
} catch (error) {
|
|
205
273
|
return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [],
|
|
@@ -232,7 +300,7 @@ export function runShardedGateTests(
|
|
|
232
300
|
requested: count, planned: shards.length, files: new Set(files).size, budgetGiB,
|
|
233
301
|
measurementFailures: measurementFailures ?? 0,
|
|
234
302
|
});
|
|
235
|
-
return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
|
|
303
|
+
return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree, mode.onShardComplete), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
|
|
236
304
|
}
|
|
237
305
|
|
|
238
306
|
/** Shared by the measured and the fixed planner: current + baseline per shard, one retry round, one aggregate. */
|
|
@@ -242,6 +310,7 @@ function runPlannedShards(
|
|
|
242
310
|
baseRef: string,
|
|
243
311
|
run: ShardProcess,
|
|
244
312
|
baselineWorktree: typeof withBaselineWorktree,
|
|
313
|
+
onShardComplete?: ShardRunMode['onShardComplete'],
|
|
245
314
|
): ShardRunResult {
|
|
246
315
|
const attempts: GateShardAttempt[] = [];
|
|
247
316
|
const failureEvidence: ShardFailureEvidence[] = [];
|
|
@@ -256,6 +325,8 @@ function runPlannedShards(
|
|
|
256
325
|
const treeReadable = (() => { try { return statSync(dir).isDirectory(); } catch { return false; } })();
|
|
257
326
|
const atBase = (shard: GateTestShard) => treeReadable ? shard.files.filter((file) => !absentAtBaseline(join(dir, file))) : [...shard.files];
|
|
258
327
|
let pending = shards;
|
|
328
|
+
let completedFiles = 0;
|
|
329
|
+
const totalFiles = new Set(shards.flatMap((shard) => shard.files)).size;
|
|
259
330
|
for (let round = 1; round <= 2 && pending.length; round++) {
|
|
260
331
|
for (const shard of pending) {
|
|
261
332
|
const runSafely = (location: string, selected: readonly string[]): ReturnType<ShardProcess> => {
|
|
@@ -279,6 +350,13 @@ function runPlannedShards(
|
|
|
279
350
|
baselineFiles,
|
|
280
351
|
currentRoot: cwd, baselineRoot: dir,
|
|
281
352
|
});
|
|
353
|
+
if (round === 1 && onShardComplete) {
|
|
354
|
+
completedFiles += shard.files.length;
|
|
355
|
+
try {
|
|
356
|
+
onShardComplete({ shardId: shard.id, completedShards: attempts.length,
|
|
357
|
+
totalShards: shards.length, completedFiles, totalFiles });
|
|
358
|
+
} catch { /* progress is observation only */ }
|
|
359
|
+
}
|
|
282
360
|
}
|
|
283
361
|
const retry = new Set(aggregateGateTestShards(shards, attempts).retryShardIds);
|
|
284
362
|
pending = shards.filter((shard) => retry.has(shard.id));
|
|
@@ -301,6 +379,146 @@ function runPlannedShards(
|
|
|
301
379
|
};
|
|
302
380
|
}
|
|
303
381
|
|
|
382
|
+
/** Runs planned bundles concurrently while retaining plan order in attempts and aggregate evidence. */
|
|
383
|
+
export async function runShardedGateTestsAsync(
|
|
384
|
+
cwd: string,
|
|
385
|
+
files: readonly string[],
|
|
386
|
+
baseRef: string,
|
|
387
|
+
count = 2,
|
|
388
|
+
run: AsyncShardProcess = runBunShardAsync,
|
|
389
|
+
baselineWorktree: typeof withBaselineWorktreeAsync = withBaselineWorktreeAsync,
|
|
390
|
+
budgetGiB = 8,
|
|
391
|
+
mode: ShardRunMode = {},
|
|
392
|
+
measure: AsyncShardProcess = run,
|
|
393
|
+
): Promise<ShardRunResult> {
|
|
394
|
+
if (mode.concurrency !== undefined && (!Number.isSafeInteger(mode.concurrency) || mode.concurrency < 1 || mode.concurrency > 4)) throw new Error('invalid shard concurrency (expected 1–4)');
|
|
395
|
+
const resources = mode.hostResources ?? hostResources();
|
|
396
|
+
const selectedConcurrency = resolveShardConcurrency(mode.concurrency, resources, budgetGiB);
|
|
397
|
+
const concurrency = selectedConcurrency.count;
|
|
398
|
+
debug.log('self-dev.shard', 'concurrency', { concurrency, reason: selectedConcurrency.reason });
|
|
399
|
+
const measurementStartedAt = performance.now();
|
|
400
|
+
const samples = new Map<string, ReturnType<ShardProcess>>();
|
|
401
|
+
if (!mode.fixedDistribution) {
|
|
402
|
+
const unique = [...new Set(files)];
|
|
403
|
+
let nextSample = 0;
|
|
404
|
+
const sampleWorker = async () => {
|
|
405
|
+
for (;;) {
|
|
406
|
+
const index = nextSample++;
|
|
407
|
+
if (index >= unique.length) return;
|
|
408
|
+
const file = unique[index]!;
|
|
409
|
+
try { samples.set(file, await measure(cwd, [file])); }
|
|
410
|
+
catch (error) {
|
|
411
|
+
debug.log('self-dev.shard', 'rss-measurement-failed', { file, error: redactSecretText(String(error)).slice(0, 500) });
|
|
412
|
+
samples.set(file, { exitCode: null });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, unique.length) }, () => sampleWorker()));
|
|
417
|
+
}
|
|
418
|
+
const measurementMs = Math.round(performance.now() - measurementStartedAt);
|
|
419
|
+
// Reuse the established measured/fixed planner and its host-cap fallback. The callback supplies a
|
|
420
|
+
// planning-only aggregate, so this phase never launches a shard or creates a baseline worktree.
|
|
421
|
+
const planningOnlyBaseline = (() => ({ status: 'passed' as const, retryShardIds: [] })) as unknown as typeof withBaselineWorktree;
|
|
422
|
+
const planned = runShardedGateTests(cwd, files, baseRef, count, (_cwd, selected) => samples.get(selected[0]!) ?? { exitCode: null },
|
|
423
|
+
planningOnlyBaseline, budgetGiB, { ...mode, ...(resources ? { hostResources: resources } : {}) });
|
|
424
|
+
if (planned.reason) return { ...planned, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs: 0 };
|
|
425
|
+
const shards = planned.shards;
|
|
426
|
+
const attempts: GateShardAttempt[] = [];
|
|
427
|
+
const failureEvidence: ShardFailureEvidence[] = [];
|
|
428
|
+
const bundlesStartedAt = performance.now();
|
|
429
|
+
let currentProcessMs = 0;
|
|
430
|
+
let baselineProcessMs = 0;
|
|
431
|
+
const baseline = await baselineWorktree(cwd, baseRef, async (dir) => {
|
|
432
|
+
const treeReadable = (() => { try { return statSync(dir).isDirectory(); } catch { return false; } })();
|
|
433
|
+
// Baseline membership is invariant for both rounds. Cache it before launching children.
|
|
434
|
+
const atBase = new Map(shards.map((shard) => [shard.id,
|
|
435
|
+
treeReadable ? shard.files.filter((file) => !absentAtBaseline(join(dir, file))) : [...shard.files]]));
|
|
436
|
+
const baselinePassCache = new Map<string, ReturnType<ShardProcess>>();
|
|
437
|
+
const totalFiles = new Set(shards.flatMap((shard) => shard.files)).size;
|
|
438
|
+
let completedShards = 0;
|
|
439
|
+
let completedFiles = 0;
|
|
440
|
+
let pending = shards;
|
|
441
|
+
for (let round = 1; round <= 2 && pending.length; round++) {
|
|
442
|
+
const roundAttempts = new Array<GateShardAttempt>(pending.length);
|
|
443
|
+
const roundEvidence = new Array<ShardFailureEvidence[]>(pending.length);
|
|
444
|
+
let next = 0;
|
|
445
|
+
const runSafely = async (location: string, selected: readonly string[]): Promise<ReturnType<ShardProcess>> => {
|
|
446
|
+
try { return await run(location, selected); }
|
|
447
|
+
catch (error) {
|
|
448
|
+
debug.log('self-dev.shard', 'bundle-runner-failed', { location, files: selected,
|
|
449
|
+
error: redactSecretText(String(error)).slice(0, 500) });
|
|
450
|
+
return { exitCode: null };
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
const worker = async () => {
|
|
454
|
+
for (;;) {
|
|
455
|
+
const index = next++;
|
|
456
|
+
if (index >= pending.length) return;
|
|
457
|
+
const shard = pending[index]!;
|
|
458
|
+
const baselineFiles = atBase.get(shard.id)!;
|
|
459
|
+
if (baselineFiles.length < shard.files.length) {
|
|
460
|
+
debug.log('self-dev.shard', 'baseline-files-absent', { shardId: shard.id, round,
|
|
461
|
+
absent: shard.files.filter((file) => !baselineFiles.includes(file)) });
|
|
462
|
+
}
|
|
463
|
+
const currentStartedAt = performance.now();
|
|
464
|
+
const current = await runSafely(cwd, shard.files);
|
|
465
|
+
currentProcessMs += performance.now() - currentStartedAt;
|
|
466
|
+
const cached = concurrency > 1 && round > 1 ? baselinePassCache.get(shard.id) : undefined;
|
|
467
|
+
if (cached) debug.log('self-dev.shard', 'baseline-cache-hit', { shardId: shard.id, round });
|
|
468
|
+
const baselineStartedAt = performance.now();
|
|
469
|
+
const base = cached ?? (baselineFiles.length ? await runSafely(dir, baselineFiles) : { exitCode: 0 });
|
|
470
|
+
baselineProcessMs += performance.now() - baselineStartedAt;
|
|
471
|
+
if (concurrency > 1 && baselineFiles.length && base.exitCode === 0 && !base.signal && base.junit) baselinePassCache.set(shard.id, base);
|
|
472
|
+
roundAttempts[index] = {
|
|
473
|
+
shardId: shard.id, attempt: round, currentJUnit: current.junit, baselineJUnit: base.junit,
|
|
474
|
+
currentExitCode: current.exitCode, baselineExitCode: base.exitCode,
|
|
475
|
+
currentSignal: current.signal, baselineSignal: base.signal,
|
|
476
|
+
currentDiagnostic: current.diagnostic, baselineDiagnostic: base.diagnostic,
|
|
477
|
+
baselineFiles, currentRoot: cwd, baselineRoot: dir,
|
|
478
|
+
};
|
|
479
|
+
roundEvidence[index] = [];
|
|
480
|
+
for (const [side, result, selected] of [
|
|
481
|
+
['current', current, shard.files], ['baseline', base, baselineFiles],
|
|
482
|
+
] as const) {
|
|
483
|
+
if (result.failure) roundEvidence[index]!.push({ shardId: shard.id, side, attempt: round,
|
|
484
|
+
files: [...selected], exitCode: result.exitCode, signal: result.signal ?? null, ...result.failure });
|
|
485
|
+
}
|
|
486
|
+
if (round === 1 && mode.onShardComplete) {
|
|
487
|
+
completedShards++;
|
|
488
|
+
completedFiles += shard.files.length;
|
|
489
|
+
try { mode.onShardComplete({ shardId: shard.id, completedShards, totalShards: shards.length,
|
|
490
|
+
completedFiles, totalFiles }); } catch { /* observation only */ }
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, pending.length) }, () => worker()));
|
|
495
|
+
attempts.push(...roundAttempts);
|
|
496
|
+
for (const evidence of roundEvidence) failureEvidence.push(...evidence);
|
|
497
|
+
const retry = new Set(aggregateGateTestShards(shards, attempts).retryShardIds);
|
|
498
|
+
pending = shards.filter((shard) => retry.has(shard.id));
|
|
499
|
+
}
|
|
500
|
+
return aggregateGateTestShards(shards, attempts);
|
|
501
|
+
});
|
|
502
|
+
const evidence = failureEvidence.length ? { failureEvidence } : {};
|
|
503
|
+
const bundleMs = Math.round(performance.now() - bundlesStartedAt);
|
|
504
|
+
if ('retryShardIds' in baseline) return {
|
|
505
|
+
...planned, aggregate: baseline, attempts, ...evidence, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs,
|
|
506
|
+
currentProcessMs: Math.round(currentProcessMs), baselineProcessMs: Math.round(baselineProcessMs),
|
|
507
|
+
...(baseline.retryShardIds.length ? { unmeasuredByShard: incompleteShardReasons(baseline.retryShardIds, attempts) } : {}),
|
|
508
|
+
};
|
|
509
|
+
const retryShardIds = shards.map((shard) => shard.id);
|
|
510
|
+
const stderrTail = baseline.gitStderrTail;
|
|
511
|
+
const stderrPart = stderrTail ? ` · git stderr: ${stderrTail}` : '';
|
|
512
|
+
return {
|
|
513
|
+
...planned, aggregate: { status: 'unmeasured', retryShardIds }, attempts, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs,
|
|
514
|
+
currentProcessMs: Math.round(currentProcessMs), baselineProcessMs: Math.round(baselineProcessMs),
|
|
515
|
+
reason: baseline.log, ...evidence,
|
|
516
|
+
unmeasuredByShard: Object.fromEntries(retryShardIds.map((id) => [id,
|
|
517
|
+
`baseline worktree: ${redactSecretText(baseline.log).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500)}${stderrPart}`])),
|
|
518
|
+
...(stderrTail ? { baselineStderrTail: stderrTail } : {}),
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
304
522
|
function incompleteShardReasons(shardIds: readonly string[], attempts: readonly GateShardAttempt[]): Record<string, string> {
|
|
305
523
|
return Object.fromEntries(shardIds.map((id) => {
|
|
306
524
|
const latest = attempts.filter((attempt) => attempt.shardId === id).at(-1);
|
|
@@ -360,3 +578,89 @@ export function runBunShardWithSpawn(cwd: string, files: readonly string[], spaw
|
|
|
360
578
|
rmSync(dir, { recursive: true, force: true });
|
|
361
579
|
}
|
|
362
580
|
}
|
|
581
|
+
|
|
582
|
+
/** Nonblocking child runner; each bundle still owns its own deterministic environment and JUnit path. */
|
|
583
|
+
export async function runBunShardAsync(cwd: string, files: readonly string[], drainTimeoutMs = 5_000): Promise<ReturnType<ShardProcess>> {
|
|
584
|
+
const timeout = selfGateShardTimeoutMs(files);
|
|
585
|
+
const spawnLane = timeout === 120_000;
|
|
586
|
+
const dir = mkdtempSync(join(tmpdir(), 'elanous-shard-junit-'));
|
|
587
|
+
const report = join(dir, 'result.xml');
|
|
588
|
+
const isolated = prepareDeterministicChildEnvironment('elanous-shard-test-env-', { env: withGateTestEnv(process.env) });
|
|
589
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
590
|
+
let drainTimer: ReturnType<typeof setTimeout> | undefined;
|
|
591
|
+
const drainAbort = new AbortController();
|
|
592
|
+
try {
|
|
593
|
+
const args = ['test', ...(spawnLane ? ['--timeout=120000'] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
|
|
594
|
+
const started = performance.now();
|
|
595
|
+
const child = Bun.spawn(['bun', ...args], { cwd, env: isolated.env, stdout: 'pipe', stderr: 'pipe' });
|
|
596
|
+
let timedOut = false;
|
|
597
|
+
let drainTimedOut = false;
|
|
598
|
+
timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL'); }, timeout);
|
|
599
|
+
const stdoutOutput = boundedChildOutput(child.stdout, drainAbort.signal);
|
|
600
|
+
const stderrOutput = boundedChildOutput(child.stderr, drainAbort.signal);
|
|
601
|
+
const exited = child.exited.then((code) => {
|
|
602
|
+
// Pipe draining can continue after process exit; a late timer must not relabel a clean exit as SIGKILL.
|
|
603
|
+
if (timer) clearTimeout(timer);
|
|
604
|
+
timer = undefined;
|
|
605
|
+
drainTimer = setTimeout(() => {
|
|
606
|
+
drainTimedOut = true;
|
|
607
|
+
debug.log('self-dev.shard', 'output-drain-timeout', { cwd, files, drainTimeoutMs });
|
|
608
|
+
drainAbort.abort();
|
|
609
|
+
}, drainTimeoutMs);
|
|
610
|
+
return code;
|
|
611
|
+
});
|
|
612
|
+
const [exitCode, stdoutBuffer, stderrBuffer] = await Promise.all([
|
|
613
|
+
exited,
|
|
614
|
+
stdoutOutput,
|
|
615
|
+
stderrOutput,
|
|
616
|
+
]);
|
|
617
|
+
if (drainTimer) clearTimeout(drainTimer);
|
|
618
|
+
drainTimer = undefined;
|
|
619
|
+
const stdout = stdoutBuffer;
|
|
620
|
+
const stderr = stderrBuffer;
|
|
621
|
+
const durationMs = performance.now() - started;
|
|
622
|
+
const usage = child.resourceUsage();
|
|
623
|
+
const junit = existsSync(report) ? readFileSync(report, 'utf8') : undefined;
|
|
624
|
+
const signal = drainTimedOut ? 'DRAIN_TIMEOUT' : timedOut ? 'SIGKILL' : child.signalCode ? String(child.signalCode) : undefined;
|
|
625
|
+
const failed = exitCode !== 0 || !!signal || junit === undefined;
|
|
626
|
+
return {
|
|
627
|
+
exitCode, signal, junit,
|
|
628
|
+
...(files.length === 1 ? { rssMb: usage ? usage.maxRSS / (1024 * 1024) : undefined, seconds: durationMs / 1000 } : {}),
|
|
629
|
+
...(junit === undefined && (exitCode !== 0 || signal) ? { diagnostic: boundedDiagnostic(stdout, stderr) } : {}),
|
|
630
|
+
...(failed ? { failure: { durationMs: Math.round(durationMs), stdoutTail: outputTail(stdout), stderrTail: outputTail(stderr) } } : {}),
|
|
631
|
+
};
|
|
632
|
+
} finally {
|
|
633
|
+
if (timer) clearTimeout(timer);
|
|
634
|
+
if (drainTimer) clearTimeout(drainTimer);
|
|
635
|
+
drainAbort.abort();
|
|
636
|
+
isolated.cleanup();
|
|
637
|
+
rmSync(dir, { recursive: true, force: true });
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/** GATE-REMOTE-SHARD-PLAN — identity of one remote shard. files/introducedFiles are optional: a caller that only relays
|
|
642
|
+
* identity (CLI wiring) passes none, while a planner-produced shard carries its file-level attribution. */
|
|
643
|
+
export interface RemoteShardSpec {
|
|
644
|
+
orchestrationId: string;
|
|
645
|
+
shardId: string;
|
|
646
|
+
totalShards: number;
|
|
647
|
+
position: number;
|
|
648
|
+
files?: readonly string[];
|
|
649
|
+
introducedFiles?: readonly string[];
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** The identity slice that rides a remote gate command line — validated so a dropped flag fails loudly, not silently. */
|
|
653
|
+
export function remoteShardArgArgs(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
|
|
654
|
+
if (!shard.orchestrationId.trim()) throw new Error('orchestration id must be non-empty');
|
|
655
|
+
if (!shard.shardId.trim()) throw new Error('shard id must be non-empty');
|
|
656
|
+
if (!Number.isSafeInteger(shard.totalShards) || shard.totalShards < 1) throw new Error('shard total must be a positive integer');
|
|
657
|
+
if (!Number.isSafeInteger(shard.position) || shard.position < 1) throw new Error('shard position must be a positive integer');
|
|
658
|
+
const args = ['--orchestration-id', shard.orchestrationId, '--shard-id', shard.shardId, '--shard-position', String(shard.position)];
|
|
659
|
+
if (options?.planFile !== undefined && options.planFile !== '') args.push('--shard-plan', options.planFile);
|
|
660
|
+
return args;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/** Full remote command for one shard — the exact argv a remote host (e.g. an node-b pod shard) would run. */
|
|
664
|
+
export function remoteShardArgv(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
|
|
665
|
+
return ['bun', 'bin/elanous.mjs', '--test', 'self', 'gate', '--changed', '--shards', String(shard.totalShards), ...remoteShardArgArgs(shard, options)];
|
|
666
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
/** Exclude importer expansion only when non-comment bytes and comment boundaries
|
|
4
|
+
* are identical. The TypeScript parser finds comments within JSDoc that a bare
|
|
5
|
+
* scanner can misread because their prose contains backticks. */
|
|
6
|
+
export function isCommentOnlySourceChange(before: string, after: string, path: string): boolean {
|
|
7
|
+
if (before === after || !/\.(?:[cm]?[jt]sx?)$/.test(path)) return false;
|
|
8
|
+
const kind = /\.(?:[cm]?[jt]sx)$/.test(path) ? ts.ScriptKind.TSX
|
|
9
|
+
: /\.(?:[cm]?js)$/.test(path) ? ts.ScriptKind.JS : ts.ScriptKind.TS;
|
|
10
|
+
const collect = (source: string): { masked: string; comments: string[] } | null => {
|
|
11
|
+
const file = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true, kind);
|
|
12
|
+
if (file.parseDiagnostics.length) return null;
|
|
13
|
+
const ranges = new Map<number, ts.CommentRange>();
|
|
14
|
+
const add = (found: ts.CommentRange[] | undefined) => {
|
|
15
|
+
for (const range of found ?? []) ranges.set(range.pos, range);
|
|
16
|
+
};
|
|
17
|
+
const visit = (node: ts.Node) => {
|
|
18
|
+
add(ts.getLeadingCommentRanges(source, node.getFullStart()));
|
|
19
|
+
add(ts.getTrailingCommentRanges(source, node.getEnd()));
|
|
20
|
+
ts.forEachChild(node, visit);
|
|
21
|
+
};
|
|
22
|
+
visit(file);
|
|
23
|
+
const comments: string[] = [];
|
|
24
|
+
let masked = '';
|
|
25
|
+
let end = 0;
|
|
26
|
+
for (const range of [...ranges.values()].sort((left, right) => left.pos - right.pos)) {
|
|
27
|
+
if (range.pos < end) return null;
|
|
28
|
+
const comment = source.slice(range.pos, range.end);
|
|
29
|
+
comments.push(comment);
|
|
30
|
+
masked += source.slice(end, range.pos) + `\u0000C${range.kind}:${comment.match(/\r\n|\r|\n/g)?.join('') ?? ''}\u0000`;
|
|
31
|
+
end = range.end;
|
|
32
|
+
}
|
|
33
|
+
return { masked: masked + source.slice(end), comments };
|
|
34
|
+
};
|
|
35
|
+
const old = collect(before);
|
|
36
|
+
const current = collect(after);
|
|
37
|
+
if (!old || !current || old.masked !== current.masked || old.comments.length !== current.comments.length) return false;
|
|
38
|
+
const directive = /^(?:\/\/\/|\/\/[#@])|@|(?:eslint|istanbul|coverage|#__PURE__|__NO_SIDE_EFFECTS__)/i;
|
|
39
|
+
// Any unquoted @ may be a TypeScript/JSDoc tag, including newly introduced ones.
|
|
40
|
+
// A backticked example username such as `@example_bot` is prose, not a tag.
|
|
41
|
+
const semanticText = (comment: string) => comment.trim().replace(/`[^`\r\n]*`/g, '');
|
|
42
|
+
let changed = false;
|
|
43
|
+
for (let index = 0; index < old.comments.length; index++) {
|
|
44
|
+
const prior = old.comments[index]!;
|
|
45
|
+
const next = current.comments[index]!;
|
|
46
|
+
if (prior === next) continue;
|
|
47
|
+
changed = true;
|
|
48
|
+
// Ordinary inline block comments and line comments stay in the importer set.
|
|
49
|
+
// This exemption is intentionally limited to JSDoc prose edits.
|
|
50
|
+
if (!prior.startsWith('/**') || !next.startsWith('/**')) return false;
|
|
51
|
+
if (directive.test(semanticText(prior)) || directive.test(semanticText(next))) return false;
|
|
52
|
+
}
|
|
53
|
+
return changed;
|
|
54
|
+
}
|