elanous 0.2.36 → 0.2.37
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 → 8kITumG9GAZ1LwT9POrAR}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 1262.a89bb27a5b2f844e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 1746.3563617ea64023a3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 2002-a43a3f380df873ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 2283.edd9627b7bdfb546.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 2375.bf364c85dbb6f085.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +27 -0
- package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 3199.6a1a9b0e6cd01dc6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2986.45d7652e4f13557e.js → 3578.4e9f9948a9a6f2f4.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +226 -0
- package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +287 -0
- package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7481.39f7a4654907bf6e.js → 4313.76f232c304a15bde.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4337e36d.f42c3b391b3d8f20.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 4383.18e5c54db3a22c88.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3757-180308bc61021b05.js → 4725-34bed25720cc326b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 4931.95cc6dbd230774ca.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5046.7fd5cbd859299448.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +104 -0
- package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +1 -0
- package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 58edce7d.f1b0c72acf13b123.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 5952.294fc574a8625184.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 5f6af561-f90b7a67f4f75d13.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +74 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 6252.240578f10952e091.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 6680.6a693c28aae4cd19.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 6745-5a63492933959dd9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 6819.be5c9c4d67f22922.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → 709a918c.4fd3b4e2a32cb4e3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 7424.c0fe2a595d4232b5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +1 -0
- package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 7867.e8725745ddd1d940.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{6466-92e65a48490b68a9.js → 7893-e444a1b0809cd1e4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{ccae1c4b-0cf414f5eff1b10d.js → 7c5ed21f-f286708e57cf88f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{3840-5825d56d46976a92.js → 8080-40d781e7704d3671.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +77 -0
- package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +1 -0
- package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +286 -0
- package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +79 -0
- package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → 8c58d09b.e8724a299658d86f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 9151.a2c51e93f9156dae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +94 -0
- package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{190.285c832bd9626f8c.js → 958.53a8dcf4729e6997.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-e2de2e59111c9aad.js → page-3337c6a1328c2674.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-f2b2e4bf6e981450.js → page-89acd5d68c0bc560.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2af16e62c12f22df.js → page-fe986fe79b107546.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → d9815f84.4918f682a45a8502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → de8446d3.31b73eb239fecd7b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.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/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/boundary-proof-mapping-audit.ts +88 -0
- 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-failure-census.ts +507 -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/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- 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/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-release.ts +114 -4
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/version-node.ts +81 -12
- 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/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +6 -0
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/self-review-cli.ts +343 -31
- 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/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/capture/tui-self-report.ts +32 -3
- 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/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/release-checklist-read-cli.ts +109 -4
- package/src/cli/release-cli.ts +43 -10
- package/src/cli/self-update.ts +23 -5
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-cli.ts +309 -11
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +97 -13
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- 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/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/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +17 -5
- package/src/graph-wizard/generate.ts +29 -6
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/index.ts +116 -13
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +35 -0
- package/src/llm.ts +123 -11
- 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/tick.ts +49 -4
- 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/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/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/policy/llm-policy.ts +3 -1
- package/src/prompt-enhance/enhance.ts +4 -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/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/landed-but-yellow.ts +93 -12
- package/src/repl/index.ts +8 -0
- 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/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-sweep.ts +241 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +50 -3
- package/src/self-implement/doctor-visit.ts +83 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +64 -1
- package/src/self-implement/gate-cli.ts +93 -9
- package/src/self-implement/gate-remote.ts +28 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +333 -18
- package/src/self-implement/goal-supervisor-fill.ts +75 -26
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +5 -5
- package/src/self-implement/orchestrator.ts +318 -25
- 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 +170 -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 +12 -6
- 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/chat.ts +7 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +4 -0
- package/src/session-runtime/index.ts +9 -1
- package/src/skills/tools/pty.ts +5 -0
- 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/task-agent/actions.ts +199 -4
- 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/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 +21 -11
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +41 -0
- package/src/task-agent/repair-next-move.ts +12 -2
- 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 +158 -13
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +4 -3
- 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-ledger-collect.ts +8 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +50 -4
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +217 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +4 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +258 -4
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/slash/resume.ts +35 -12
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +71 -0
- package/src/tui-client/local-chat-turn.ts +4 -3
- package/src/user-config.ts +19 -1
- 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 +6 -1
- package/src/ux-sim/next-tui-seat-scenarios.ts +124 -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/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/2812ca6a.3b9f4a7a08885744.js +0 -1
- 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/3031-85328a92fcce4da6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3148-98efd4869d660a87.js +0 -1
- 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/379.ee262e37586fe1ae.js +0 -74
- 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/4116.a84a92a2492c080e.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/599.c39c571b6733f2a2.js +0 -41
- 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/6566.926a1d1b7c911442.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/6925.562d532110879886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.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/7784.1f0ac4a16d190cf4.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/8037.e254fd797aa224d1.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/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/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/outputs/page-e7abc34a48a6f71e.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/term/page-c15958835534404b.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/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/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
|
@@ -51,6 +51,16 @@ export interface ShardRunMode {
|
|
|
51
51
|
fixedDistribution?: boolean;
|
|
52
52
|
/** Measured on the executing host; override only for deterministic planning tests. */
|
|
53
53
|
hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number };
|
|
54
|
+
/** Observation after each bundle's first current+baseline attempt; never controls retries or verdict. */
|
|
55
|
+
onShardComplete?: (progress: ShardRunProgress) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ShardRunProgress {
|
|
59
|
+
shardId: string;
|
|
60
|
+
completedShards: number;
|
|
61
|
+
totalShards: number;
|
|
62
|
+
completedFiles: number;
|
|
63
|
+
totalFiles: number;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
function hostResources(): ShardRunMode['hostResources'] | undefined {
|
|
@@ -162,7 +172,7 @@ export function runShardedGateTests(
|
|
|
162
172
|
try { fixed = planFixedGateTestShards(files, count); }
|
|
163
173
|
catch (error) { return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [], reason: String(error), distribution: 'fixed' }; }
|
|
164
174
|
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' };
|
|
175
|
+
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed' };
|
|
166
176
|
}
|
|
167
177
|
const rss = new Map<string, number>();
|
|
168
178
|
const seconds = new Map<string, number>();
|
|
@@ -199,7 +209,7 @@ export function runShardedGateTests(
|
|
|
199
209
|
const fixed = planFixedGateTestShards(files, maxCount);
|
|
200
210
|
debug.log('self-dev.shard', 'host-cap-fixed-fallback', { requested: count, cap: maxCount,
|
|
201
211
|
files: new Set(files).size, reason, measurementFailures: measurementFailures ?? 0 });
|
|
202
|
-
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed-cap-fallback',
|
|
212
|
+
return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed-cap-fallback',
|
|
203
213
|
fallbackReason: reason, ...(measurementFailures ? { measurementFailures } : {}) };
|
|
204
214
|
} catch (error) {
|
|
205
215
|
return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [],
|
|
@@ -232,7 +242,7 @@ export function runShardedGateTests(
|
|
|
232
242
|
requested: count, planned: shards.length, files: new Set(files).size, budgetGiB,
|
|
233
243
|
measurementFailures: measurementFailures ?? 0,
|
|
234
244
|
});
|
|
235
|
-
return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
|
|
245
|
+
return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree, mode.onShardComplete), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
|
|
236
246
|
}
|
|
237
247
|
|
|
238
248
|
/** Shared by the measured and the fixed planner: current + baseline per shard, one retry round, one aggregate. */
|
|
@@ -242,6 +252,7 @@ function runPlannedShards(
|
|
|
242
252
|
baseRef: string,
|
|
243
253
|
run: ShardProcess,
|
|
244
254
|
baselineWorktree: typeof withBaselineWorktree,
|
|
255
|
+
onShardComplete?: ShardRunMode['onShardComplete'],
|
|
245
256
|
): ShardRunResult {
|
|
246
257
|
const attempts: GateShardAttempt[] = [];
|
|
247
258
|
const failureEvidence: ShardFailureEvidence[] = [];
|
|
@@ -256,6 +267,8 @@ function runPlannedShards(
|
|
|
256
267
|
const treeReadable = (() => { try { return statSync(dir).isDirectory(); } catch { return false; } })();
|
|
257
268
|
const atBase = (shard: GateTestShard) => treeReadable ? shard.files.filter((file) => !absentAtBaseline(join(dir, file))) : [...shard.files];
|
|
258
269
|
let pending = shards;
|
|
270
|
+
let completedFiles = 0;
|
|
271
|
+
const totalFiles = new Set(shards.flatMap((shard) => shard.files)).size;
|
|
259
272
|
for (let round = 1; round <= 2 && pending.length; round++) {
|
|
260
273
|
for (const shard of pending) {
|
|
261
274
|
const runSafely = (location: string, selected: readonly string[]): ReturnType<ShardProcess> => {
|
|
@@ -279,6 +292,13 @@ function runPlannedShards(
|
|
|
279
292
|
baselineFiles,
|
|
280
293
|
currentRoot: cwd, baselineRoot: dir,
|
|
281
294
|
});
|
|
295
|
+
if (round === 1 && onShardComplete) {
|
|
296
|
+
completedFiles += shard.files.length;
|
|
297
|
+
try {
|
|
298
|
+
onShardComplete({ shardId: shard.id, completedShards: attempts.length,
|
|
299
|
+
totalShards: shards.length, completedFiles, totalFiles });
|
|
300
|
+
} catch { /* progress is observation only */ }
|
|
301
|
+
}
|
|
282
302
|
}
|
|
283
303
|
const retry = new Set(aggregateGateTestShards(shards, attempts).retryShardIds);
|
|
284
304
|
pending = shards.filter((shard) => retry.has(shard.id));
|
|
@@ -360,3 +380,30 @@ export function runBunShardWithSpawn(cwd: string, files: readonly string[], spaw
|
|
|
360
380
|
rmSync(dir, { recursive: true, force: true });
|
|
361
381
|
}
|
|
362
382
|
}
|
|
383
|
+
|
|
384
|
+
/** GATE-REMOTE-SHARD-PLAN — identity of one remote shard. files/introducedFiles are optional: a caller that only relays
|
|
385
|
+
* identity (CLI wiring) passes none, while a planner-produced shard carries its file-level attribution. */
|
|
386
|
+
export interface RemoteShardSpec {
|
|
387
|
+
orchestrationId: string;
|
|
388
|
+
shardId: string;
|
|
389
|
+
totalShards: number;
|
|
390
|
+
position: number;
|
|
391
|
+
files?: readonly string[];
|
|
392
|
+
introducedFiles?: readonly string[];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** The identity slice that rides a remote gate command line — validated so a dropped flag fails loudly, not silently. */
|
|
396
|
+
export function remoteShardArgArgs(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
|
|
397
|
+
if (!shard.orchestrationId.trim()) throw new Error('orchestration id must be non-empty');
|
|
398
|
+
if (!shard.shardId.trim()) throw new Error('shard id must be non-empty');
|
|
399
|
+
if (!Number.isSafeInteger(shard.totalShards) || shard.totalShards < 1) throw new Error('shard total must be a positive integer');
|
|
400
|
+
if (!Number.isSafeInteger(shard.position) || shard.position < 1) throw new Error('shard position must be a positive integer');
|
|
401
|
+
const args = ['--orchestration-id', shard.orchestrationId, '--shard-id', shard.shardId, '--shard-position', String(shard.position)];
|
|
402
|
+
if (options?.planFile !== undefined && options.planFile !== '') args.push('--shard-plan', options.planFile);
|
|
403
|
+
return args;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/** Full remote command for one shard — the exact argv a remote host (e.g. an node-b pod shard) would run. */
|
|
407
|
+
export function remoteShardArgv(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
|
|
408
|
+
return ['bun', 'bin/elanous.mjs', '--test', 'self', 'gate', '--changed', '--shards', String(shard.totalShards), ...remoteShardArgArgs(shard, options)];
|
|
409
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
|
|
1
3
|
import { debug } from '../debug/log.js';
|
|
4
|
+
import { loadReviewRoundBrief, type ReviewRoundBrief } from './review-round-brief.js';
|
|
2
5
|
import { findIncidentPrecedents, type IncidentPrecedent } from '../harness/harness-incidents.js';
|
|
3
6
|
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
4
7
|
import {
|
|
@@ -16,6 +19,42 @@ export function doctorVisitIncidentRoot(): string {
|
|
|
16
19
|
return elanousStateRoot();
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
export interface DoctorReviewPrMetadata { headRefOid: string; body: string; files: string[]; comments?: Array<{ body: string; author: string }> }
|
|
23
|
+
|
|
24
|
+
/** Fetch only the metadata needed to anchor a saved review to the current PR head. */
|
|
25
|
+
export function readDoctorReviewPr(pr: number): DoctorReviewPrMetadata {
|
|
26
|
+
const result = spawnSync('gh', ['pr', 'view', String(pr), '--json', 'headRefOid,body,files,author,comments'], {
|
|
27
|
+
encoding: 'utf8', timeout: 30_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER, stdio: ['ignore', 'pipe', 'pipe'],
|
|
28
|
+
});
|
|
29
|
+
if (result.error || result.status !== 0) throw new Error(`PR #${pr} unavailable: ${result.error?.message ?? result.stderr?.trim() ?? 'gh failed'}`);
|
|
30
|
+
const data = JSON.parse(result.stdout) as { headRefOid?: unknown; body?: unknown; files?: unknown; author?: { login?: unknown }; comments?: unknown };
|
|
31
|
+
if (typeof data.headRefOid !== 'string' || !/^[a-f0-9]{40}$/i.test(data.headRefOid)) throw new Error('PR headRefOid is missing or invalid');
|
|
32
|
+
return {
|
|
33
|
+
headRefOid: data.headRefOid,
|
|
34
|
+
body: typeof data.body === 'string' ? data.body : '',
|
|
35
|
+
files: Array.isArray(data.files) ? data.files.flatMap((file: unknown) => {
|
|
36
|
+
if (typeof file === 'string') return [file];
|
|
37
|
+
if (file && typeof file === 'object' && typeof (file as { path?: unknown }).path === 'string') return [(file as { path: string }).path];
|
|
38
|
+
return [];
|
|
39
|
+
}) : [],
|
|
40
|
+
comments: typeof data.author?.login === 'string' && Array.isArray(data.comments) ? data.comments.flatMap((comment: unknown) => {
|
|
41
|
+
if (!comment || typeof comment !== 'object') return [];
|
|
42
|
+
const item = comment as { body?: unknown; author?: { login?: unknown } };
|
|
43
|
+
const login = item.author?.login;
|
|
44
|
+
return typeof item.body === 'string' && typeof login === 'string' && login === data.author?.login
|
|
45
|
+
? [{ body: item.body, author: login }] : [];
|
|
46
|
+
}) : [],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Doctor's saved-review view; never records a run-ledger visit for a PR. */
|
|
51
|
+
export function readDoctorReviewBrief(pr: number, read: (pr: number) => DoctorReviewPrMetadata = readDoctorReviewPr, reviewResultsDir?: string): ReviewRoundBrief {
|
|
52
|
+
if (!Number.isSafeInteger(pr) || pr <= 0) throw new Error('PR number must be a positive integer');
|
|
53
|
+
const metadata = read(pr);
|
|
54
|
+
return loadReviewRoundBrief({ pr, head: metadata.headRefOid, body: metadata.body, changedFiles: metadata.files, comments: metadata.comments?.map((comment) => comment.body),
|
|
55
|
+
...(reviewResultsDir ? { reviewResultsDir } : {}) });
|
|
56
|
+
}
|
|
57
|
+
|
|
19
58
|
/** DOCTOR-VISIT 증상 닫힌 목록 — 이 밖의 값은 기록·조회 모두 거부한다. */
|
|
20
59
|
export const DOCTOR_SYMPTOMS = [
|
|
21
60
|
'admit-starved',
|
|
@@ -180,8 +219,52 @@ export function recordTaskAgentNeedsOwnerVisit(input: {
|
|
|
180
219
|
return { status: outcome.result ?? 'missing-ledger' };
|
|
181
220
|
}
|
|
182
221
|
|
|
222
|
+
/** A parent stop that needs an owner records one shadow visit per stop, without running a prescription. */
|
|
223
|
+
export function recordParentNeedsOwnerVisit(input: {
|
|
224
|
+
runId: string;
|
|
225
|
+
stopKey: string;
|
|
226
|
+
evidence: string;
|
|
227
|
+
dir?: string;
|
|
228
|
+
}): { status: 'missing-ledger' | 'recorded' | 'already-recorded' } {
|
|
229
|
+
const outcome = appendRunLedgerEntryChecked(input.runId, (entries) => {
|
|
230
|
+
if (entries === null) return { append: false, result: 'missing-ledger' as const };
|
|
231
|
+
if (entries.some((entry) => entry.event === 'doctor-visit' && entry.data.from === 'parent'
|
|
232
|
+
&& entry.data.symptom === 'needs-owner' && entry.data.stopKey === input.stopKey)) {
|
|
233
|
+
return { append: false, result: 'already-recorded' as const };
|
|
234
|
+
}
|
|
235
|
+
return { append: true, entry: {
|
|
236
|
+
runId: input.runId,
|
|
237
|
+
timestamp: new Date().toISOString(),
|
|
238
|
+
event: 'doctor-visit',
|
|
239
|
+
data: { from: 'parent', symptom: 'needs-owner', stopKey: input.stopKey, evidence: input.evidence },
|
|
240
|
+
} };
|
|
241
|
+
}, input.dir);
|
|
242
|
+
if (outcome.appended) {
|
|
243
|
+
debug.log('run-doctor', 'visit', { runId: input.runId, from: 'parent', symptom: 'needs-owner', stopKey: input.stopKey });
|
|
244
|
+
return { status: 'recorded' };
|
|
245
|
+
}
|
|
246
|
+
if (outcome.result === null) throw new Error(`run-ledger-write-refused: ${input.runId}`);
|
|
247
|
+
return { status: outcome.result };
|
|
248
|
+
}
|
|
249
|
+
|
|
183
250
|
export type ReadDoctorVisitsOptions = RunLedgerLookupOptions;
|
|
184
251
|
|
|
252
|
+
/** Project logged review briefs into status without changing the run-ledger schema. Keep the latest observation per PR. */
|
|
253
|
+
export function doctorReviewVisits(events: readonly { timestamp?: string; sequence?: number; runId?: string; key?: string; evidence?: string }[]): (Omit<DoctorVisit, 'runId'> & { runId?: string })[] {
|
|
254
|
+
const seenPrs = new Set<string>();
|
|
255
|
+
return [...events].sort((left, right) => {
|
|
256
|
+
const leftAt = left.timestamp ? Date.parse(left.timestamp) : 0;
|
|
257
|
+
const rightAt = right.timestamp ? Date.parse(right.timestamp) : 0;
|
|
258
|
+
return rightAt - leftAt || (right.sequence ?? 0) - (left.sequence ?? 0) || String(right.key ?? '').localeCompare(String(left.key ?? ''));
|
|
259
|
+
}).flatMap((event) => {
|
|
260
|
+
const pr = /^(\d+)(?::|$)/.exec(event.key ?? '')?.[1];
|
|
261
|
+
if (pr && seenPrs.has(pr)) return [];
|
|
262
|
+
if (pr) seenPrs.add(pr);
|
|
263
|
+
return [{ ...(event.runId ? { runId: event.runId } : {}), from: 'seat' as const, symptom: 'review-loop' as const,
|
|
264
|
+
...(event.evidence ? { evidence: event.evidence } : {}), ...(event.timestamp ? { timestamp: event.timestamp } : {}) }];
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
185
268
|
/** `runId` 원장이 조회 범위 안에 있는가 — `doctor status --run` 이 없는 런을 «0건»으로 삼키지 않게 한다. */
|
|
186
269
|
export function doctorVisitRunExists(runId: string, options: ReadDoctorVisitsOptions = {}): boolean {
|
|
187
270
|
return lookupRunLedger(runId, options).matches.length > 0;
|
|
@@ -85,6 +85,7 @@ export interface GateArtifactSummary extends GateArtifactCounts {
|
|
|
85
85
|
verdict: string | null;
|
|
86
86
|
/** 판정 줄(`tests: …` / `[gate-baseline] …` / `shards: unmeasured (…)`) 그대로. */
|
|
87
87
|
verdictLine?: string;
|
|
88
|
+
timeoutRechecks?: readonly { name: string; file: string; result: 'pass' | 'timeout' | 'failure' | 'unknown'; elapsedMs: number; rawResultLine: string }[];
|
|
88
89
|
exitCode: number;
|
|
89
90
|
/** 정수 칸 중 하나라도 null 일 때만 — 왜 못 셌나(한 줄). */
|
|
90
91
|
countsUnavailableReason?: string;
|
|
@@ -129,6 +130,7 @@ export interface GateArtifactInput {
|
|
|
129
130
|
testFiles: readonly string[];
|
|
130
131
|
verdict: string | null;
|
|
131
132
|
verdictLine?: string;
|
|
133
|
+
timeoutRechecks?: readonly { name: string; file: string; result: 'pass' | 'timeout' | 'failure' | 'unknown'; elapsedMs: number; rawResultLine: string }[];
|
|
132
134
|
exitCode: number;
|
|
133
135
|
/** 판정 정수(못 센 칸은 null ⊕ countsUnavailableReason). 안 주면 다섯 다 null · 이유 'not recorded' — 칸은 «늘» 쓴다. */
|
|
134
136
|
counts?: GateArtifactCounts;
|
|
@@ -219,6 +221,7 @@ export function writeGateArtifacts(input: GateArtifactInput): { summaryPath: str
|
|
|
219
221
|
shardsDetail,
|
|
220
222
|
verdict: input.verdict,
|
|
221
223
|
...(input.verdictLine !== undefined ? { verdictLine: input.verdictLine } : {}),
|
|
224
|
+
...(input.timeoutRechecks ? { timeoutRechecks: input.timeoutRechecks } : {}),
|
|
222
225
|
exitCode: input.exitCode,
|
|
223
226
|
introduced: counts.introduced,
|
|
224
227
|
preexisting: counts.preexisting,
|
|
@@ -388,8 +391,9 @@ export function importRemoteGateArtifacts(dir: string, files: Map<string, Buffer
|
|
|
388
391
|
writeFileSync(run.resultPath, `${JSON.stringify(result, null, 2)}\n`);
|
|
389
392
|
};
|
|
390
393
|
for (const shard of summary.shardsDetail) { relocate(shard?.current); relocate(shard?.baseline); }
|
|
391
|
-
//
|
|
392
|
-
for (const [name, bytes] of files) if (name.endsWith('.failure.json')
|
|
394
|
+
// Optional observations stay optional for older remote commits. Neither changes the gate verdict.
|
|
395
|
+
for (const [name, bytes] of files) if ((name === 'progress.json' || name.endsWith('.failure.json'))
|
|
396
|
+
&& artifactNamePattern.test(name)) writeFileSync(join(dir, name), bytes);
|
|
393
397
|
summary.remoteHost = host;
|
|
394
398
|
writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
|
|
395
399
|
return { summaryPath, junitFiles };
|
|
@@ -9,7 +9,7 @@ import type { GitRunResult } from '../git-fs/retry.js';
|
|
|
9
9
|
import { linkWorktreeDependencies, worktreeAddTimeoutForRepo } from '../git-fs/worktree.js';
|
|
10
10
|
import { reapStaleGateWorktrees } from './gate-baseline-reap.js';
|
|
11
11
|
|
|
12
|
-
export type GateFailureAttribution = 'introduced' | 'preexisting' | 'unknown' | 'precondition-unmet' | 'flaky-timeout' | 'flaky-rerun';
|
|
12
|
+
export type GateFailureAttribution = 'introduced' | 'preexisting' | 'unknown' | 'precondition-unmet' | 'flaky-timeout' | 'flaky-rerun' | 'timeout-recheck-passed';
|
|
13
13
|
export type GateBaselinePresence = 'present' | 'missing' | 'unknown';
|
|
14
14
|
export type TimeoutVariability = 'may-vary' | 'same' | 'unknown';
|
|
15
15
|
|
|
@@ -72,6 +72,16 @@ export interface GateBaselineReport extends GateBaselineSummary {
|
|
|
72
72
|
files: string[];
|
|
73
73
|
baselineStatus: BaselineProcessStatus;
|
|
74
74
|
log: string;
|
|
75
|
+
timeoutRechecks?: TimeoutRecheckRecord[];
|
|
76
|
+
timeoutRecheckPassed?: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface TimeoutRecheckRecord {
|
|
80
|
+
name: string;
|
|
81
|
+
file: string;
|
|
82
|
+
result: 'pass' | 'timeout' | 'failure' | 'unknown';
|
|
83
|
+
elapsedMs: number;
|
|
84
|
+
rawResultLine: string;
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
interface GateTestCountChange {
|
|
@@ -697,6 +707,9 @@ function summarizeGateBaseline(failures: readonly GateTestFailure[]): GateBaseli
|
|
|
697
707
|
if (failure.attribution === 'flaky-rerun') {
|
|
698
708
|
return { ...withPresence, flakyRerun: withPresence.flakyRerun + 1 };
|
|
699
709
|
}
|
|
710
|
+
if (failure.attribution === 'timeout-recheck-passed') {
|
|
711
|
+
return withPresence;
|
|
712
|
+
}
|
|
700
713
|
const withTimeoutRegression = failure.timeoutRegression === 'passed-at-base'
|
|
701
714
|
? { ...withPresence, timeoutPassedAtBase: withPresence.timeoutPassedAtBase + 1 }
|
|
702
715
|
: withPresence;
|
|
@@ -722,6 +735,51 @@ export function rerunBunSingleTest(cwd: string, file: string, testName: string,
|
|
|
722
735
|
return classifyBunSingleTestRerun(result);
|
|
723
736
|
}
|
|
724
737
|
|
|
738
|
+
/** A standalone timeout-only retry is allowed only when every introduced failure is explicitly a Bun timeout. */
|
|
739
|
+
export function recheckTimeoutOnlyIntroducedFailures(
|
|
740
|
+
cwd: string,
|
|
741
|
+
report: GateBaselineReport,
|
|
742
|
+
run: (cwd: string, file: string, name: string, timeoutMs: number) => { observation?: TimeoutRerunObservation; elapsedMs: number; output: string } = runTimeoutRecheck,
|
|
743
|
+
): GateBaselineReport {
|
|
744
|
+
const eligible = report.failures.length > 0
|
|
745
|
+
&& report.introduced === report.failures.length
|
|
746
|
+
&& report.failures.every((failure) => failure.attribution === 'introduced' && !!failure.file
|
|
747
|
+
&& /\bthis test timed out after \d+ms\b/i.test(failure.diagnostic ?? ''));
|
|
748
|
+
if (!eligible) return report;
|
|
749
|
+
const records: TimeoutRecheckRecord[] = [];
|
|
750
|
+
const failures = report.failures.map((failure) => {
|
|
751
|
+
if (!failure.file) return failure;
|
|
752
|
+
const prefix = `${failure.file} > `;
|
|
753
|
+
const name = failure.name.startsWith(prefix) ? failure.name.slice(prefix.length) : failure.name;
|
|
754
|
+
const { observation, elapsedMs, output } = run(cwd, failure.file, name, 60_000);
|
|
755
|
+
const result = observation ?? 'unknown';
|
|
756
|
+
const record: TimeoutRecheckRecord = {
|
|
757
|
+
name: failure.name, file: failure.file, result, elapsedMs,
|
|
758
|
+
rawResultLine: flattenControlChars(redactSecretText(output)).slice(-500),
|
|
759
|
+
};
|
|
760
|
+
records.push(record);
|
|
761
|
+
debug.log('gate.baseline', 'timeout-recheck', record);
|
|
762
|
+
return result === 'pass' ? { ...failure, attribution: 'timeout-recheck-passed' as const } : failure;
|
|
763
|
+
});
|
|
764
|
+
return {
|
|
765
|
+
...report,
|
|
766
|
+
...summarizeGateBaseline(failures),
|
|
767
|
+
failures,
|
|
768
|
+
timeoutRechecks: records,
|
|
769
|
+
timeoutRecheckPassed: failures.filter((failure) => failure.attribution === 'timeout-recheck-passed').length,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function runTimeoutRecheck(cwd: string, file: string, name: string, timeoutMs: number): { observation?: TimeoutRerunObservation; elapsedMs: number; output: string } {
|
|
774
|
+
const started = Date.now();
|
|
775
|
+
const result = runIsolatedBunTest(cwd, ['--timeout', String(timeoutMs), '--test-name-pattern', buildBunSingleTestPattern(name), file], timeoutMs + 10_000);
|
|
776
|
+
return {
|
|
777
|
+
observation: classifyBunSingleTestRerun(result),
|
|
778
|
+
elapsedMs: Date.now() - started,
|
|
779
|
+
output: `${String(result.stdout ?? '')}\n${String(result.stderr ?? '')}`,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
|
|
725
783
|
/** `introduced` 재실행 상한. 초과분은 돌리지 않고 보고서에 남긴다. 부하로 건너뛰지 않는다. */
|
|
726
784
|
export const INTRODUCED_RERUN_CAP = 8;
|
|
727
785
|
|
|
@@ -1512,6 +1570,7 @@ export function formatGateBaselineNote(report: GateBaselineReport, unrunImporter
|
|
|
1512
1570
|
+ `, unknown=${report.unknown}, precondition-unmet=${report.preconditionUnmet}`
|
|
1513
1571
|
+ (report.timedOut > 0 ? `, timed-out=${report.timedOut}` : '')
|
|
1514
1572
|
+ (report.flakyRerun > 0 ? `, flaky-rerun=${report.flakyRerun}` : '')
|
|
1573
|
+
+ ((report.timeoutRecheckPassed ?? 0) > 0 ? `, timeout-recheck-passed=${report.timeoutRecheckPassed}` : '')
|
|
1515
1574
|
+ (runId ? `, run=${runId}` : '')
|
|
1516
1575
|
+ (report.missingAtBase > 0 ? `, missing-at-base=${report.missingAtBase}` : '');
|
|
1517
1576
|
const lines = report.failures.map((failure) => `- ${failure.attribution}: ${failure.name}`
|
|
@@ -1532,10 +1591,14 @@ export function formatGateBaselineNote(report: GateBaselineReport, unrunImporter
|
|
|
1532
1591
|
: report.rerunNotRun > 0
|
|
1533
1592
|
? `\n[gate-baseline] rerun not-run=${report.rerunNotRun}`
|
|
1534
1593
|
: '';
|
|
1594
|
+
const timeoutRecheckLines = report.timeoutRechecks?.length
|
|
1595
|
+
? `\n[gate.baseline.timeout-recheck] ${report.timeoutRechecks.map((item) => `${item.name}: ${item.result} elapsed=${item.elapsedMs}ms · ${item.rawResultLine}`).join('\n')}`
|
|
1596
|
+
: '';
|
|
1535
1597
|
return `${head}\n${lines.join('\n')}\n${report.log}`
|
|
1536
1598
|
+ timedOutLine
|
|
1537
1599
|
+ mayVaryNonTimeoutLine
|
|
1538
1600
|
+ rerunLine
|
|
1601
|
+
+ timeoutRecheckLines
|
|
1539
1602
|
+ (report.preexisting > 0 ? '\n⚠️ preexisting 실패는 base에서도 재현됨 — 이 PR의 책임이 아니다.' : '');
|
|
1540
1603
|
}
|
|
1541
1604
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { existsSync, lstatSync, mkdtempSync, readFileSync, realpathSync } from 'node:fs';
|
|
1
|
+
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { tmpdir } from 'node:os';
|
|
3
4
|
import { spawnSync } from 'node:child_process';
|
|
4
5
|
import { join } from 'node:path/posix';
|
|
@@ -12,7 +13,7 @@ import { runIosUnitTestGate } from '../../scripts/ci-ios-unit-tests.js';
|
|
|
12
13
|
import { runPwaBuildGate } from '../../scripts/ci-pwa-build-gate.js';
|
|
13
14
|
import { runMockModuleRestoreGate } from '../../scripts/ci-mock-module-restore-gate.js';
|
|
14
15
|
import { parseReviewDepthFromFilesJson } from '../agent-mission/review-depth.js';
|
|
15
|
-
import { buildGateBaselineReport, calculateGateTestCountChange, formatGateBaselineNote, formatGateTestCountNote, isGateTestFile, runGateBaseline, type BaselineProcessResult, type BaselineProcessStatus, type GateTestFailure } from './gate-baseline.js';
|
|
16
|
+
import { buildGateBaselineReport, calculateGateTestCountChange, formatGateBaselineNote, formatGateTestCountNote, isGateTestFile, recheckTimeoutOnlyIntroducedFailures, runGateBaseline, type BaselineProcessResult, type BaselineProcessStatus, type GateTestFailure, type TimeoutRecheckRecord, type TimeoutRerunObservation } from './gate-baseline.js';
|
|
16
17
|
import { resolveGateScope } from './gate-scope.js';
|
|
17
18
|
import { publicExposureFiles, runExposeGate } from './expose-gate.js';
|
|
18
19
|
import { getUserConfig } from '../user-config.js';
|
|
@@ -26,7 +27,8 @@ import {
|
|
|
26
27
|
overlapWithCurrentChanges,
|
|
27
28
|
} from '../cli/pr-granularity.js';
|
|
28
29
|
import { listWorktrees } from '../git-fs/worktree.js';
|
|
29
|
-
import { runShardedGateTests, writeShardFailureEvidence } from '../self-dev/shard-run.js';
|
|
30
|
+
import { runShardedGateTests, writeShardFailureEvidence, remoteShardArgv, type ShardRunProgress } from '../self-dev/shard-run.js';
|
|
31
|
+
import { planGateRemoteShards, shardPlanOrchestrationId, type GateRemoteShard } from '../self-dev/shard-plan.js';
|
|
30
32
|
import { parseGateScenario, readGateScenarioFile } from './gate-scenario.js';
|
|
31
33
|
import { isGateSpawnLaneFile } from '../self-dev/spawn-lane-files.js';
|
|
32
34
|
import { defaultGateEnvKey, defaultRevResolver, resolveArtifactDir, writeGateArtifacts, type GateArtifactCounts, type GateArtifactsUnavailable, type RevResolver } from './gate-artifacts.js';
|
|
@@ -99,7 +101,11 @@ interface SelfGateCliDeps {
|
|
|
99
101
|
readFile?: (path: string) => string | undefined;
|
|
100
102
|
runTests?: (cwd: string, files: readonly string[]) => ProcessResult;
|
|
101
103
|
runBaseline?: (cwd: string, files: readonly string[], baseRef: string) => BaselineProcessResult;
|
|
104
|
+
runTimeoutRecheck?: (cwd: string, file: string, name: string, timeoutMs: number) => { observation?: TimeoutRerunObservation; elapsedMs: number; output: string };
|
|
102
105
|
runShards?: typeof runShardedGateTests;
|
|
106
|
+
/** Test seam for the live progress line. */
|
|
107
|
+
writeProgressStderr?: (line: string) => void;
|
|
108
|
+
now?: () => number;
|
|
103
109
|
runIsolationGate?: (out: GateOutput) => number;
|
|
104
110
|
runMockModuleRestoreGate?: (out: GateOutput) => number;
|
|
105
111
|
/** 모델 이름 하드코딩 래칫(🅕 #20521) — `pr land` 만 물고 하니스 무인 병합은 안 물면 위반이 main 에 들어가 남의 착지를 막는다(🅣 2026-09-25). */
|
|
@@ -131,6 +137,7 @@ interface GateArtifactCapture {
|
|
|
131
137
|
/** `unrun importer tests: N` 의 N — 색인 조회 실패면 null(그 이유가 importerLookupFailed). */
|
|
132
138
|
unrunImporters?: number | null;
|
|
133
139
|
importerLookupFailed?: string;
|
|
140
|
+
timeoutRechecks?: readonly TimeoutRecheckRecord[];
|
|
134
141
|
}
|
|
135
142
|
|
|
136
143
|
/** SIDE-VERIFY ③ — summary 정수 칸: 게이트가 이미 낸 `result.baseline` ⊕ `unrunImporterTotal` 을 «옮기기만» 한다.
|
|
@@ -388,7 +395,9 @@ export function observePrFileOverlap(
|
|
|
388
395
|
return { ok: false as const, out: '', err: error instanceof Error ? error.message : String(error) };
|
|
389
396
|
}
|
|
390
397
|
};
|
|
391
|
-
|
|
398
|
+
// The resolved base range is the complete scope; a time cutoff can hide a
|
|
399
|
+
// just-created commit when a gate shard is slow.
|
|
400
|
+
const commits = collectBaseLandingCommits(run, cwd, { since: null, baseRef: `${baseOid}..${baseRefName}` });
|
|
392
401
|
if (commits === null) return { status: 'unavailable', reason: 'git log failed' };
|
|
393
402
|
const overlaps = overlapWithCurrentChanges(commits, files);
|
|
394
403
|
return overlaps.length > 0
|
|
@@ -588,6 +597,24 @@ export function formatUnrunImporterTests(importerTestsNotRun: NonNullable<Return
|
|
|
588
597
|
return `unrun importer tests: ${importerTestsNotRun.total}${files}; unresolved relative specifiers: ${importerTestsNotRun.unresolvedRelativeSpecifiers}`;
|
|
589
598
|
}
|
|
590
599
|
|
|
600
|
+
/** gate 출력 한 줄에 실리는 미등재 spawn-lane 시험의 최대 표시 수 — 실측 드리프트(57건)를 전부 나열하면
|
|
601
|
+
* «읽히지 않는 소음»이 된다(`formatUnrunImporterTests` 의 잘림 정책과 같은 취지). */
|
|
602
|
+
const UNLISTED_SPAWN_LANE_DISPLAY_LIMIT = 10;
|
|
603
|
+
|
|
604
|
+
/** ⛔⭐ 소비자 배선(무인 리뷰 must-fix) — `resolveGateScope` 이 채우는 `runtimeEdgeImpact` 를 읽는 곳이
|
|
605
|
+
* 없으면 그 측정은 어디에도 드러나지 않는다. 정책은 형제들과 같다 — ***「보고한다. 막지 않는다.」***
|
|
606
|
+
* 손으로 관리하는 `GATE_SPAWN_LANE_FILES` 가 실측에서 빠뜨린 spawn-lane 시험을 알린다. */
|
|
607
|
+
export function formatUnlistedSpawnLaneTests(impact: ReturnType<typeof resolveGateScope>['runtimeEdgeImpact']): string {
|
|
608
|
+
if (!impact) return 'unlisted spawn-lane tests: (not measured — no importer index)';
|
|
609
|
+
if (!impact.measured) return 'unlisted spawn-lane tests: (not measured)';
|
|
610
|
+
const total = impact.unlistedSpawnLaneTests.length;
|
|
611
|
+
if (total === 0) return 'unlisted spawn-lane tests: 0';
|
|
612
|
+
const shown = impact.unlistedSpawnLaneTests.slice(0, UNLISTED_SPAWN_LANE_DISPLAY_LIMIT);
|
|
613
|
+
const truncated = total > shown.length ? `, showing ${shown.length}/${total}` : '';
|
|
614
|
+
return `unlisted spawn-lane tests: ${total} (${shown.join(', ')}${truncated})`
|
|
615
|
+
+ ' ⚠️ GATE_SPAWN_LANE_FILES 가 빠뜨린 실측 spawn-lane 시험 — 「보고만 한다. 막지 않는다.」';
|
|
616
|
+
}
|
|
617
|
+
|
|
591
618
|
export function formatPartialObservationNote(unrunImporterTotal: number, note: string): string {
|
|
592
619
|
if (unrunImporterTotal <= 0) return note;
|
|
593
620
|
return `partial observation: ${unrunImporterTotal} unrun importer tests; ${note}`;
|
|
@@ -756,6 +783,7 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
|
|
|
756
783
|
testFiles: capture.testFiles ?? result.testFiles,
|
|
757
784
|
verdict: capture.verdict ?? null,
|
|
758
785
|
...(capture.verdictLine !== undefined ? { verdictLine: capture.verdictLine } : {}),
|
|
786
|
+
...(capture.timeoutRechecks ? { timeoutRechecks: capture.timeoutRechecks } : {}),
|
|
759
787
|
exitCode: result.exitCode,
|
|
760
788
|
counts: counts.counts,
|
|
761
789
|
...(counts.reason !== undefined ? { countsUnavailableReason: counts.reason } : {}),
|
|
@@ -770,6 +798,31 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
|
|
|
770
798
|
}
|
|
771
799
|
}
|
|
772
800
|
|
|
801
|
+
/** A completed bundle is observed immediately, before the synchronous runner returns. Each sink is best effort. */
|
|
802
|
+
function shardProgressObserver(cwd: string, options: SelfGateCliOptions, deps: SelfGateCliDeps): (progress: ShardRunProgress) => void {
|
|
803
|
+
const now = deps.now ?? Date.now;
|
|
804
|
+
const startedAt = now();
|
|
805
|
+
return (progress) => {
|
|
806
|
+
const elapsedMs = Math.max(0, now() - startedAt);
|
|
807
|
+
const estimatedRemainingMs = progress.completedShards > 0
|
|
808
|
+
? Math.round(elapsedMs * (progress.totalShards - progress.completedShards) / progress.completedShards) : null;
|
|
809
|
+
const snapshot = { ...progress, elapsedMs, estimatedRemainingMs };
|
|
810
|
+
const line = `gate shard progress: bundles ${progress.completedShards}/${progress.totalShards} · files ${progress.completedFiles}/${progress.totalFiles} · elapsed ${Math.round(elapsedMs / 1000)}s · remaining ~${estimatedRemainingMs === null ? '?' : Math.round(estimatedRemainingMs / 1000) + 's'}\n`;
|
|
811
|
+
try { (deps.writeProgressStderr ?? ((value) => { process.stderr.write(value); }))(line); } catch { /* observation only */ }
|
|
812
|
+
try { debug.log('gate.cli', 'shard-progress', snapshot); } catch { /* observation only */ }
|
|
813
|
+
if (!options.artifactDir?.trim()) return;
|
|
814
|
+
let temporary: string | undefined;
|
|
815
|
+
try {
|
|
816
|
+
const dir = resolveArtifactDir(options.artifactDir, cwd);
|
|
817
|
+
mkdirSync(dir, { recursive: true });
|
|
818
|
+
temporary = join(dir, `.progress.${process.pid}.${randomUUID()}.tmp`);
|
|
819
|
+
writeFileSync(temporary, `${JSON.stringify(snapshot, null, 2)}\n`);
|
|
820
|
+
renameSync(temporary, join(dir, 'progress.json'));
|
|
821
|
+
} catch { /* artifact failure must not affect the gate verdict */ }
|
|
822
|
+
finally { if (temporary) { try { rmSync(temporary, { force: true }); } catch { /* observation only */ } } }
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
|
|
773
826
|
function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: SelfGateCliDeps, capture: GateArtifactCapture): SelfGateCliResult {
|
|
774
827
|
if (options.base && options.pr) throw new Error('use either --base <ref> or --pr <number>, not both');
|
|
775
828
|
if (options.shards !== undefined && (!Number.isSafeInteger(options.shards) || options.shards < 1)) throw new Error('invalid --shards count');
|
|
@@ -803,6 +856,9 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
803
856
|
// 🚨 러너 우주 «밖» — 형제들과 같은 정책으로 «말만» 한다(`OBS-T418`).
|
|
804
857
|
formatUnrunnableChangeKinds(selection.files),
|
|
805
858
|
formatUnrunImporterTests(importerTestsNotRun, lookupFailed),
|
|
859
|
+
// ⛔⭐ 무인 리뷰 must-fix — 죽은 필드 배선: `resolveGateScope` 이 채운 `runtimeEdgeImpact` 을
|
|
860
|
+
// 실제로 읽어 출력하는 소비자(이 줄이 없으면 그 측정은 어디에도 드러나지 않는다).
|
|
861
|
+
formatUnlistedSpawnLaneTests(scope.runtimeEdgeImpact),
|
|
806
862
|
`caller tests: ${lookupFailed ? `lookup failed (${lookupFailed})` : scope.callerTests.map(({ file, reasons }) => `${file} (${reasons.join('+')})`).join(', ') || (routeIndex?.lookupFailures.length ? 'route lookup incomplete' : '(none)')}`,
|
|
807
863
|
...(routeIndex?.lookupFailures.length ? [`⚠️ caller route base lookup failed — unmeasured: ${routeIndex.lookupFailures.map(({ source, reason }) => `${source} (${reason})`).join(', ')}`] : []),
|
|
808
864
|
...(callerTestsOverflow.length ? [`⚠️ caller test cap exceeded — not run: ${callerTestsOverflow.map(({ file, reasons }) => `${file} (${reasons.join('+')})`).join(', ')}`] : []),
|
|
@@ -854,9 +910,10 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
854
910
|
const spawnFileCount = testFiles.filter(isGateSpawnLaneFile).length;
|
|
855
911
|
const shardCount = options.shards ?? (Math.min(3, spawnFileCount) + Number(testFiles.length > spawnFileCount));
|
|
856
912
|
const runShards = deps.runShards ?? runShardedGateTests;
|
|
913
|
+
const onShardComplete = shardProgressObserver(cwd, options, deps);
|
|
857
914
|
const sharded = options.fixedShardDistribution
|
|
858
|
-
? runShards(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, { fixedDistribution: true })
|
|
859
|
-
: runShards(cwd, testFiles, selection.baseRef, shardCount);
|
|
915
|
+
? runShards(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, { fixedDistribution: true, onShardComplete })
|
|
916
|
+
: runShards(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, { onShardComplete });
|
|
860
917
|
capture.sharded = sharded;
|
|
861
918
|
capture.verdict = sharded.aggregate.status;
|
|
862
919
|
lines.push(`shards: ${sharded.shards.length} (${sharded.shards.map((shard) => `${shard.id}=${shard.files.join(',')}`).join('; ')})${sharded.expandedFrom !== undefined ? ` · RSS 예산상 ${sharded.expandedFrom}→${sharded.shards.length} 자동 확장` : ''}${sharded.measurementFailures ? ` · 측정 실패 ${sharded.measurementFailures}` : ''}${options.fixedShardDistribution ? ' · 고정 분배(사전 측정 없음)' : ''}${sharded.distribution === 'fixed-cap-fallback' ? ` · 호스트 상한 자동 고정 분배(${sharded.fallbackReason})` : ''}`);
|
|
@@ -897,7 +954,15 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
897
954
|
capture.unmeasuredReason = unmeasuredReason;
|
|
898
955
|
}
|
|
899
956
|
else if (aggregate.report) {
|
|
900
|
-
const report = aggregate.report;
|
|
957
|
+
const report = recheckTimeoutOnlyIntroducedFailures(cwd, aggregate.report, deps.runTimeoutRecheck);
|
|
958
|
+
capture.timeoutRechecks = report.timeoutRechecks;
|
|
959
|
+
const timeoutRecheckResolvedFailure = aggregate.status === 'failed'
|
|
960
|
+
&& (report.timeoutRecheckPassed ?? 0) > 0
|
|
961
|
+
&& report.introduced === 0 && report.unknown === 0 && report.preconditionUnmet === 0
|
|
962
|
+
&& report.timedOut === 0 && report.flakyRerun === 0 && report.worktreeFailuresParsed
|
|
963
|
+
&& report.baselineStatus !== 'unknown';
|
|
964
|
+
const effectiveStatus = timeoutRecheckResolvedFailure ? 'passed' : aggregate.status;
|
|
965
|
+
capture.verdict = effectiveStatus;
|
|
901
966
|
logGateCliBaseline(cwd, {
|
|
902
967
|
introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown,
|
|
903
968
|
preconditionUnmet: report.preconditionUnmet, timedOut: report.timedOut,
|
|
@@ -914,7 +979,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
914
979
|
capture.verdictLine = lines[lines.length - 1];
|
|
915
980
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
916
981
|
return {
|
|
917
|
-
exitCode:
|
|
982
|
+
exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !expose.passed ? 1 : 0,
|
|
918
983
|
lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
|
|
919
984
|
documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
|
|
920
985
|
alwaysIncludeMissing, importerTestsAdded, ...(shardBaseline ? { baseline: shardBaseline } : {}),
|
|
@@ -935,7 +1000,8 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
935
1000
|
|
|
936
1001
|
if (worktreeLog.includes('deterministic environment setup failed')) lines.push(worktreeLog);
|
|
937
1002
|
const baseline = (deps.runBaseline ?? runGateBaseline)(cwd, testFiles, selection.baseRef);
|
|
938
|
-
const report = buildGateBaselineReport(worktreeLog, baseline);
|
|
1003
|
+
const report = recheckTimeoutOnlyIntroducedFailures(cwd, buildGateBaselineReport(worktreeLog, baseline), deps.runTimeoutRecheck);
|
|
1004
|
+
capture.timeoutRechecks = report.timeoutRechecks;
|
|
939
1005
|
logGateCliBaseline(cwd, {
|
|
940
1006
|
introduced: report.introduced,
|
|
941
1007
|
preexisting: report.preexisting,
|
|
@@ -958,3 +1024,21 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
|
|
|
958
1024
|
const exitCode = !androidPassed || !iosPassed || !pwaPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
|
|
959
1025
|
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 } };
|
|
960
1026
|
}
|
|
1027
|
+
|
|
1028
|
+
/** GATE-REMOTE-SHARD-PLAN — a shard plan plus the ready-to-run remote command for each shard. */
|
|
1029
|
+
export interface RemoteGateShardPlan {
|
|
1030
|
+
orchestrationId: string;
|
|
1031
|
+
shards: GateRemoteShard[];
|
|
1032
|
+
commands: string[][];
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/** Turn a changed-file list into identity-carrying shards and their remote gate commands (shard-plan → shard-run wiring). */
|
|
1036
|
+
export function planRemoteGateShardCommands(
|
|
1037
|
+
files: readonly string[],
|
|
1038
|
+
shardCount: number,
|
|
1039
|
+
options?: { planFile?: string; orchestrationId?: string },
|
|
1040
|
+
): RemoteGateShardPlan {
|
|
1041
|
+
const orchestrationId = options?.orchestrationId ?? shardPlanOrchestrationId(files);
|
|
1042
|
+
const shards = planGateRemoteShards(files, shardCount, orchestrationId);
|
|
1043
|
+
return { orchestrationId, shards, commands: shards.map((shard) => remoteShardArgv(shard, options)) };
|
|
1044
|
+
}
|
|
@@ -142,8 +142,9 @@ function hostSlotScriptWithSlot(cap: number, dir: string, tools: readonly SlotLo
|
|
|
142
142
|
return [
|
|
143
143
|
`GS=${quote(dir)}; mkdir -p "$GS" || infra slots`,
|
|
144
144
|
`${pick}else infra lock-tool; fi`,
|
|
145
|
+
'load1() { if [ -r /proc/loadavg ]; then awk \'NR==1 {print $1}\' /proc/loadavg; elif command -v sysctl >/dev/null 2>&1; then sysctl -n vm.loadavg 2>/dev/null | awk \'{gsub(/[{}]/, ""); print $1}\'; else echo unknown; fi; }',
|
|
145
146
|
`n=1; while [ $n -le ${n} ]; do $GL "$GS/slot$n" ${passSlot ? 'env GATE_REMOTE_SLOT="$n" ' : ''}sh "$W/run.sh"; s=$?; [ -f "$W/started" ] && exit $s; n=$((n+1)); done`,
|
|
146
|
-
`echo "${BUSY}=$((n-1))" >&2; exit 98`,
|
|
147
|
+
`echo "${BUSY}=$((n-1));load1=$(load1)" >&2; exit 98`,
|
|
147
148
|
];
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -184,7 +185,7 @@ export const PUSH_TIMEOUT_MS = 10 * 60_000;
|
|
|
184
185
|
|
|
185
186
|
export type RemoteRunOutcome =
|
|
186
187
|
| { kind: 'ran'; rc: number; stdout: Buffer; stderr: Buffer; commit: string; host: string; ms: number }
|
|
187
|
-
| { kind: 'busy'; occupied?: number; rc?: number }
|
|
188
|
+
| { kind: 'busy'; occupied?: number; load1?: number | null; rc?: number }
|
|
188
189
|
| { kind: 'infra'; reason: string; stage?: string; rc?: number | null; stderr?: string };
|
|
189
190
|
|
|
190
191
|
export interface RemoteRunOptions {
|
|
@@ -349,8 +350,10 @@ export function runOnRemote(opts: RemoteRunOptions, runner: GateRemoteRunner = r
|
|
|
349
350
|
if (!(run.rc === 0 && marker >= 0)) {
|
|
350
351
|
const last = stderrText.trimEnd().split('\n').at(-1) ?? '';
|
|
351
352
|
if (run.rc === 98) {
|
|
352
|
-
const busy = /^__GATE_REMOTE_BUSY(?:=(\d+))?$/.exec(last);
|
|
353
|
-
if (busy) return { kind: 'busy', rc: run.rc,
|
|
353
|
+
const busy = /^__GATE_REMOTE_BUSY(?:=(\d+))?(?:;load1=(unknown|\d+(?:\.\d+)?|))?$/.exec(last);
|
|
354
|
+
if (busy) return { kind: 'busy', rc: run.rc,
|
|
355
|
+
...(busy[1] !== undefined ? { occupied: Number(busy[1]) } : {}),
|
|
356
|
+
...(busy[2] !== undefined ? { load1: busy[2] === '' || busy[2] === 'unknown' ? null : Number(busy[2]) } : {}) };
|
|
354
357
|
}
|
|
355
358
|
if (run.rc === 97 && last.startsWith(INFRA)) return { kind: 'infra', stage: last.slice(INFRA.length).trim(), rc: run.rc, stderr: stderrText, reason: `remote-${last.slice(INFRA.length).trim()}` };
|
|
356
359
|
}
|
|
@@ -459,6 +462,8 @@ export interface DispatchDeps {
|
|
|
459
462
|
env?: NodeJS.ProcessEnv;
|
|
460
463
|
sleep?: (ms: number) => Promise<void>;
|
|
461
464
|
now?: () => number;
|
|
465
|
+
/** Test seam for gate.remote events; production defaults to the structured debug log. */
|
|
466
|
+
log?: (event: string, data: Record<string, unknown>) => void;
|
|
462
467
|
write?: { out: (data: string | Uint8Array) => void; err: (data: string | Uint8Array) => void };
|
|
463
468
|
}
|
|
464
469
|
|
|
@@ -531,6 +536,9 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
531
536
|
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
532
537
|
const now = deps.now ?? Date.now;
|
|
533
538
|
const deadline = now() + settings.slotWaitSeconds * 1000;
|
|
539
|
+
let waitStartedAt: number | undefined;
|
|
540
|
+
const logWait = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('gate.remote', event, data));
|
|
541
|
+
let waitedForSlot = false;
|
|
534
542
|
debug.log('gate.remote', 'dispatch', { tool: opts.tool, host, reason: decision.reason });
|
|
535
543
|
let outcome: RemoteRunOutcome;
|
|
536
544
|
for (;;) {
|
|
@@ -540,6 +548,14 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
540
548
|
outcome = { kind: 'infra', reason: `exception: ${error instanceof Error ? error.message : String(error)}` };
|
|
541
549
|
}
|
|
542
550
|
if (outcome.kind !== 'busy') break;
|
|
551
|
+
waitedForSlot = true;
|
|
552
|
+
waitStartedAt ??= now();
|
|
553
|
+
const waitData = {
|
|
554
|
+
tool: opts.tool, host, reason: 'host-busy', load1: outcome.load1 ?? null, loadThreshold: settings.loadThreshold,
|
|
555
|
+
occupied: outcome.occupied ?? null, cap: hostCap, elapsedMs: Math.max(0, now() - waitStartedAt),
|
|
556
|
+
};
|
|
557
|
+
logWait('wait-reason', waitData);
|
|
558
|
+
write.err(`[gate.remote] waiting on ${host} — reason=host-busy load=${outcome.load1 ?? 'unknown'}/${settings.loadThreshold} slots=${outcome.occupied ?? 'unknown'}/${hostCap} elapsed=${Math.floor(waitData.elapsedMs / 1000)}s\n`);
|
|
543
559
|
debug.log('gate.remote', 'host-busy', { tool: opts.tool, host, cap: hostCap, occupied: outcome.occupied ?? null });
|
|
544
560
|
// Never start an attempt past the deadline: an expired self gate wait remains unmeasured.
|
|
545
561
|
const left = deadline - now();
|
|
@@ -547,6 +563,14 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
|
|
|
547
563
|
await sleep(Math.min(15_000, left));
|
|
548
564
|
if (now() >= deadline) break;
|
|
549
565
|
}
|
|
566
|
+
if (waitedForSlot) {
|
|
567
|
+
const resolution = outcome.kind === 'ran' ? 'slot-open' : outcome.kind === 'busy' ? 'deadline-slot-still-busy'
|
|
568
|
+
: `remote-infra: ${outcome.reason}`;
|
|
569
|
+
const waitData = { tool: opts.tool, host, reason: resolution, elapsedMs: Math.max(0, now() - waitStartedAt!),
|
|
570
|
+
...(outcome.kind === 'busy' ? { occupied: outcome.occupied ?? null, cap: hostCap } : {}) };
|
|
571
|
+
logWait('wait-ended', waitData);
|
|
572
|
+
write.err(`[gate.remote] wait ended on ${host} — reason=${resolution} elapsed=${Math.floor(waitData.elapsedMs / 1000)}s${outcome.kind === 'busy' ? ` slots=${outcome.occupied ?? 'unknown'}/${hostCap}` : ''}\n`);
|
|
573
|
+
}
|
|
550
574
|
if (opts.onRemoteOutcome) {
|
|
551
575
|
try { opts.onRemoteOutcome(outcome, host, deps.runner ?? realGateRemoteRunner); }
|
|
552
576
|
catch (error) { debug.log('gate.remote', 'outcome-hook-failed', { tool: opts.tool, host, error: error instanceof Error ? error.message : String(error) }); }
|