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
|
@@ -2,6 +2,7 @@ import { CLAIM_IDLE_HOURS, PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-l
|
|
|
2
2
|
import { debug } from '../debug/log.js';
|
|
3
3
|
import { assessDraftTriage, decideDraft, draftClaimComment, draftClaimState, draftReleaseComment, laterMergedTwins, sameGoalPr, PROTECTED_LABELS, type DraftTriageAssessment, type DraftTriagePr, type DraftTriageReviewState } from './draft-triage-rules.js';
|
|
4
4
|
import { cellIdFromBody } from '../pr-tool/census.js';
|
|
5
|
+
import { RELEASE_PATH_LABEL } from './release-path-guard.js';
|
|
5
6
|
import { cardPrNumber, draftTaskOwner, type TaskCard } from '../task-agent/task-hand.js';
|
|
6
7
|
import type { PrTerminalRecord } from './draft-residue.js';
|
|
7
8
|
import { branchLineageSlug } from '../cli/pr-lineage.js';
|
|
@@ -13,6 +14,7 @@ export interface SweepDraft extends DraftTriagePr {
|
|
|
13
14
|
readonly createdAt: string;
|
|
14
15
|
/** Last PR update (push, label, comment). Missing ⇒ no idle-based close; merged twins can still close. */
|
|
15
16
|
readonly updatedAt?: string;
|
|
17
|
+
readonly headSha?: string;
|
|
16
18
|
readonly runId?: string | null;
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -26,17 +28,22 @@ export interface SweepMergedPr extends DraftTriagePr {
|
|
|
26
28
|
export interface DraftSweepAdapters {
|
|
27
29
|
/** Each call returns one complete page; a rejection must not be mistaken for an empty page. */
|
|
28
30
|
listDrafts(page: number, perPage: number, repository: string): Promise<readonly SweepDraft[]>;
|
|
31
|
+
/** Optional completeness of a bounded inventory; a partial inventory can inform dry-run only. */
|
|
32
|
+
inventoryStatus?(): Promise<{ complete: boolean; reason?: string }>;
|
|
29
33
|
/** Head commit time is fetched only for explicit triage, where it gates idle/close recommendations. */
|
|
30
34
|
getHeadCommitTime?(repository: string, number: number): Promise<string | undefined>;
|
|
31
35
|
listMerged(page: number, perPage: number, repository: string): Promise<readonly SweepMergedPr[]>;
|
|
32
36
|
/** Complete closed PR inventory for the creation cohort (including closed without merge). */
|
|
33
37
|
listRecentClosed?(repository: string, createdSince: Date): Promise<readonly SweepMergedPr[]>;
|
|
34
38
|
/** Undefined means no run assessment; a merged twin or 24h idle draft can still authorize a close. */
|
|
35
|
-
|
|
39
|
+
/** Intentionally needs identity only: adapters must not couple sweep status lookup to presentation fields. */
|
|
40
|
+
getRunStatus(draft: Pick<SweepDraft, 'number' | 'branch' | 'runId'>, repository: string): Promise<string | undefined>;
|
|
36
41
|
/** Undefined means liveness could not be established. */
|
|
37
42
|
listLiveBranches(repository: string): Promise<ReadonlySet<string> | undefined>;
|
|
38
43
|
setLabels(repository: string, number: number, change: { add: string; remove: readonly string[] }): Promise<void>;
|
|
39
44
|
closeDraft(repository: string, number: number): Promise<void>;
|
|
45
|
+
/** Minimal live identity check used by snapshot apply; no repository-wide inventory is read. */
|
|
46
|
+
getDraftSnapshot?(repository: string, number: number): Promise<DraftSweepSnapshot | undefined>;
|
|
40
47
|
/** Resolve the latest claim comment owner; a failed lookup must not authorize a close. */
|
|
41
48
|
getClaimOwner?(repository: string, number: number): Promise<string | undefined>;
|
|
42
49
|
/** Current owner, accounting for a later claim release; only draft metrics need this distinction. */
|
|
@@ -71,7 +78,28 @@ export interface DraftSweepAdapters {
|
|
|
71
78
|
* Must reject when the run could not be stopped — the draft is then neither labelled nor closed.
|
|
72
79
|
* Absent ⇒ a live duplicate is kept, never closed.
|
|
73
80
|
*/
|
|
74
|
-
|
|
81
|
+
/** Same minimal identity contract as getRunStatus; stopping authority is scoped to the selected run pair. */
|
|
82
|
+
supersedeRun?(draft: Pick<SweepDraft, 'number' | 'branch' | 'runId'>, repository: string,
|
|
83
|
+
newer: Pick<SweepDraft, 'number' | 'branch' | 'runId'>): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface DraftSweepSnapshot {
|
|
87
|
+
readonly number: number;
|
|
88
|
+
readonly state: 'open' | 'closed';
|
|
89
|
+
readonly draft: boolean;
|
|
90
|
+
readonly headSha: string;
|
|
91
|
+
readonly branch: string;
|
|
92
|
+
readonly updatedAt: string;
|
|
93
|
+
readonly labels: readonly string[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface DraftSweepApplyPlan {
|
|
97
|
+
readonly version: 1;
|
|
98
|
+
readonly closeCap: number;
|
|
99
|
+
readonly closeCapSource: DraftSweepCloseCapSource;
|
|
100
|
+
readonly entries: readonly (DraftSweepEntry & { readonly headSha: string; readonly branch: string; readonly runId?: string;
|
|
101
|
+
readonly stopRunRequired?: boolean; readonly supersedeNewer?: { readonly number: number; readonly branch: string; readonly runId?: string };
|
|
102
|
+
readonly updatedAt: string; readonly labels: readonly string[] })[];
|
|
75
103
|
}
|
|
76
104
|
|
|
77
105
|
/** Review PASS and gate posture used only by the daily old-draft count. */
|
|
@@ -95,6 +123,10 @@ export interface DraftSweepOptions {
|
|
|
95
123
|
alreadyClosed?: number;
|
|
96
124
|
/** Include evidence-backed next-action recommendations in JSON output; never authorizes writes. */
|
|
97
125
|
includeTriage?: boolean;
|
|
126
|
+
/** Build a frozen apply plan from a complete dry-run classification. */
|
|
127
|
+
includeApplyPlan?: boolean;
|
|
128
|
+
/** Apply exactly this plan after live identity preflight. */
|
|
129
|
+
applyPlan?: DraftSweepApplyPlan;
|
|
98
130
|
}
|
|
99
131
|
|
|
100
132
|
export interface DraftSweepEntry {
|
|
@@ -113,6 +145,7 @@ export interface DraftSweepResult {
|
|
|
113
145
|
apply: boolean;
|
|
114
146
|
complete: boolean;
|
|
115
147
|
entries: DraftSweepEntry[];
|
|
148
|
+
applyPlan?: DraftSweepApplyPlan;
|
|
116
149
|
triage?: { entries: Array<{ number: number; assessment: DraftTriageAssessment }>; counts: Record<string, number> };
|
|
117
150
|
counts: Record<string, number>;
|
|
118
151
|
/** Drafts whose run could not be observed from here (kept, or closed by the idle rule). */
|
|
@@ -260,9 +293,26 @@ export async function collectDraftMetrics(repository: string, adapters: Pick<Dra
|
|
|
260
293
|
|| (pr.mergedAt !== undefined && !Number.isFinite(Date.parse(pr.mergedAt)))
|
|
261
294
|
|| !Array.isArray(pr.labels) || pr.labels.some((name) => typeof name !== 'string')))
|
|
262
295
|
throw new Error('Incomplete draft metric inventory');
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const
|
|
296
|
+
// Fold each source independently; a merged closed row outranks an unmerged snapshot.
|
|
297
|
+
// The serialized row is a stable tie-breaker when timestamps match, regardless of page order.
|
|
298
|
+
const fold = <T extends { number: number }>(rows: readonly T[], rank: (pr: T) => readonly number[]): T[] => {
|
|
299
|
+
const byNumber = new Map<number, T>();
|
|
300
|
+
for (const row of rows) {
|
|
301
|
+
const prior = byNumber.get(row.number);
|
|
302
|
+
if (prior) {
|
|
303
|
+
const a = rank(row), b = rank(prior);
|
|
304
|
+
const order = a.reduce((result, value, index) => result || value - b[index]!, 0);
|
|
305
|
+
if (order < 0 || (order === 0 && JSON.stringify(row) <= JSON.stringify(prior))) continue;
|
|
306
|
+
}
|
|
307
|
+
byNumber.set(row.number, row);
|
|
308
|
+
}
|
|
309
|
+
return [...byNumber.values()];
|
|
310
|
+
};
|
|
311
|
+
const uniqueDrafts = fold(drafts, (pr) => [Number.isFinite(Date.parse(pr.updatedAt ?? ''))
|
|
312
|
+
? Date.parse(pr.updatedAt!) : Date.parse(pr.createdAt), Date.parse(pr.createdAt)]);
|
|
313
|
+
const uniqueClosed = fold(closed, (pr) => [pr.mergedAt ? 1 : 0,
|
|
314
|
+
pr.mergedAt ? Date.parse(pr.mergedAt) : Date.parse(pr.createdAt!), Date.parse(pr.createdAt!)]);
|
|
315
|
+
const open = uniqueDrafts.filter(harnessDraft);
|
|
266
316
|
const owners = await Promise.all(open.map(async (draft) => {
|
|
267
317
|
if (!adapters.getActiveClaimOwner) throw new Error('Draft owner lookup unavailable');
|
|
268
318
|
const owner = await adapters.getActiveClaimOwner(repository, draft.number);
|
|
@@ -270,9 +320,12 @@ export async function collectDraftMetrics(repository: string, adapters: Pick<Dra
|
|
|
270
320
|
return owner;
|
|
271
321
|
}));
|
|
272
322
|
const cohort = [...open.filter((pr) => Date.parse(pr.createdAt) >= cutoff && Date.parse(pr.createdAt) <= matured),
|
|
273
|
-
...
|
|
323
|
+
...uniqueClosed.filter((pr) => (pr.branch.startsWith('self-impl/') || pr.labels!.some((name) => name.startsWith('elanous:')))
|
|
274
324
|
&& pr.createdAt && Date.parse(pr.createdAt) >= cutoff && Date.parse(pr.createdAt) <= matured)];
|
|
275
325
|
if (new Set(cohort.map((pr) => pr.number)).size !== cohort.length) throw new Error('Overlapping draft metric inventory');
|
|
326
|
+
const folded = drafts.length - uniqueDrafts.length + closed.length - uniqueClosed.length;
|
|
327
|
+
if (folded) try { debug.log('drafts.metrics', 'duplicate-pr-folded', { repository, drafts: drafts.length - uniqueDrafts.length,
|
|
328
|
+
closed: closed.length - uniqueClosed.length, folded }); } catch { /* fail-soft */ }
|
|
276
329
|
const converted48h = cohort.filter((pr) => 'mergedAt' in pr && typeof pr.mergedAt === 'string'
|
|
277
330
|
&& Date.parse(pr.mergedAt) >= Date.parse(pr.createdAt!) && Date.parse(pr.mergedAt) <= clock
|
|
278
331
|
&& Date.parse(pr.mergedAt) - Date.parse(pr.createdAt!) <= 48 * 3_600_000).length;
|
|
@@ -770,6 +823,17 @@ function harnessDraft(draft: SweepDraft): boolean {
|
|
|
770
823
|
return draft.branch.startsWith('self-impl/') || draft.labels.some((name) => name.startsWith('elanous:'));
|
|
771
824
|
}
|
|
772
825
|
|
|
826
|
+
/** A prior final event is authoritative only when the branch is not observably live. */
|
|
827
|
+
function isLiveDraftRun(status: string | undefined, branch: string, liveBranches: ReadonlySet<string>): boolean {
|
|
828
|
+
return status === 'running' || status === 'probable-running'
|
|
829
|
+
|| (status !== 'self-implement.result final' && liveBranches.has(branch));
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
function isKnownSweepCloseReason(reason: string): boolean {
|
|
833
|
+
return ['superseded-by #', 'duplicate-of-open #', 'claim-expired', 'stale-unobserved', 'harvest-expired', 'stale-ended-run']
|
|
834
|
+
.some((prefix) => reason === prefix || reason.startsWith(prefix));
|
|
835
|
+
}
|
|
836
|
+
|
|
773
837
|
/**
|
|
774
838
|
* The newest open draft of the same goal lineage that was created strictly after `draft` — a rerun
|
|
775
839
|
* (e.g. a forced requeue) of the same goal. Reads only the branch, so a draft with no task card still has a lineage.
|
|
@@ -835,8 +899,130 @@ export function draftSweepDaily(
|
|
|
835
899
|
return { date: now.toISOString().slice(0, 10), over24h, closable, harvestable, blocked };
|
|
836
900
|
}
|
|
837
901
|
|
|
902
|
+
/** Validate serialized plans at the CLI boundary; malformed or ambiguous plans must never reach a writer. */
|
|
903
|
+
export function validateDraftSweepApplyPlan(value: unknown): DraftSweepApplyPlan {
|
|
904
|
+
if (!value || typeof value !== 'object') throw new Error('invalid draft sweep apply plan');
|
|
905
|
+
const plan = value as Partial<DraftSweepApplyPlan>;
|
|
906
|
+
if (plan.version !== 1 || !validCloseCap(plan.closeCap)
|
|
907
|
+
|| !['flag', 'config', 'default'].includes(String(plan.closeCapSource)) || !Array.isArray(plan.entries)) {
|
|
908
|
+
throw new Error('invalid draft sweep apply plan header');
|
|
909
|
+
}
|
|
910
|
+
const seen = new Set<number>();
|
|
911
|
+
for (const entry of plan.entries) {
|
|
912
|
+
if (!entry || !Number.isSafeInteger(entry.number) || entry.number! < 1 || seen.has(entry.number!)
|
|
913
|
+
|| !['keep', 'close', 'report'].includes(entry.action) || typeof entry.reason !== 'string'
|
|
914
|
+
|| (entry.action === 'close' && !isKnownSweepCloseReason(entry.reason))
|
|
915
|
+
|| typeof entry.headSha !== 'string' || !/^[a-f0-9]{40}$/i.test(entry.headSha)
|
|
916
|
+
|| typeof entry.branch !== 'string' || !entry.branch
|
|
917
|
+
|| (entry.statusLabel !== undefined && !stateLabels.some((state) => state.name === entry.statusLabel))
|
|
918
|
+
|| (entry.supersedeNewer !== undefined && (!Number.isSafeInteger(entry.supersedeNewer.number)
|
|
919
|
+
|| entry.supersedeNewer.number < 1 || entry.supersedeNewer.number === entry.number
|
|
920
|
+
|| typeof entry.supersedeNewer.branch !== 'string' || !entry.supersedeNewer.branch
|
|
921
|
+
|| (entry.supersedeNewer.runId !== undefined && typeof entry.supersedeNewer.runId !== 'string')))
|
|
922
|
+
|| typeof entry.updatedAt !== 'string' || !Number.isFinite(Date.parse(entry.updatedAt))
|
|
923
|
+
|| !Array.isArray(entry.labels) || entry.labels.some((name: unknown) => typeof name !== 'string')
|
|
924
|
+
|| (entry.stopRunRequired === true && (!entry.runId || !entry.supersedeNewer?.runId))
|
|
925
|
+
|| (entry.supersedeNewer !== undefined && entry.stopRunRequired !== true)) {
|
|
926
|
+
throw new Error('invalid draft sweep apply plan entry');
|
|
927
|
+
}
|
|
928
|
+
seen.add(entry.number!);
|
|
929
|
+
}
|
|
930
|
+
const closes = plan.entries.filter((entry) => entry.action === 'close').length;
|
|
931
|
+
if (closes > plan.closeCap!) throw new Error('draft sweep apply plan exceeds close cap');
|
|
932
|
+
return value as DraftSweepApplyPlan;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
async function applyDraftSweepPlan(repository: string, adapters: DraftSweepAdapters, planInput: DraftSweepApplyPlan): Promise<DraftSweepResult> {
|
|
936
|
+
const plan = validateDraftSweepApplyPlan(planInput);
|
|
937
|
+
const result: DraftSweepResult = { repository, apply: true, complete: false, entries: plan.entries.map(({ number, action, reason, statusLabel }) => ({
|
|
938
|
+
number, action, reason, ...(statusLabel ? { statusLabel } : {}), applied: false,
|
|
939
|
+
})), counts: {}, closeCap: plan.closeCap, closeCapSource: plan.closeCapSource };
|
|
940
|
+
const writable = plan.entries.filter((entry) => entry.action !== 'report' && (entry.action === 'close' || Boolean(entry.statusLabel)));
|
|
941
|
+
const preflightEntries = new Map(writable.map((entry) => [entry.number, entry]));
|
|
942
|
+
for (const entry of writable) if (entry.supersedeNewer) {
|
|
943
|
+
const newer = plan.entries.find((candidate) => candidate.number === entry.supersedeNewer!.number);
|
|
944
|
+
if (!newer) { result.error = `snapshot apply plan missing newer PR #${entry.supersedeNewer.number}`; return result; }
|
|
945
|
+
preflightEntries.set(newer.number, newer);
|
|
946
|
+
}
|
|
947
|
+
if (!adapters.getDraftSnapshot) { result.error = 'draft snapshot preflight unavailable'; return result; }
|
|
948
|
+
// Read and validate every target before the first mutation: one stale item blocks the whole write batch.
|
|
949
|
+
const snapshots = await mapBounded([...preflightEntries.values()], DRAFT_SWEEP_CONCURRENCY, async (entry) => ({ entry,
|
|
950
|
+
current: await adapters.getDraftSnapshot!(repository, entry.number) }));
|
|
951
|
+
const drift = snapshots.find(({ entry, current }) => !current || current.number !== entry.number || current.state !== 'open'
|
|
952
|
+
|| current.draft !== true || current.headSha !== entry.headSha || current.branch !== entry.branch || current.updatedAt !== entry.updatedAt
|
|
953
|
+
|| current.labels.length !== entry.labels.length || [...current.labels].sort().join('\0') !== [...entry.labels].sort().join('\0'));
|
|
954
|
+
if (drift) {
|
|
955
|
+
const number = drift.entry.number;
|
|
956
|
+
result.error = `draft snapshot drift at #${number}; no writes performed`;
|
|
957
|
+
for (const entry of result.entries) if (writable.some((item) => item.number === entry.number)) entry.error = result.error;
|
|
958
|
+
return result;
|
|
959
|
+
}
|
|
960
|
+
const stopPlans = writable.filter((entry) => entry.stopRunRequired === true);
|
|
961
|
+
const stoppedRuns = new Set<number>();
|
|
962
|
+
if (stopPlans.length) {
|
|
963
|
+
if (!adapters.supersedeRun || !adapters.getRunStatus || !adapters.listLiveBranches
|
|
964
|
+
|| stopPlans.some((entry) => !entry.runId || !entry.supersedeNewer?.runId)) {
|
|
965
|
+
result.error = 'snapshot apply cannot verify live duplicate run ownership';
|
|
966
|
+
return result;
|
|
967
|
+
}
|
|
968
|
+
const branches = await adapters.listLiveBranches(repository);
|
|
969
|
+
if (!branches) { result.error = 'snapshot apply cannot verify branch liveness'; return result; }
|
|
970
|
+
const liveChecks = await Promise.all(stopPlans.map(async (entry) => {
|
|
971
|
+
const newer = entry.supersedeNewer!;
|
|
972
|
+
const [oldStatus, newerStatus] = await Promise.all([
|
|
973
|
+
adapters.getRunStatus!({ number: entry.number, branch: entry.branch, runId: entry.runId }, repository),
|
|
974
|
+
adapters.getRunStatus!({ number: newer.number, branch: newer.branch, runId: newer.runId }, repository),
|
|
975
|
+
]);
|
|
976
|
+
return { entry, newer, oldStatus, newerStatus, ok: isLiveDraftRun(oldStatus, entry.branch, branches)
|
|
977
|
+
&& isLiveDraftRun(newerStatus, newer.branch, branches) };
|
|
978
|
+
}));
|
|
979
|
+
const invalid = liveChecks.find((check) => !check.ok);
|
|
980
|
+
if (invalid) { result.error = `live duplicate run state drift at #${invalid.entry.number}; no PR writes performed`; return result; }
|
|
981
|
+
for (const check of liveChecks) {
|
|
982
|
+
try {
|
|
983
|
+
await adapters.supersedeRun!({ number: check.entry.number, branch: check.entry.branch, runId: check.entry.runId }, repository,
|
|
984
|
+
{ number: check.newer.number, branch: check.newer.branch, runId: check.newer.runId });
|
|
985
|
+
stoppedRuns.add(check.entry.number);
|
|
986
|
+
} catch (error) { result.error = `could not stop planned run at #${check.entry.number}: ${sweepFailureReason(error)}`; return result; }
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
for (const { entry } of snapshots) {
|
|
990
|
+
const output = result.entries.find((item) => item.number === entry.number)!;
|
|
991
|
+
let mutated = false;
|
|
992
|
+
try {
|
|
993
|
+
if (entry.action === 'close' && entry.reason.startsWith('claim-expired')) {
|
|
994
|
+
// A complete comment inventory with no owner marker is valid; incomplete/unreadable inventories throw.
|
|
995
|
+
// The owner value itself is not a close criterion; classification and updatedAt preflight own that decision.
|
|
996
|
+
if (!adapters.getClaimOwner) throw new Error('claim owner lookup unavailable');
|
|
997
|
+
await adapters.getClaimOwner(repository, entry.number);
|
|
998
|
+
}
|
|
999
|
+
if (entry.statusLabel) {
|
|
1000
|
+
const remove = stateLabels.filter((item) => entry.labels.includes(item.name) && item.name !== entry.statusLabel).map((item) => item.name);
|
|
1001
|
+
if (!entry.labels.includes(entry.statusLabel) || remove.length) {
|
|
1002
|
+
await adapters.setLabels(repository, entry.number, { add: entry.statusLabel, remove });
|
|
1003
|
+
mutated = true;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (entry.action === 'close') {
|
|
1007
|
+
await closeSweptDraft(adapters, repository, entry.number, entry.reason, () => { mutated = true; });
|
|
1008
|
+
}
|
|
1009
|
+
output.applied = mutated;
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
if ((mutated && entry.action === 'close') || stoppedRuns.has(entry.number)) output.partialApplied = true;
|
|
1012
|
+
output.error = sweepFailureReason(error);
|
|
1013
|
+
result.error = `snapshot apply failed at #${entry.number}: ${output.error}`;
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
result.complete = true;
|
|
1018
|
+
result.closed = plan.entries.filter((entry) => entry.action === 'close').length;
|
|
1019
|
+
for (const entry of result.entries) result.counts[entry.reason] = (result.counts[entry.reason] ?? 0) + 1;
|
|
1020
|
+
return result;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
838
1023
|
/** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
|
|
839
|
-
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date(), closeCap: requestedCap, closeCapSource: requestedSource, alreadyClosed = 0, includeTriage = false }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
1024
|
+
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date(), closeCap: requestedCap, closeCapSource: requestedSource, alreadyClosed = 0, includeTriage = false, includeApplyPlan = false, applyPlan }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
1025
|
+
if (applyPlan) return applyDraftSweepPlan(repository, adapters, applyPlan);
|
|
840
1026
|
const validCap = validCloseCap(requestedCap);
|
|
841
1027
|
const closeCap = validCap ?? DRAFT_SWEEP_CLOSE_CAP;
|
|
842
1028
|
const closeCapSource: DraftSweepCloseCapSource = validCap === undefined ? 'default' : requestedSource ?? 'flag';
|
|
@@ -871,6 +1057,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
871
1057
|
let drafts: SweepDraft[] = [];
|
|
872
1058
|
let merged: SweepMergedPr[] = [];
|
|
873
1059
|
let liveBranches: ReadonlySet<string> | undefined;
|
|
1060
|
+
let inventoryStatus: { complete: boolean; reason?: string } = { complete: true };
|
|
874
1061
|
try {
|
|
875
1062
|
[drafts, merged, liveBranches] = await Promise.all([
|
|
876
1063
|
collectPages((page, size) => adapters.listDrafts(page, size, repository)),
|
|
@@ -880,6 +1067,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
880
1067
|
if (!liveBranches) throw new Error('Branch liveness unavailable');
|
|
881
1068
|
if (drafts.some((pr) => !Number.isInteger(pr.number) || !pr.branch || !Array.isArray(pr.labels) || !Number.isFinite(Date.parse(pr.createdAt)))
|
|
882
1069
|
|| merged.some((pr) => !Number.isInteger(pr.number) || !pr.branch)) throw new Error('Invalid PR inventory');
|
|
1070
|
+
inventoryStatus = await adapters.inventoryStatus?.() ?? inventoryStatus;
|
|
883
1071
|
} catch (error) {
|
|
884
1072
|
timing('inventory', drafts.length + merged.length, 'failed');
|
|
885
1073
|
result.error = sweepFailureReason(error);
|
|
@@ -887,6 +1075,10 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
887
1075
|
return finish();
|
|
888
1076
|
}
|
|
889
1077
|
timing('inventory', drafts.length + merged.length);
|
|
1078
|
+
if (!inventoryStatus.complete && apply) {
|
|
1079
|
+
result.error = inventoryStatus.reason ?? 'PR inventory incomplete';
|
|
1080
|
+
return finish();
|
|
1081
|
+
}
|
|
890
1082
|
for (const pr of drafts) if (pr.runId) runIdByNumber.set(pr.number, pr.runId);
|
|
891
1083
|
const statuses = new Map<number, string | undefined>();
|
|
892
1084
|
const finality = new Map<number, boolean | undefined>();
|
|
@@ -926,7 +1118,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
926
1118
|
}
|
|
927
1119
|
timing('review-gate', censused.length);
|
|
928
1120
|
}
|
|
929
|
-
result.daily = draftSweepDaily(drafts, merged, now, reviewGate);
|
|
1121
|
+
if (inventoryStatus.complete) result.daily = draftSweepDaily(drafts, merged, now, reviewGate);
|
|
930
1122
|
// Card and terminal inventories are observations, not closing authority. An unreadable source cannot mint a claim.
|
|
931
1123
|
let cards: readonly TaskCard[] | undefined;
|
|
932
1124
|
let terminals: readonly PrTerminalRecord[] | undefined;
|
|
@@ -999,7 +1191,17 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
999
1191
|
const cellTerminals = terminals?.filter((terminal) => terminal.repository === repository && terminal.prNumber === draft.number);
|
|
1000
1192
|
const activeOwnerObservation = ownerCard ? undefined : activeOwnerObservations.get(draft.number);
|
|
1001
1193
|
const posture = reviewGate.get(draft.number);
|
|
1194
|
+
const replacement = identity.cellId && identity.checks.provenance.state === 'yes'
|
|
1195
|
+
? merged.find((pr) => pr.number !== draft.number && cellIdFromBody(pr.body ?? '') === identity.cellId
|
|
1196
|
+
&& Number.isFinite(Date.parse(pr.mergedAt ?? '')) && Date.parse(pr.mergedAt!) > Date.parse(draft.createdAt)
|
|
1197
|
+
&& (pr.body ?? '').split(/\r?\n/).some((line) => line.trim() === `Supersedes: #${draft.number}`)) : undefined;
|
|
1198
|
+
const lastFailure = cellTerminals?.filter((terminal) => terminal.terminalClass.startsWith('failed-')
|
|
1199
|
+
&& Number.isFinite(Date.parse(terminal.at)))
|
|
1200
|
+
.sort((a, b) => Date.parse(b.at) - Date.parse(a.at))[0];
|
|
1201
|
+
const lastFailureTail = lastFailure?.hostRegateFailure?.detail ?? lastFailure?.stage ?? null;
|
|
1002
1202
|
const assessment = assessDraftTriage({ draft, now, runStatus: statuses.get(draft.number),
|
|
1203
|
+
...(replacement ? { replacement: { number: replacement.number, evidence: `Supersedes: #${draft.number}` } } : {}),
|
|
1204
|
+
lastFailureTail,
|
|
1003
1205
|
...(posture?.gate ? { gate: posture.gate } : {}),
|
|
1004
1206
|
...(posture?.triageReview ? { review: posture.triageReview } : {}),
|
|
1005
1207
|
newerSameCellSameCard,
|
|
@@ -1013,12 +1215,14 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1013
1215
|
for (const row of triageRows) triageCounts[row.assessment.nextAction] = (triageCounts[row.assessment.nextAction] ?? 0) + 1;
|
|
1014
1216
|
result.triage = { entries: triageRows, counts: triageCounts };
|
|
1015
1217
|
}
|
|
1016
|
-
result.complete =
|
|
1218
|
+
result.complete = inventoryStatus.complete;
|
|
1219
|
+
if (!inventoryStatus.complete) result.error = inventoryStatus.reason ?? 'PR inventory incomplete';
|
|
1017
1220
|
let closes = Number.isSafeInteger(alreadyClosed) && alreadyClosed > 0 ? alreadyClosed : 0;
|
|
1018
1221
|
let unobserved = 0;
|
|
1019
1222
|
let claimed = 0;
|
|
1020
1223
|
let claimExpired = 0;
|
|
1021
1224
|
const lineageCounts: DraftSweepLineageCounts = { closed: 0, harvestableClosed: 0, fallThrough: {} };
|
|
1225
|
+
const stopRunPlans = new Map<number, { runId?: string; newer: { number: number; branch: string; runId?: string } }>();
|
|
1022
1226
|
result.lineage = lineageCounts;
|
|
1023
1227
|
// 칸-keyed closes this tick; published on `lineageCounts` only when the 칸 rule fires (existing shapes stay byte-identical).
|
|
1024
1228
|
let cellClosed = 0;
|
|
@@ -1035,7 +1239,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1035
1239
|
let claimPartialApplied = false;
|
|
1036
1240
|
let partialClaimUnowned = false;
|
|
1037
1241
|
let releasePending = false;
|
|
1038
|
-
if (apply && harnessDraft(draft) && !draft.labels.some((name) => name === approvalLabel || name === keepLabel || name === releaseHoldLabel)
|
|
1242
|
+
if (apply && harnessDraft(draft) && !draft.labels.some((name) => name === approvalLabel || name === keepLabel || name === releaseHoldLabel || name === RELEASE_PATH_LABEL)
|
|
1039
1243
|
&& stateLabels.filter((state) => draft.labels.includes(state.name)).length <= 1
|
|
1040
1244
|
&& !draft.labels.includes(supersededLabel)) {
|
|
1041
1245
|
const logClaim = (event: 'claim-marked' | 'claim-released' | 'claim-skipped', owner: string | null, runId: string | null, reason: string) =>
|
|
@@ -1128,8 +1332,10 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1128
1332
|
...(claimWriteFailed ? { error: claimWriteError, ...(claimPartialApplied ? { partialApplied: true } : {}) } : {}) });
|
|
1129
1333
|
continue;
|
|
1130
1334
|
}
|
|
1131
|
-
if (draft.labels.includes(releaseHoldLabel ?? '') ||
|
|
1132
|
-
|
|
1335
|
+
if (draft.labels.includes(releaseHoldLabel ?? '') || draft.labels.includes(RELEASE_PATH_LABEL)
|
|
1336
|
+
|| (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
|
|
1337
|
+
const held = draft.labels.includes(keepLabel ?? '') ? keepLabel
|
|
1338
|
+
: draft.labels.includes(RELEASE_PATH_LABEL) ? RELEASE_PATH_LABEL : releaseHoldLabel;
|
|
1133
1339
|
record({ number: draft.number, action: 'keep', reason: `label:${held}`, applied: false });
|
|
1134
1340
|
continue;
|
|
1135
1341
|
}
|
|
@@ -1152,9 +1358,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1152
1358
|
const base = decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1153
1359
|
finalRunResult, ageHours: runStatus ? ageHours : idleHours });
|
|
1154
1360
|
if (!base.reason.startsWith('label:') && !base.reason.startsWith('superseded-by #') && !base.reason.startsWith('duplicate-of-open #')) {
|
|
1155
|
-
const
|
|
1156
|
-
|| (status !== 'self-implement.result final' && liveBranches.has(branch));
|
|
1157
|
-
const runLive = live(runStatus, draft.branch);
|
|
1361
|
+
const runLive = isLiveDraftRun(runStatus, draft.branch, liveBranches);
|
|
1158
1362
|
const lineageKey = branchLineageKey(draft.branch);
|
|
1159
1363
|
const cellId = cellNewer ? cellIdFromBody(draft.body ?? '') : null;
|
|
1160
1364
|
const duplicateOf = cellNewer ? `cell ${cellId}` : `lineage ${lineageKey}`;
|
|
@@ -1184,7 +1388,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1184
1388
|
else if (runLive && !adapters.supersedeRun) fallThrough('lineage-duplicate-run-live');
|
|
1185
1389
|
// Safety (OP 10-11): a live run is stopped only when the newer run of the same lineage is itself live —
|
|
1186
1390
|
// never trade a running attempt for one that already ended or was never observed running.
|
|
1187
|
-
else if (runLive && !
|
|
1391
|
+
else if (runLive && !isLiveDraftRun(statuses.get(duplicateNewer.number), duplicateNewer.branch, liveBranches)) fallThrough('lineage-newer-run-not-live');
|
|
1188
1392
|
else if (closes >= closeCap) {
|
|
1189
1393
|
record({ number: draft.number, action: 'keep', reason: 'close-cap', applied: false });
|
|
1190
1394
|
continue;
|
|
@@ -1208,6 +1412,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1208
1412
|
lineageCounts.closed += 1;
|
|
1209
1413
|
if (harvestable) lineageCounts.harvestableClosed += 1;
|
|
1210
1414
|
if (cellNewer) cellClosed += 1;
|
|
1415
|
+
if (runLive) stopRunPlans.set(draft.number, { runId: draft.runId ?? undefined, newer: { number: duplicateNewer.number,
|
|
1416
|
+
branch: duplicateNewer.branch, runId: duplicateNewer.runId ?? undefined } });
|
|
1211
1417
|
const entry: DraftSweepEntry = { number: draft.number, action: 'close', reason, statusLabel: supersededLabel, applied: false };
|
|
1212
1418
|
record(entry);
|
|
1213
1419
|
if (!apply) continue;
|
|
@@ -1345,5 +1551,24 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1345
1551
|
result.closed = closes - (Number.isSafeInteger(alreadyClosed) && alreadyClosed > 0 ? alreadyClosed : 0);
|
|
1346
1552
|
result.claimed = claimed;
|
|
1347
1553
|
result.claimExpired = claimExpired;
|
|
1554
|
+
if (includeApplyPlan && !apply && result.complete) {
|
|
1555
|
+
const byNumber = new Map(drafts.map((draft) => [draft.number, draft]));
|
|
1556
|
+
const planEntries = result.entries.map((entry) => {
|
|
1557
|
+
const draft = byNumber.get(entry.number);
|
|
1558
|
+
if (!draft?.headSha || !draft.updatedAt || !Number.isFinite(Date.parse(draft.updatedAt))) {
|
|
1559
|
+
throw new Error(`cannot freeze apply plan: missing head SHA or updatedAt for #${entry.number}`);
|
|
1560
|
+
}
|
|
1561
|
+
const stopRun = stopRunPlans.get(entry.number);
|
|
1562
|
+
const newer = stopRun ? byNumber.get(stopRun.newer.number) : undefined;
|
|
1563
|
+
if (stopRun && (!draft.runId || !newer?.runId || stopRun.runId !== draft.runId
|
|
1564
|
+
|| stopRun.newer.branch !== newer.branch || stopRun.newer.runId !== newer.runId)) {
|
|
1565
|
+
throw new Error(`cannot freeze apply plan: live duplicate run identity incomplete for #${entry.number}`);
|
|
1566
|
+
}
|
|
1567
|
+
return { ...entry, headSha: draft.headSha, branch: draft.branch, ...(draft.runId ? { runId: draft.runId } : {}),
|
|
1568
|
+
...(stopRun ? { stopRunRequired: true, supersedeNewer: stopRun.newer } : {}),
|
|
1569
|
+
updatedAt: draft.updatedAt, labels: [...draft.labels].sort() };
|
|
1570
|
+
});
|
|
1571
|
+
result.applyPlan = validateDraftSweepApplyPlan({ version: 1, closeCap, closeCapSource, entries: planEntries });
|
|
1572
|
+
}
|
|
1348
1573
|
return finish();
|
|
1349
1574
|
}
|
|
@@ -40,7 +40,7 @@ export interface DraftTriagePr {
|
|
|
40
40
|
latestCommitAt?: string;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export type DraftTriageNextAction = 'close-a' | 'close-c' | 'human';
|
|
43
|
+
export type DraftTriageNextAction = 'close-a' | 'close-b' | 'close-c' | 'harvest' | 'human';
|
|
44
44
|
export type DraftTriageReviewState = 'approved' | 'changes-requested' | 'commented' | 'dismissed' | 'pending' | 'unknown';
|
|
45
45
|
export type DraftTriageCheck = { state: 'yes' | 'no' | 'unknown'; evidence: string };
|
|
46
46
|
export interface DraftTriageAssessment {
|
|
@@ -51,6 +51,8 @@ export interface DraftTriageAssessment {
|
|
|
51
51
|
review: DraftTriageReviewState;
|
|
52
52
|
cellStatus: 'green' | 'yellow' | 'red' | 'done' | 'unknown';
|
|
53
53
|
nextAction: DraftTriageNextAction;
|
|
54
|
+
lastFailureTail: string | null;
|
|
55
|
+
missingEvidence: readonly string[];
|
|
54
56
|
checks: Readonly<Record<'provenance' | 'gate' | 'review' | 'cell-complete' | 'cell-status-repository-bound' | 'replacement-landed' | 'newer-same-card' | 'idle-48h' | 'protected' | 'recent-commit' | 'running' | 'owner-confirmed', DraftTriageCheck>>;
|
|
55
57
|
evidence: readonly string[];
|
|
56
58
|
}
|
|
@@ -68,11 +70,15 @@ export interface DraftTriageAssessmentInput {
|
|
|
68
70
|
targetRepository?: string;
|
|
69
71
|
newerSameCellSameCard?: boolean;
|
|
70
72
|
ownerConfirmed?: boolean;
|
|
73
|
+
/** Explicit merged PR naming this draft as its same-cell predecessor. */
|
|
74
|
+
replacement?: { number: number; evidence: string };
|
|
75
|
+
/** Exact-PR terminal failure, not a failure inferred from another draft in the cell. */
|
|
76
|
+
lastFailureTail?: string | null;
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
const CLOSE_PROTECTED_LABELS = new Set([
|
|
74
80
|
'elanous:running', 'elanous:keep', 'elanous:release-hold', 'elanous:idea-approval',
|
|
75
|
-
'elanous:harvest-claimed', 'triage:land', 'triage:active',
|
|
81
|
+
'elanous:harvest-claimed', RELEASE_PATH_LABEL, 'triage:land', 'triage:active',
|
|
76
82
|
]);
|
|
77
83
|
const TRIAGE_TERMINAL_RUN_STATUSES = new Set(['completed', 'failed', 'cancelled', 'abandoned', 'self-implement.result final']);
|
|
78
84
|
|
|
@@ -124,7 +130,10 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
124
130
|
const idle48h = Number.isFinite(ageHours) && ageHours >= 48;
|
|
125
131
|
let nextAction: DraftTriageNextAction = 'human';
|
|
126
132
|
if (closeEligible && cellComplete && cellStatusRepositoryBound) nextAction = 'close-a';
|
|
133
|
+
else if (closeEligible && input.replacement) nextAction = 'close-b';
|
|
127
134
|
else if (closeEligible && idle48h && input.ownerConfirmed === true) nextAction = 'close-c';
|
|
135
|
+
else if (provenance && (draft.labels ?? []).includes('elanous:harvestable') && !protectedState && runNotRunning
|
|
136
|
+
&& input.gate === 'pass' && input.review === 'approved') nextAction = 'harvest';
|
|
128
137
|
|
|
129
138
|
const checks = {
|
|
130
139
|
provenance: { state: provenance ? 'yes' : 'unknown', evidence: provenance ? `origin=${origin}; cell=${cellId}; card=${cardId}` : '출처·유효 칸·카드 표지가 모두 확인되지 않음' },
|
|
@@ -132,7 +141,9 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
132
141
|
review: { state: input.review === undefined || input.review === 'unknown' ? 'unknown' : input.review === 'approved' ? 'yes' : 'no', evidence: `latest exact-head review=${input.review ?? 'unknown'}` },
|
|
133
142
|
'cell-complete': { state: input.cellStatus && cellStatusRepositoryBound ? (cellComplete ? 'yes' : 'no') : 'unknown', evidence: input.cellStatus ? `cell=${cellId ?? 'unknown'} status=${input.cellStatus}${cellStatusRepositoryBound ? '' : ' (저장소 귀속 미확인)'}` : `칸 상태 미관측${cellId ? ` (${cellId})` : ''}` },
|
|
134
143
|
'cell-status-repository-bound': { state: cellStatusRepositoryBound ? 'yes' : hasCellStatusRepositoryIdentity ? 'no' : 'unknown', evidence: cellStatusRepositoryBound ? `칸 상태 저장소=${input.cellStatusRepository}; 대상 저장소=${input.targetRepository}` : hasCellStatusRepositoryIdentity ? `칸 상태 저장소=${input.cellStatusRepository}; 대상 저장소=${input.targetRepository} (불일치)` : '칸 상태의 대상 저장소 귀속 미확인' },
|
|
135
|
-
'replacement-landed':
|
|
144
|
+
'replacement-landed': input.replacement
|
|
145
|
+
? { state: 'yes', evidence: `merged #${input.replacement.number}: ${input.replacement.evidence}` }
|
|
146
|
+
: { state: 'unknown', evidence: '현재 adapter는 같은 칸 병합 PR과 이 초안의 대체 관계를 증명하지 않음; follow-up 필요' },
|
|
136
147
|
'newer-same-card': { state: input.newerSameCellSameCard === undefined ? 'unknown' : input.newerSameCellSameCard ? 'yes' : 'no', evidence: `${input.newerSameCellSameCard === undefined ? '같은 칸·카드 새 draft 관계 미관측' : `same-cell-same-card-newer=${input.newerSameCellSameCard}`}; 관측 표지이며 대체 증거가 아님` },
|
|
137
148
|
'idle-48h': { state: Number.isFinite(ageHours) ? (idle48h ? 'yes' : 'no') : 'unknown', evidence: Number.isFinite(ageHours) ? `head age=${ageHours.toFixed(1)}h` : 'head commit 시각 미관측' },
|
|
138
149
|
protected: { state: protectedState ? 'yes' : 'no', evidence: protectedLabel ? `보호 표지=${protectedLabel}` : '보호 표지 없음' },
|
|
@@ -140,9 +151,12 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
140
151
|
running: { state: running ? 'yes' : runNotRunning ? 'no' : 'unknown', evidence: running ? `run=${input.runStatus ?? 'elanous:running'}` : runNotRunning ? `종결 run=${input.runStatus}` : `run 상태 미관측${input.runStatus ? ` (${input.runStatus})` : ''}` },
|
|
141
152
|
'owner-confirmed': { state: input.ownerConfirmed === undefined ? 'unknown' : input.ownerConfirmed ? 'yes' : 'no', evidence: input.ownerConfirmed === undefined ? '소유자 출처 미관측' : input.ownerConfirmed ? '고유 카드 또는 활성 claim owner 확인' : '고유 소유자 없음' },
|
|
142
153
|
} satisfies DraftTriageAssessment['checks'];
|
|
143
|
-
const
|
|
154
|
+
const missingEvidence = Object.entries(checks).filter(([, check]) => check.state === 'unknown').map(([name]) => name);
|
|
155
|
+
const evidence = [...Object.values(checks).map((check) => check.evidence),
|
|
156
|
+
...(input.lastFailureTail ? [`last failure: ${input.lastFailureTail}`] : [])];
|
|
144
157
|
return { origin, cellId, cardId, gate: input.gate ?? 'unknown', review: input.review ?? 'unknown',
|
|
145
|
-
cellStatus: input.cellStatus ?? 'unknown', nextAction,
|
|
158
|
+
cellStatus: input.cellStatus ?? 'unknown', nextAction, lastFailureTail: input.lastFailureTail ?? null,
|
|
159
|
+
missingEvidence, checks, evidence };
|
|
146
160
|
}
|
|
147
161
|
|
|
148
162
|
export interface DraftTriageInput {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// 📏 실측이 그 분리를 뒷받침한다: 폴백 판정 전수 493 중 `action=grok` ***0건*** —
|
|
19
19
|
// 쿼터 축은 과부하에 «반응하지 않는다».
|
|
20
20
|
import { resolveModelAlias } from '../intelligence-map/model-alias.js';
|
|
21
|
-
import type
|
|
21
|
+
import { getProvider, inferProviderFromModel, resolveReviewModelAlias, type LLMProvider } from '../llm.js';
|
|
22
22
|
import { spawnSync } from 'node:child_process';
|
|
23
23
|
import { claudeBackend, resolveBackendSpawn } from '../agent-mission/driver.js';
|
|
24
24
|
import { checkClaudeSubscription } from '../agent-mission/claude-subscription.js';
|
|
@@ -279,19 +279,57 @@ export function buildReviewProviderAttempts(
|
|
|
279
279
|
primary: ReviewProviderAttempt,
|
|
280
280
|
fallbacks: readonly ReviewProviderAttempt[],
|
|
281
281
|
): ReviewProviderAttempt[] {
|
|
282
|
-
const
|
|
283
|
-
const
|
|
282
|
+
const model = resolveReviewModelAlias(primary.model);
|
|
283
|
+
const inferred = inferProviderFromModel(model);
|
|
284
|
+
const supported = Boolean(inferred && (inferred !== 'local' || model.startsWith('local:') || model.startsWith('local-llm:')));
|
|
285
|
+
let selectedProvider: LLMProvider | undefined;
|
|
286
|
+
if (supported) {
|
|
287
|
+
const provider = getProvider(model);
|
|
288
|
+
if (!primary.provider || primary.provider.name === provider.name) selectedProvider = primary.provider ?? provider;
|
|
289
|
+
}
|
|
290
|
+
if (!selectedProvider) {
|
|
291
|
+
// A malformed/ambiguous configured primary is diagnostic, not fatal: the configured/default
|
|
292
|
+
// fallback attempts below still provide the review. Preserve an unresolved attempt so the
|
|
293
|
+
// runner records its reason, and expose a stable event for operational diagnosis.
|
|
294
|
+
try {
|
|
295
|
+
debug.log('review.fallback', 'primary-unresolved', {
|
|
296
|
+
model: primary.model,
|
|
297
|
+
configuredProvider: primary.provider?.name ?? null,
|
|
298
|
+
}, { level: 'warn' });
|
|
299
|
+
} catch { /* fail-soft */ }
|
|
300
|
+
}
|
|
301
|
+
const normalizedPrimary: ReviewProviderAttempt = {
|
|
302
|
+
...primary,
|
|
303
|
+
model,
|
|
304
|
+
...(selectedProvider ? { provider: selectedProvider } : { provider: undefined }),
|
|
305
|
+
};
|
|
306
|
+
const out: ReviewProviderAttempt[] = [normalizedPrimary];
|
|
307
|
+
const seen = new Set(selectedProvider ? [model] : []);
|
|
284
308
|
for (const f of fallbacks) {
|
|
285
|
-
if (!f.model.trim()
|
|
286
|
-
|
|
287
|
-
|
|
309
|
+
if (!f.model.trim()) continue;
|
|
310
|
+
const fallbackModel = resolveReviewModelAlias(f.model);
|
|
311
|
+
if (seen.has(fallbackModel)) continue;
|
|
312
|
+
const fallbackInference = inferProviderFromModel(fallbackModel);
|
|
313
|
+
if (!fallbackInference || (fallbackInference === 'local' && !fallbackModel.startsWith('local:') && !fallbackModel.startsWith('local-llm:'))) {
|
|
314
|
+
throw new Error(`review fallback: ambiguous or unsupported fallback model "${f.model}"`);
|
|
315
|
+
}
|
|
316
|
+
const fallbackProvider = getProvider(fallbackModel);
|
|
317
|
+
if (f.provider && f.provider.name !== fallbackProvider.name) {
|
|
318
|
+
throw new Error(`review fallback: unsupported provider "${f.provider.name}" for model "${fallbackModel}"`);
|
|
319
|
+
}
|
|
320
|
+
if (normalizedPrimary.provider && (f.provider ?? fallbackProvider).name === normalizedPrimary.provider.name) continue;
|
|
321
|
+
seen.add(fallbackModel);
|
|
322
|
+
const selectedFallbackProvider = f.provider ?? fallbackProvider;
|
|
323
|
+
out.push(f.model === fallbackModel && f.provider === selectedFallbackProvider
|
|
324
|
+
? f : { ...f, model: fallbackModel, provider: selectedFallbackProvider });
|
|
288
325
|
}
|
|
289
326
|
return out;
|
|
290
327
|
}
|
|
291
328
|
|
|
292
329
|
/** A distinct provider is available even when the optional config list is empty. */
|
|
293
330
|
export function defaultReviewFallbackModel(primaryProvider?: string): string {
|
|
294
|
-
|
|
331
|
+
// `claude` is a family label, not a model alias; use the canonical Opus alias for the Claude lane.
|
|
332
|
+
return resolveModelAlias(primaryProvider === 'grok' ? 'opus' : 'grok')!;
|
|
295
333
|
}
|
|
296
334
|
|
|
297
335
|
export interface ReviewFallbackObservation {
|
|
@@ -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
|
+
}
|