elanous 0.2.35 → 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/{T1mBQqmkwKDLGtyisDCOd → 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/{9952.5daf5f94063a2b3e.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/1746.3563617ea64023a3.js +115 -0
- 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/{1dc5a567.9b092bfae3d7099b.js → 1ed5e8af.cf424815c7c0efad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4705-194e64e47ca0fbdb.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/{13.02a07436dec15f89.js → 210.90b2cbd64926cf34.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9512.5a76207a730e0491.js → 2283.edd9627b7bdfb546.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{6866-79aa5b4e47cac6aa.js → 2318-450e75d07605b8fe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{938.66ad1ef0e5abae1c.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/3199.6a1a9b0e6cd01dc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9214.63a510d39178e997.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/{2018.a741297bce759490.js → 4313.76f232c304a15bde.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1165.bad13fc9151a7288.js → 4324.c99ba3e83eb1b691.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3f7c4ee5.3dde54f01a816613.js → 4337e36d.f42c3b391b3d8f20.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7385.50a308a477bdfc21.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/{8557-e7898769499cd56f.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/{5483-dd5d7697f6bdb106.js → 4833-7934c592c5569f00.js} +1 -1
- 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/{8444.4c26b379ca2b9596.js → 4931.95cc6dbd230774ca.js} +17 -17
- 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/{3408.21d1570602f4b6c0.js → 5046.7fd5cbd859299448.js} +1 -1
- 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/58edce7d.f1b0c72acf13b123.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5952.294fc574a8625184.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b6705a4f-b9a9047de9eecfd0.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/6252.240578f10952e091.js +34 -0
- package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5101.e32282718f99ed6f.js → 6680.6a693c28aae4cd19.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4718-17d2af636796a330.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/{6236.e18cced2d5ba6afb.js → 6819.be5c9c4d67f22922.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2833-0fe47af99ed13c29.js → 6971-fb5f9dc0a2cb5d2d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5176c6.6773b6c5994e1d99.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/7424.c0fe2a595d4232b5.js +23 -0
- 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/{7644.17e37ba6f1d4226e.js → 7867.e8725745ddd1d940.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{0368f25d-ad84af92fefee68f.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/{359-2250789a2d3499e7.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/{b2f6ba4d.fb56fdbbf798df33.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/{1530.0e612369b6fd7ea0.js → 9151.a2c51e93f9156dae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4441-875b97f5821ed58a.js → 9175-7d383df15a82e2be.js} +1 -1
- 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/958.53a8dcf4729e6997.js +64 -0
- 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-3337c6a1328c2674.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +1 -0
- 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-fe986fe79b107546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-47c5d4db587266bd.js → page-1e5da297557d2354.js} +1 -1
- 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-1f5a60f70cb4dd0c.js → page-88a1edbff62eaf1d.js} +1 -1
- 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-bac7dee94e5eae4a.js → page-443364c9e4a23b31.js} +1 -1
- 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-dc0a532f5b9196ec.js → page-ac2c1e6169cfce57.js} +1 -1
- 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/{d06f9160.a3d9062f95de8ad7.js → d9815f84.4918f682a45a8502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{cbe38a15.5a032598e39970c6.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/docs/goal-context/05-authoring-lessons.jsonl +47 -0
- package/docs/goal-context/README.md +3 -0
- package/graphs/default-loop.yaml +6 -1
- package/graphs/drafts/recipes.yaml +27 -7
- package/graphs/implement-loop.yaml +24 -0
- package/graphs/release/recipes.yaml +6 -0
- package/graphs/release/release-loop.yaml +17 -4
- package/graphs/wizard/recipes.yaml +44 -0
- package/graphs/wizard/wizard-loop.yaml +44 -0
- 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/research-report.yaml +2 -0
- 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/ci-typecheck-changed.ts +139 -5
- package/scripts/codex-fallback-live-probe.ts +17 -15
- package/scripts/coord-role-pack.ts +1 -1
- package/scripts/first10-gate.ts +416 -0
- package/scripts/fleet/node-setup.sh +32 -2
- package/scripts/fleet/run-light-worker.sh +9 -0
- package/scripts/fleet/wsl-node-setup.sh +432 -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 +344 -8
- package/scripts/release-loop/gate-closure.ts +48 -0
- package/scripts/release-loop/gate-diff.ts +2 -1
- package/scripts/release-loop/gate-node.ts +249 -53
- package/scripts/release-loop/known-issues-node.ts +6 -4
- package/scripts/release-loop/node-verdict.ts +2 -0
- package/scripts/release-loop/notes-repair.ts +216 -0
- package/scripts/release-loop/prepare-node.ts +61 -5
- package/scripts/release-loop/resume-cap.ts +14 -34
- package/scripts/release-loop/resume-release.ts +151 -15
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/traffic-node.ts +59 -0
- package/scripts/release-loop/traffic-transition.ts +159 -0
- package/scripts/release-loop/version-node.ts +81 -12
- package/scripts/rhythm/daily.ts +137 -3
- package/scripts/train/green-leg.ts +176 -0
- package/scripts/tui-continue-real-evidence.ts +47 -0
- package/scripts/ux-sim.ts +53 -0
- package/skills/README.md +1 -0
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +54 -6
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/delegate-hint.ts +16 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/runner.ts +82 -2
- package/src/agent/task-notification.ts +56 -10
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent/types.ts +4 -0
- package/src/agent-substrate/pr-reviewer.ts +64 -4
- package/src/agent-substrate/review-intent.ts +29 -2
- package/src/agent-substrate/review-observation.ts +3 -0
- package/src/agent-substrate/self-review-cli.ts +490 -26
- package/src/autopilot/lineage/sources.ts +1 -1
- package/src/autopilot/mission-codebase-gate.ts +141 -12
- package/src/autopilot/pr-manager.ts +89 -18
- package/src/boot/daemon-runtime.ts +35 -3
- package/src/boot/daemon-tools/pty-shell.ts +2 -1
- package/src/boot/daemon-tools/self-implement.ts +1 -0
- package/src/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/budget/usage-outcomes.ts +8 -4
- package/src/capture/tui-self-report.ts +132 -1
- package/src/chat/goal-continue-verdict.ts +41 -0
- package/src/chat/index.ts +30 -4
- package/src/chat/internal-turn-origin.ts +1 -0
- package/src/chat/paste-fold.ts +86 -0
- package/src/chat/tool-render/block.ts +32 -0
- package/src/chat/tool-render/dispatch.ts +2 -20
- package/src/chat/tool-render/result-text.ts +98 -0
- package/src/chat/turn-typeahead.ts +70 -7
- package/src/cli/autopilot-cli.ts +24 -9
- package/src/cli/config-audit.ts +119 -0
- package/src/cli/decisions-cli.ts +7 -4
- package/src/cli/doctor-cli.ts +137 -6
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/herdr-cli.ts +34 -0
- package/src/cli/light-entry-route.ts +6 -3
- package/src/cli/log-event-names.ts +2 -0
- package/src/cli/logs-cli.ts +357 -2
- package/src/cli/make-cli.ts +247 -11
- package/src/cli/memory-cli.ts +30 -1
- package/src/cli/msg-cli.ts +132 -14
- package/src/cli/pr-cli.ts +29 -16
- package/src/cli/pr-granularity.ts +5 -3
- package/src/cli/pr-land-base-read.ts +11 -2
- package/src/cli/pr-land-heavy-remote.ts +6 -3
- package/src/cli/pr-land-overlap-evidence.ts +23 -4
- package/src/cli/pr-land-recovery.ts +117 -1
- package/src/cli/pty-takeover-cli.ts +8 -7
- package/src/cli/release-checklist-read-cli.ts +109 -4
- package/src/cli/release-cli.ts +64 -15
- package/src/cli/release-single-flight.ts +1 -1
- package/src/cli/self-update.ts +23 -5
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-card-show.ts +162 -0
- package/src/cli/tasks-cli.ts +868 -352
- package/src/cli/tasks-read-cli.ts +197 -0
- 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-core-turn.ts +4 -2
- package/src/core-turn/run-goal-loop.ts +76 -16
- package/src/core-turn/types.ts +8 -1
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/context/keys.ts +8 -31
- package/src/dashboard/index.ts +299 -62
- package/src/dashboard/input/agent-wake.ts +50 -1
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
- package/src/dashboard/input/chat-main-slash-command.ts +4 -2
- package/src/dashboard/input/goal-continue.ts +210 -0
- package/src/dashboard/input/goal-interim.ts +2 -0
- package/src/dashboard/input/internal-turn.ts +2 -8
- package/src/dashboard/input/seat-autowake.ts +9 -7
- package/src/dashboard/input/turn-autoheal.ts +52 -0
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/seat-boot-preamble.ts +132 -5
- package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -10
- package/src/dashboard/slash-runtime/model-choices.ts +15 -0
- package/src/dashboard/stale-install-check.ts +3 -99
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/debug/batch-queue.ts +119 -0
- package/src/debug/tui-log-tag.ts +67 -0
- package/src/display/agent-surface.ts +7 -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/standalone-log-sink.ts +15 -2
- package/src/domains/surface-events.ts +80 -1
- package/src/esc-abort-gate.ts +69 -0
- package/src/exec-requests/planner.ts +37 -2
- package/src/execution-loop/launch-gate.ts +4 -3
- package/src/git-fs/cli-stderr.ts +45 -0
- package/src/git-fs/gh-cli.ts +6 -3
- package/src/git-fs/git-cli.ts +11 -5
- package/src/git-fs/worktree.ts +95 -1
- package/src/graph-runner/graph-cli.ts +44 -2
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +37 -16
- package/src/graph-wizard/generate.ts +131 -4
- package/src/graph-wizard/steps.ts +15 -0
- package/src/grounding/proactive-ground.ts +86 -0
- package/src/harness/control-inbox.ts +49 -1
- package/src/harness/harness-cli-command.ts +230 -40
- package/src/harness/harness-incidents.ts +52 -1
- package/src/harness/pod-control-send.ts +33 -5
- package/src/harness/review-adapter.ts +26 -6
- package/src/harness/self-send-remote.ts +69 -0
- package/src/harness/self-send-routing-guard.ts +6 -0
- package/src/harness/self-send-target.ts +4 -3
- package/src/index.ts +443 -25
- package/src/input-core/context-key-runtime.ts +21 -0
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/light-cli.ts +6 -1
- 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-wellformed.ts +70 -0
- package/src/llm.ts +158 -15
- 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/msg-wake.ts +35 -39
- package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
- package/src/loops/orchestrator/inbox.ts +59 -11
- package/src/loops/orchestrator/knowhow-pack.ts +364 -0
- package/src/loops/orchestrator/tick.ts +54 -5
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/model-tier/llm-tier-map.ts +12 -17
- package/src/models/prompts.ts +17 -2
- package/src/msg/msg-post-office.ts +116 -0
- package/src/msg/msg-store.ts +17 -0
- package/src/mss/logging/log-store.ts +79 -22
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/decisions-route.ts +38 -18
- package/src/nexus/api/graph-wizard-api.ts +46 -3
- 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/boot/register-mcp-clients.ts +263 -38
- package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
- package/src/nexus/state/state.ts +7 -1
- package/src/oauth/codex-account-store.ts +34 -1
- package/src/onboarding/first-run.ts +37 -6
- package/src/onboarding/web-first.ts +43 -11
- package/src/ops/loops-map.ts +46 -0
- package/src/ops/overview-cache.ts +22 -4
- package/src/ops/overview-collect.ts +12 -6
- package/src/ops/overview.ts +44 -8
- package/src/persona/loader.ts +11 -0
- package/src/persona/types.ts +8 -0
- package/src/policy/llm-policy.ts +3 -1
- package/src/prompt-enhance/enhance.ts +4 -4
- package/src/prompt-library/session-guidance.ts +14 -0
- package/src/provider-summary.ts +8 -0
- package/src/pty-shell/availability.ts +7 -0
- package/src/pty-shell/herdr-agent-report.ts +155 -37
- package/src/pty-shell/herdr-prompt.ts +266 -0
- 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 +327 -15
- package/src/pty-shell/pty-special-keys.ts +42 -2
- package/src/pty-shell/registry.ts +25 -15
- package/src/pty-shell/stale-install-check.ts +99 -0
- package/src/pty-shell/tui-run-state.ts +249 -3
- package/src/release-loop/auto-start.ts +20 -2
- package/src/release-loop/checklist.ts +126 -9
- package/src/release-loop/feature-store.ts +9 -9
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/release-loop/rehearsal.ts +36 -20
- package/src/repl/index.ts +27 -1
- package/src/seat-loop/knowhow-lint.ts +1 -1
- 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 +183 -20
- package/src/self-dev/decompose.ts +61 -0
- package/src/self-dev/dev-cli.ts +37 -3
- package/src/self-dev/dev-pipeline.ts +37 -9
- package/src/self-dev/draft-sweep.ts +241 -16
- package/src/self-dev/draft-triage-rules.ts +50 -5
- package/src/self-dev/glm-credential-guard.ts +77 -0
- package/src/self-dev/graph-journey-nodes.ts +1 -0
- package/src/self-dev/graph-journey-route.ts +12 -2
- package/src/self-dev/orchestrate-cli.ts +68 -3
- package/src/self-dev/orchestrate.ts +116 -17
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/run-supervisor.ts +55 -2
- package/src/self-dev/run-types.ts +1 -1
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +50 -3
- package/src/self-health/autoheal.ts +153 -0
- package/src/self-health/signatures.ts +6 -0
- package/src/self-implement/device-first.ts +116 -0
- package/src/self-implement/doctor-visit.ts +322 -1
- package/src/self-implement/evidence-command-budget.ts +80 -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-cli.ts +1 -0
- package/src/self-implement/goal-author-decompose.ts +265 -4
- package/src/self-implement/goal-author.ts +366 -26
- package/src/self-implement/goal-elaborate.ts +176 -22
- package/src/self-implement/goal-refine.ts +3 -0
- package/src/self-implement/goal-supervisor-fill.ts +75 -26
- package/src/self-implement/graph-variant.ts +40 -6
- package/src/self-implement/headless-elanous-driver.ts +19 -3
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +5 -5
- package/src/self-implement/off-diff-evidence.ts +58 -6
- package/src/self-implement/orchestrator.ts +536 -42
- package/src/self-implement/pod-warm-pool-profile.ts +1 -0
- package/src/self-implement/pwa-import-graph.ts +1 -1
- package/src/self-implement/review-round-brief.ts +300 -0
- package/src/self-implement/rework-policy.ts +44 -0
- package/src/self-implement/run-ledger.ts +278 -6
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/run-ttl.ts +38 -24
- package/src/self-implement/running-runs.ts +17 -3
- package/src/self-implement/scope-adjacency.ts +3 -1
- package/src/self-implement/seams.ts +72 -10
- 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/self-implement/wiring-check.ts +358 -0
- 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/shell-env-bootstrap.ts +11 -4
- package/src/skills/runner.ts +4 -2
- package/src/skills/tools/agent.ts +290 -48
- package/src/skills/tools/pty.ts +5 -0
- package/src/skills/tools/schedule-wakeup.ts +23 -4
- package/src/skills/tools/shell.ts +61 -6
- package/src/skills/tools/terminal-modal-inject.ts +1 -2
- package/src/skills/tools/terminal-modal.ts +10 -8
- package/src/skills/url-router.ts +41 -1
- package/src/smart-wizard/run.ts +66 -0
- package/src/status/bar.ts +34 -6
- package/src/status/metrics.ts +12 -1
- package/src/status/status-provider-info.ts +37 -6
- package/src/steward/rejudge-tick.ts +22 -7
- package/src/steward/resync-tick.ts +31 -4
- package/src/steward/ta-repair-event-collect.ts +17 -6
- package/src/task-agent/actions.ts +202 -5
- 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/land-queue.ts +21 -8
- package/src/task-agent/live-moves.ts +70 -9
- 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/mission.ts +30 -0
- package/src/task-agent/parent-host.ts +21 -11
- package/src/task-agent/rejudge-on-head.ts +87 -5
- package/src/task-agent/repair-cycle.ts +179 -32
- package/src/task-agent/repair-next-move.ts +42 -4
- package/src/task-agent/repair-outcomes.ts +29 -0
- package/src/task-agent/repair-worker.ts +14 -4
- package/src/task-agent/review-prior-fix.ts +12 -2
- package/src/task-agent/shadow.ts +229 -8
- package/src/task-agent/task-card-prefix.ts +2 -0
- package/src/task-agent/task-hand.ts +630 -30
- package/src/task-agent/task-parent-role-llm.ts +45 -0
- package/src/task-agent/tier-split.ts +80 -10
- 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-account-broker.ts +9 -0
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
- package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +86 -5
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
- package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
- 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-manifest-test-normalize.ts +11 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +126 -8
- package/src/task-orchestrator/surfaces/pod-provenance.ts +8 -2
- package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
- package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +491 -36
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +612 -54
- package/src/task-orchestrator/surfaces/self-implement.ts +46 -2
- package/src/testing/linux-env.ts +177 -0
- package/src/tool-runtime/index.ts +15 -2
- package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
- package/src/tty-foreground.ts +155 -0
- package/src/tui/chat/goal-interim.ts +177 -0
- package/src/tui/chat/log-view.ts +205 -18
- package/src/tui/chat/self-health-status.ts +232 -0
- package/src/tui/entry.ts +623 -80
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/input/composer.ts +8 -1
- package/src/tui/slash/compact-command.ts +7 -0
- package/src/tui/slash/compact.ts +1 -7
- package/src/tui/slash/resume.ts +98 -0
- 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 +49 -5
- package/src/tui-client/next-dashboard-runtime.ts +8 -0
- package/src/tui-client/next-loop-command.ts +70 -0
- package/src/tui-client/next-wakeup.ts +191 -0
- package/src/tui.ts +37 -0
- package/src/ui/modal-adapter.ts +2 -2
- 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 +670 -0
- package/src/ux-sim/cli-config-audit-device.ts +121 -0
- package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
- package/src/ux-sim/event-monkey.ts +3 -2
- package/src/ux-sim/fake-bin.ts +45 -0
- package/src/ux-sim/fake-gh.ts +174 -0
- package/src/ux-sim/fake-herdr.ts +238 -0
- package/src/ux-sim/fake-kubectl.ts +142 -0
- package/src/ux-sim/fake-llm.ts +116 -6
- package/src/ux-sim/fault-glm-no-credential.ts +116 -0
- package/src/ux-sim/fault-nextmove-dispatch.ts +102 -1
- package/src/ux-sim/fault-scope-escape-lift.ts +33 -6
- package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
- package/src/ux-sim/goal-device.ts +619 -0
- package/src/ux-sim/in-process-cli.ts +22 -5
- package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
- package/src/ux-sim/mock-authoring-first-run.ts +97 -0
- package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
- package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
- package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
- package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
- package/src/ux-sim/next-tui-seat-scenarios.ts +749 -0
- package/src/ux-sim/onboarding-first-run-device.ts +269 -0
- package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
- 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/subagent-tools-device.ts +81 -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/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
- package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +0 -41
- package/apps/pwa/out/_next/static/chunks/1674.2a65fd5668e1cc5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +0 -24
- package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +0 -74
- package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1993-c0007b7ad0c0ef41.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +0 -148
- package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2625.5d870aa999f33db1.js +0 -34
- package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +0 -77
- package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +0 -62
- package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +0 -90
- package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +0 -36
- package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3677-4215f826f6aa68e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4346.8601952e73bf5803.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +0 -24
- package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +0 -23
- package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/56d372f2.681ab4ec4c998fae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +0 -287
- package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +0 -1
- package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +0 -8
- package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +0 -93
- package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6b89c8bd.24df687a820500b3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +0 -149
- package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +0 -104
- package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8219.baa715d1deee80e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +0 -226
- package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +0 -64
- package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8637.47f5b35afcae5e6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +0 -115
- package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/967-2aa39b2d04b4c690.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-406b47745b53f269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +0 -1
- /package/apps/pwa/out/_next/static/{T1mBQqmkwKDLGtyisDCOd → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* - 기본은 SHADOW: 카드와 명령만 남기고 아무것도 띄우지 않는다. `--live` 일 때만 주입된 launcher 로 띄운다.
|
|
8
8
|
* - 관측: `debug.log('task-agent', 'handed', {taskId, seat, checklistId, mode, runPriority})`.
|
|
9
9
|
*/
|
|
10
|
-
import { execFileSync } from 'node:child_process';
|
|
10
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
11
11
|
import { createHash, randomBytes } from 'node:crypto';
|
|
12
12
|
import { mkdirSync, readFileSync, statSync, writeFileSync, type Stats } from 'node:fs';
|
|
13
13
|
import { dirname, join, posix, resolve } from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { parse as parseYaml } from 'yaml';
|
|
16
|
-
import { validateUnitCalls } from '../graph-runner/runner.js';
|
|
16
|
+
import { runGraph, validateUnitCalls, type GraphRunOptions, type GraphRunState } from '../graph-runner/runner.js';
|
|
17
17
|
import { parseGraphTemplateYaml } from '../self-implement/graph-yaml.js';
|
|
18
18
|
import { resolveDaemonHarnessTarget } from '../intake-plane/harness-target.js';
|
|
19
19
|
import { HARNESS_RUN_ID_ENV, mintRunId, normalizeRunId } from '../harness/harness-space.js';
|
|
@@ -25,14 +25,20 @@ import { checkCompletionEvidence, deliverableReceiptEvidence } from './completio
|
|
|
25
25
|
import { judgeNextMove } from './judge.js';
|
|
26
26
|
import { checklistDevVersion, listChecklist } from '../release-loop/checklist.js';
|
|
27
27
|
import { loadRunLedger, runLedgerDir } from '../self-implement/run-ledger.js';
|
|
28
|
+
// Keep doctor-visit recording synchronous: updateTaskCard callers observe it before the transition returns.
|
|
29
|
+
import { recordTaskAgentNeedsOwnerVisit } from '../self-implement/doctor-visit.js';
|
|
28
30
|
import { applyRunIdentityTag, applyRunIdentityTags, deriveBirthIdentity, parseRunIdentityTag, runIdentityFieldText, runIdentityQueuePriority, runPriorityClass, validateRunIdentity, type RunIdentity, type RunIdentityCell, type RunIdentityOrigin } from './run-identity.js';
|
|
29
31
|
import { parseWorkOrder, renderWorkOrderGoal, WORK_ORDER_FILE_PATTERN, type WorkOrder } from './work-order.js';
|
|
30
32
|
import { inspectPrelaunchAlreadyDone, type AlreadyDoneDecision, type AlreadyDoneCandidate,
|
|
31
33
|
type PrelaunchGitRunnerForTest } from './prelaunch-already-done.js';
|
|
32
|
-
import { draftReleaseComment } from '../self-dev/draft-triage-rules.js';
|
|
33
|
-
import { parseAskTargetPathHints, parseAskTargetPathHintsResult } from '../self-dev/launch-preflight-text.js';
|
|
34
|
-
import { inspectGoalDoneBoundary } from '../self-implement/goal-author.js';
|
|
34
|
+
import { draftClaimComment, draftClaimRecordLive, draftClaimState, draftReleaseComment } from '../self-dev/draft-triage-rules.js';
|
|
35
|
+
import { parseAskTargetPathHints, parseAskTargetPathHintsResult, type AskTargetPathHintsParseResult } from '../self-dev/launch-preflight-text.js';
|
|
36
|
+
import { inspectGoalDoneBoundary, linesOutsideFencedCode } from '../self-implement/goal-author.js';
|
|
37
|
+
import { selectKnowhowPack } from '../self-implement/knowhow-pack.js';
|
|
35
38
|
import { INFLIGHT_REGISTRY_FILE, registerInflight } from '../pr-tool/inflight-registry.js';
|
|
39
|
+
import { taskParentRoleEnv, taskParentRolePinsForChild } from './task-parent-role-llm.js';
|
|
40
|
+
import { runHarvestUnit, type ReviewInvocation } from './harvest-unit.js';
|
|
41
|
+
import { TASK_CARD_PREFIX } from './task-card-prefix.js';
|
|
36
42
|
|
|
37
43
|
export interface ResolveHandTextDeps {
|
|
38
44
|
cwd: string;
|
|
@@ -88,8 +94,8 @@ export function resolveHandText(text: string, deps: ResolveHandTextDeps = { cwd:
|
|
|
88
94
|
|
|
89
95
|
export const TASK_SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
|
|
90
96
|
export type TaskSeat = typeof TASK_SEATS[number];
|
|
91
|
-
/** 과제 카드 id 접두 — `task show <id>` 가 이 접두로 TOX 태스크와
|
|
92
|
-
export
|
|
97
|
+
/** 과제 카드 id 접두 — `task show <id>` 가 이 접두로 TOX 태스크와 갈린다(정본 = task-card-prefix.ts). */
|
|
98
|
+
export { TASK_CARD_PREFIX };
|
|
93
99
|
/** Pod Job 의 metadata.labels 에 붙일 카드 식별자 — 원장의 카드 id 와 정확히 같아야 한다. */
|
|
94
100
|
export const TASK_CARD_LABEL = 'elanous.task-card';
|
|
95
101
|
/**
|
|
@@ -119,6 +125,43 @@ export function taskCardLabelContext(card: Pick<TaskCard, 'id'>): TaskCardLabelC
|
|
|
119
125
|
export const COMPLETION_KINDS = ['code-pr', 'artifact', 'research-report', 'ops-action', 'content', 'watch-brief', 'decision-support', 'deliverable'] as const;
|
|
120
126
|
export type CompletionKind = typeof COMPLETION_KINDS[number];
|
|
121
127
|
|
|
128
|
+
/** «실행·조사» 손의 조합 — 종결 종류별 조합이 아직 없을 때 그 손이 기본으로 쓰는 판(조사 make-doc ⊕ 확인 verify). */
|
|
129
|
+
export const RUN_RESEARCH_COMPOSITION = 'graphs/work/run-research.yaml';
|
|
130
|
+
|
|
131
|
+
/** 기본 손 묶음 — «개발»(자식 구현 런·PR 착지 = 코드 하니스) 또는 «실행·조사»(비코드 종결 다섯 ⊕ 콘텐츠·전달). */
|
|
132
|
+
export type DefaultHand = 'develop' | 'run-research';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* DEFAULT-HANDS — 종결 종류마다 과제 담당이 기본으로 쥐는 손과 그 «확인 증거»(RFC-loop-agent-map §A4c).
|
|
136
|
+
* 기본은 «개발»이 아니라 «실행·조사»다: 마케터·산업 현장·선생님·C 레벨이 자기 일을 그대로 맡긴다.
|
|
137
|
+
* 코드 하니스(`harness-say` 자식 구현 런 · PR 착지)는 개발자 팩(`code-pr`)만 쓴다.
|
|
138
|
+
*/
|
|
139
|
+
export interface DefaultHandSpec {
|
|
140
|
+
hand: DefaultHand;
|
|
141
|
+
/** 확인 증거 — 종류별 판정 규칙의 이름(정본 = `completion-evidence.ts` `checkCompletionEvidence`). */
|
|
142
|
+
evidence: string;
|
|
143
|
+
/** 종류별 조합 파일이 없을 때 그 손이 기본으로 쓰는 조합. */
|
|
144
|
+
composition: string;
|
|
145
|
+
/** 코드 하니스(자식 구현 런·PR 병합)를 쓰나 — 개발자 팩 전용. */
|
|
146
|
+
codeHarness: boolean;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const DEFAULT_HANDS: Record<CompletionKind, DefaultHandSpec> = {
|
|
150
|
+
'code-pr': { hand: 'develop', evidence: '구현 — PR 병합', composition: 'graphs/work/code-pr.yaml', codeHarness: true },
|
|
151
|
+
'research-report': { hand: 'run-research', evidence: '조사 — 출처 인용 보고(출처 ⊕ 반대 근거)', composition: 'graphs/work/research-report.yaml', codeHarness: false },
|
|
152
|
+
artifact: { hand: 'run-research', evidence: '산출물 — 파일 ⊕ 미리보기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
153
|
+
content: { hand: 'run-research', evidence: '콘텐츠 — 파일 ⊕ 미리보기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
154
|
+
'ops-action': { hand: 'run-research', evidence: '실행 — 실행 기록 ⊕ 되읽기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
155
|
+
'watch-brief': { hand: 'run-research', evidence: '감시·브리핑 — 일정 ⊕ 도착', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
156
|
+
'decision-support': { hand: 'run-research', evidence: '결정 지원 — 카드 ⊕ 기록', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
157
|
+
deliverable: { hand: 'run-research', evidence: '전달 — 산출물 ⊕ 수신 확인', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/** 카드의 종결 종류가 기본으로 받는 손 — 비면 code-pr(=개발)다. */
|
|
161
|
+
export function defaultHandOf(completion: CompletionKind | undefined): DefaultHand {
|
|
162
|
+
return DEFAULT_HANDS[completion ?? 'code-pr'].hand;
|
|
163
|
+
}
|
|
164
|
+
|
|
122
165
|
export interface TaskComposition {
|
|
123
166
|
file: string;
|
|
124
167
|
/** null = 파일은 있으나 파싱 실패로 판을 확인하지 못했다. */
|
|
@@ -133,15 +176,32 @@ export interface CompositionSelection {
|
|
|
133
176
|
error?: string;
|
|
134
177
|
}
|
|
135
178
|
|
|
179
|
+
/** 조합 저장소 루트(기본) — `graphs/work/<completion>.yaml` 는 이 루트에서 읽는다. */
|
|
180
|
+
export const COMPOSITION_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
181
|
+
|
|
136
182
|
/** 1판은 조합을 고르고 단위 해석 결과를 기록한다. 단위 실행은 2판의 몫이다. */
|
|
137
|
-
export function selectTaskComposition(completion: CompletionKind, root =
|
|
138
|
-
const
|
|
139
|
-
|
|
183
|
+
export function selectTaskComposition(completion: CompletionKind, root = COMPOSITION_ROOT): CompositionSelection {
|
|
184
|
+
const requested = `graphs/work/${completion}.yaml`;
|
|
185
|
+
// DEFAULT-HANDS — 종류별 조합이 없으면 그 손의 기본 조합(«실행·조사»)으로 내려간다.
|
|
186
|
+
// 비개발 종결이 «조합 없음»으로 막히면 사람별 표본이 과제 담당에 닿지도 못한다.
|
|
187
|
+
let file = requested;
|
|
188
|
+
let path = join(root, file);
|
|
140
189
|
let source: string;
|
|
141
190
|
try { source = readFileSync(path, 'utf8'); } catch (error) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
191
|
+
const missing = (error as NodeJS.ErrnoException)?.code === 'ENOENT';
|
|
192
|
+
if (!missing) {
|
|
193
|
+
return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
|
|
194
|
+
error: `조합 읽기 오류: ${file}: ${error instanceof Error ? error.message : String(error)}` };
|
|
195
|
+
}
|
|
196
|
+
const fallback = DEFAULT_HANDS[completion].composition;
|
|
197
|
+
if (fallback === requested) return { unitsResolved: false, missingUnits: [] };
|
|
198
|
+
file = fallback;
|
|
199
|
+
path = join(root, file);
|
|
200
|
+
try { source = readFileSync(path, 'utf8'); } catch (fallbackError) {
|
|
201
|
+
if ((fallbackError as NodeJS.ErrnoException)?.code === 'ENOENT') return { unitsResolved: false, missingUnits: [] };
|
|
202
|
+
return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
|
|
203
|
+
error: `조합 읽기 오류: ${file}: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}` };
|
|
204
|
+
}
|
|
145
205
|
}
|
|
146
206
|
const parsed = parseGraphTemplateYaml(source, path);
|
|
147
207
|
if (!parsed.template || parsed.errors.length) {
|
|
@@ -198,6 +258,9 @@ export interface TaskCardEvent {
|
|
|
198
258
|
verdict?: string | null; reviewed?: boolean | null; mustFix?: number | null; reviewRoute?: string | null;
|
|
199
259
|
/** Exact bytes of the captured review stdout; repair must read the same resultPath and digest. */
|
|
200
260
|
reviewSha256?: string;
|
|
261
|
+
/** HARNESS-FULL-GRAPH-NEXTMOVE — next-move 결정 순간 만든 수 id(간선·발사와 같은 값). `repair-launched` · `relaunch-launched`(일반 재발사) ·
|
|
262
|
+
* `repair-result`(결과 파일의 값이 카드와 짝지어졌을 때만 · NEXTMOVE-GENERAL-RELAUNCH-MOVEID) 줄에 싣는다. */
|
|
263
|
+
moveId?: string;
|
|
201
264
|
}
|
|
202
265
|
/** 카드 history 의 live-move 줄 이벤트 이름 — 상태 사유(«마지막 칸») 판정에서 뺀다. */
|
|
203
266
|
export const LIVE_MOVE_HISTORY_EVENT = 'live-move';
|
|
@@ -262,6 +325,11 @@ export interface TaskCard {
|
|
|
262
325
|
goalId?: string;
|
|
263
326
|
/** `manual` = pr/goalId 를 사람이 적었다(`recordPieceRef`) — 런 묶기가 건드리지 않는다. */
|
|
264
327
|
refSource?: 'manual';
|
|
328
|
+
/**
|
|
329
|
+
* DRAFT-CLAIM-AUTO-2-FU — 이 손이 그 draft 로 남긴 claim 기록. `body` 는 PR 에 달 «🔧 처리 중» 문면이고
|
|
330
|
+
* claim 이 성립한 손만 갖는다(수확이 머리를 확정하지 못하면 `body` 없이 `harvest` 사유만 남는다).
|
|
331
|
+
*/
|
|
332
|
+
draftClaim?: TaskCardDraftClaimRecord;
|
|
265
333
|
/** 조각 카드만 — ② 가 선행 착지 뒤 넘겼다(한 번만 · 같은 잠금 안에서 먼저 적는다). */
|
|
266
334
|
handed?: { at: string; mode: 'shadow' | 'live'; claim?: string; error?: string };
|
|
267
335
|
/**
|
|
@@ -301,6 +369,8 @@ export interface TaskCard {
|
|
|
301
369
|
taLand?: true;
|
|
302
370
|
/** TASKS-HAND-CHILD-LLM — `tasks hand --child-llm <provider>/<model> [--child-llm-effort <level>]` → 발사 인자 `--child-llm-provider/-model/-effort`. */
|
|
303
371
|
childLlm?: TaskChildLlm;
|
|
372
|
+
/** Explicit parent role pins; the implementation child remains controlled by childLlm. */
|
|
373
|
+
parentRoleLlm?: string[];
|
|
304
374
|
/** Dispatch difficulty, fixed at handoff so repair uses the same judgement. */
|
|
305
375
|
tier?: '하' | '중' | '상' | '특';
|
|
306
376
|
/**
|
|
@@ -313,7 +383,9 @@ export interface TaskCard {
|
|
|
313
383
|
/** Same-PR repair launches; exact source head and worker result are retained for CAS and retry limits. */
|
|
314
384
|
repairs?: Array<{ pr: number; head: string; branch: string; at: string; move: string; runId: string;
|
|
315
385
|
resultPath: string; fromModel: string; toModel: string; status: 'requested' | 'unconfirmed' | 'failed' | 'applied';
|
|
316
|
-
detail?: string; commit?: string; bundleSha256?: string; bundlePath?: string
|
|
386
|
+
detail?: string; commit?: string; bundleSha256?: string; bundlePath?: string;
|
|
387
|
+
/** HARNESS-FULL-GRAPH-NEXTMOVE — next-move 결정 순간 만든 수 id. 이 칸 전 원장 줄엔 없다. */
|
|
388
|
+
moveId?: string }>;
|
|
317
389
|
}
|
|
318
390
|
|
|
319
391
|
/** 구현 자식 LLM 선택 — 하니스 `--child-llm-provider/--child-llm-model/--child-llm-effort` 로 그대로 넘긴다(검증 권위는 하니스). */
|
|
@@ -362,14 +434,295 @@ export function abandonedDraftReleaseNote(card: Pick<TaskCard, 'id' | 'status' |
|
|
|
362
434
|
|
|
363
435
|
/** A uniquely launched code-PR card may own a draft through its PR or its opening run. */
|
|
364
436
|
export function draftTaskOwner(cards: readonly TaskCard[], draft: { number: number; runId?: string | null }): TaskCard | undefined {
|
|
365
|
-
const owners = cards
|
|
437
|
+
const owners = draftTaskOwners(cards, draft);
|
|
438
|
+
return owners.length === 1 ? owners[0] : undefined;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* DRAFT-CLAIM-AUTO-2-FU — 그 draft 를 쥐고 있다고 말하는 카드 «전부». `draftTaskOwner` 는 이 목록이 한 장일 때만
|
|
443
|
+
* 주인을 돌려주므로, 두 장 이상이면 어느 쪽이 진짜인지 모른다 = 중복 claim.
|
|
444
|
+
*/
|
|
445
|
+
export function draftTaskOwners(cards: readonly TaskCard[], draft: { number: number; runId?: string | null }): TaskCard[] {
|
|
446
|
+
return cards.filter((card) => card.status === 'launched' && (card.completion ?? 'code-pr') === 'code-pr'
|
|
366
447
|
&& card.seat && (card.runId || card.runChildId) && (cardPrNumber(card) === draft.number
|
|
367
448
|
|| (draft.runId && (card.runId === draft.runId || card.runChildId === draft.runId))));
|
|
368
|
-
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 손이 draft 하나를 잡을 때의 «지금» 관측값(라벨·갱신 시각은 호출자가 관측해 넘긴다). */
|
|
452
|
+
export interface HandTaskDraftClaim {
|
|
453
|
+
/** 관측한 draft PR 번호 — 손이 잡으려는 PR. 카드에 묶인 PR 과 같은 번호다. */
|
|
454
|
+
pr: number;
|
|
455
|
+
/** 그 PR 의 지금 라벨(claim·harvestable 판정 입력 · `draftClaimState`). */
|
|
456
|
+
labels: readonly string[];
|
|
457
|
+
/** 그 PR 의 마지막 갱신 시각 — 없으면 만료인지 아닌지 모르므로 claim 하지 않는다. */
|
|
458
|
+
updatedAt?: string;
|
|
459
|
+
/** 그 PR 을 연 런 id(카드 묶기 키 — `draftTaskOwner`). */
|
|
460
|
+
runId?: string | null;
|
|
461
|
+
/** 손 수확 — 리뷰 결과로 머리를 확정한 «뒤에만» claim 한다. */
|
|
462
|
+
harvest?: HandTaskDraftHarvest;
|
|
463
|
+
/** DRAFT-CLAIM-AUTO-2-FU — claim 문면을 «실제 PR 댓글»로 게시하는 포트. 생산 배선(`tasks hand --draft-claim <pr>`)이 gh 게시자를 준다. 없으면 `body` 를 카드에만 남긴다. */
|
|
464
|
+
postComment?: (pr: number, body: string) => Promise<string | undefined>;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손 수확: 그 머리에서 리뷰를 다시 받아 수확이 성립할 때만 claim 한다.
|
|
469
|
+
* 생산 배선(`handDraftClaim`)이 관측한 PR 머리(`expectedHead`) ⊕ 포트의 리뷰 러너(`invokeReview`)로 조립한다.
|
|
470
|
+
*/
|
|
471
|
+
export interface HandTaskDraftHarvest {
|
|
472
|
+
/** 리뷰를 요청한 머리(40-hex) — 없거나 지금 머리와 다르면 수확은 성립하지 않는다(claim 0). */
|
|
473
|
+
expectedHead?: string;
|
|
474
|
+
/** 리뷰 의도 문면(없으면 손 문면을 쓴다). */
|
|
475
|
+
reviewIntent?: string;
|
|
476
|
+
/** `elanous self review <pr> --json` 를 부르는 자리 — 호출자(관측 포트)가 준다. */
|
|
477
|
+
invokeReview: (args: { pr: string; intent: string }) => Promise<ReviewInvocation>;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 카드에 남는 claim 기록. */
|
|
481
|
+
export interface TaskCardDraftClaimRecord {
|
|
482
|
+
pr: number;
|
|
483
|
+
at: string;
|
|
484
|
+
/** 만료된 claim 을 다시 잡았나(= 재claim). */
|
|
485
|
+
reclaim: boolean;
|
|
486
|
+
/** PR 에 달 «🔧 처리 중» 문면 — claim 이 성립한 손만. */
|
|
487
|
+
body?: string;
|
|
488
|
+
/** shadow 는 게시 예약이 아니므로 live claim 을 막지 않는다. 옛 기록은 live 로 취급한다. */
|
|
489
|
+
mode?: 'shadow' | 'live';
|
|
490
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 게시한 PR 댓글 위치(댓글 url·id · `postComment` 포트가 있는 생산 경로만). */
|
|
491
|
+
postedTo?: string;
|
|
492
|
+
/** 쥐고 있던 카드 id(관측됐을 때). */
|
|
493
|
+
ownerId?: string;
|
|
494
|
+
/** 손 수확 증거 — 머리를 확정하지 못했으면 `outcome`·`reason` 만 있고 `body` 는 없다. */
|
|
495
|
+
harvest?: { outcome: 'done' | 'rework' | 'needs-human' | 'failed'; headCommit?: string; reason?: string };
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 이 손이 draft 를 잡아도 되나(중복 claim 거부 · 만료된 claim 만 재claim). */
|
|
499
|
+
export type DraftClaimJudgement =
|
|
500
|
+
| { ok: true; body: string; reclaim: boolean; ownerId?: string }
|
|
501
|
+
| { ok: false; reason: string; ownerId?: string };
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* DRAFT-CLAIM-AUTO-2-FU — 판정선: ⑴ 두 장 이상의 카드가 같은 draft 를 쥐고 있으면 거부(어느 쪽이 진짜인지 모른다),
|
|
505
|
+
* ⑵ 갱신 시각을 못 읽으면(`unobserved`) 만료인지 알 수 없으니 거부, ⑶ 살아 있는 claim 을 다른 카드가 쥐고 있으면 거부
|
|
506
|
+
* (중복 claim), ⑷ 다른 카드에 남은 «살아 있는» claim 기록(카드 `draftClaim`)이 같은 PR 을 쥐고 있으면 거부 —
|
|
507
|
+
* 연속된 손 호출이 «같은» draft 를 다시 claim 하지 못하게(launched 카드의 PR·런 소유권 가드만으는 부족하다),
|
|
508
|
+
* ⑸ «만료»로 관측된 claim 만 다시 잡는다(재claim 문면).
|
|
509
|
+
*/
|
|
510
|
+
export function judgeDraftClaim(input: {
|
|
511
|
+
draft: { number: number; labels: readonly string[]; updatedAt?: string; runId?: string | null };
|
|
512
|
+
cards: readonly TaskCard[];
|
|
513
|
+
cardId: string;
|
|
514
|
+
seat?: TaskSeat;
|
|
515
|
+
now: Date;
|
|
516
|
+
}): DraftClaimJudgement {
|
|
517
|
+
const owners = draftTaskOwners(input.cards, input.draft);
|
|
518
|
+
if (owners.length > 1) {
|
|
519
|
+
return { ok: false, reason: `duplicate-claim: ${owners.map((card) => card.id).join(', ')} 가 같은 PR #${input.draft.number} 를 쥐고 있다` };
|
|
520
|
+
}
|
|
521
|
+
const owner = owners[0];
|
|
522
|
+
const state = draftClaimState(input.draft, input.now);
|
|
523
|
+
if (state === 'unobserved') {
|
|
524
|
+
return { ok: false, ...(owner ? { ownerId: owner.id } : {}), reason: `claim-unobserved: PR #${input.draft.number} 의 claim 시각을 못 읽었다` };
|
|
525
|
+
}
|
|
526
|
+
if (state === 'claimed' && owner?.id !== input.cardId) {
|
|
527
|
+
return {
|
|
528
|
+
ok: false,
|
|
529
|
+
...(owner ? { ownerId: owner.id } : {}),
|
|
530
|
+
reason: `duplicate-claim: ${owner ? owner.id : '카드 원장 밖 주인'} 가 PR #${input.draft.number} 를 처리 중이다`,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
const recordOwner = input.cards.find((card) => {
|
|
534
|
+
const record = card.draftClaim;
|
|
535
|
+
return card.id !== input.cardId && record !== undefined && record.pr === input.draft.number
|
|
536
|
+
&& record.body !== undefined && record.mode !== 'shadow' && draftClaimRecordLive(record.at, input.now);
|
|
537
|
+
});
|
|
538
|
+
if (recordOwner) {
|
|
539
|
+
return { ok: false, ownerId: recordOwner.id, reason: `duplicate-claim: 카드 ${recordOwner.id} 가 PR #${input.draft.number} 의 claim 기록을 쥐고 있다` };
|
|
540
|
+
}
|
|
541
|
+
const reclaim = state === 'expired';
|
|
542
|
+
return {
|
|
543
|
+
ok: true,
|
|
544
|
+
reclaim,
|
|
545
|
+
...(owner ? { ownerId: owner.id } : {}),
|
|
546
|
+
body: draftClaimComment(input.seat ?? input.cardId, input.now, reclaim ? '만료 claim 재claim — 자동' : undefined),
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 그 draft 를 이미 다른 카드가 쥐고 있다(또는 만료인지 못 정한다). 이때 카드는 «쓰지 않는다». */
|
|
551
|
+
export class TaskDraftClaimRejectedError extends Error {
|
|
552
|
+
readonly cardId: string;
|
|
553
|
+
readonly reason: string;
|
|
554
|
+
constructor(cardId: string, reason: string) {
|
|
555
|
+
super(`draft claim 거부 (${cardId}): ${reason}`);
|
|
556
|
+
this.name = 'TaskDraftClaimRejectedError';
|
|
557
|
+
this.cardId = cardId;
|
|
558
|
+
this.reason = reason;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손 수확(있으면) → claim 판정을 생산 진입점 안에서 닫는다.
|
|
564
|
+
*
|
|
565
|
+
* ⑴ 수확이 머리를 확정하지 못하면(`needs-human`·`failed`) claim 문면(`body`)을 만들지 않고 사유만 남긴다 —
|
|
566
|
+
* 다른 PR/낡은 머리 리뷰를 이 claim 에 붙이지 않는다. ⑵ 머리를 확정했으면 카드 원장(디스크)의 다른 카드와
|
|
567
|
+
* 견줘 중복·만료를 판정하고, 거부면 던진다(호출자가 카드를 쓰기 «전»에 멈춘다).
|
|
568
|
+
*/
|
|
569
|
+
async function resolveHandDraftClaim(input: {
|
|
570
|
+
claim: HandTaskDraftClaim;
|
|
571
|
+
cards: readonly TaskCard[];
|
|
572
|
+
cardId: string;
|
|
573
|
+
seat?: TaskSeat;
|
|
574
|
+
now: Date;
|
|
575
|
+
ask: string;
|
|
576
|
+
}): Promise<TaskCardDraftClaimRecord> {
|
|
577
|
+
const { claim } = input;
|
|
578
|
+
const harvest = claim.harvest ? await runHarvestUnit({
|
|
579
|
+
ask: input.ask,
|
|
580
|
+
context: {
|
|
581
|
+
pr: claim.pr,
|
|
582
|
+
...(claim.harvest.expectedHead !== undefined ? { expectedHead: claim.harvest.expectedHead } : {}),
|
|
583
|
+
reviewIntent: claim.harvest.reviewIntent ?? input.ask,
|
|
584
|
+
},
|
|
585
|
+
}, claim.harvest.invokeReview) : undefined;
|
|
586
|
+
const reason = harvest
|
|
587
|
+
? typeof harvest.result.reason === 'string' ? harvest.result.reason
|
|
588
|
+
: typeof harvest.result.error === 'string' ? harvest.result.error : undefined
|
|
589
|
+
: undefined;
|
|
590
|
+
const harvestRecord: TaskCardDraftClaimRecord['harvest'] | undefined = harvest ? {
|
|
591
|
+
outcome: harvest.outcome,
|
|
592
|
+
...(typeof harvest.result.headCommit === 'string' ? { headCommit: harvest.result.headCommit } : {}),
|
|
593
|
+
...(reason !== undefined ? { reason } : {}),
|
|
594
|
+
} : undefined;
|
|
595
|
+
const at = input.now.toISOString();
|
|
596
|
+
if (harvest && harvest.outcome !== 'done' && harvest.outcome !== 'rework') {
|
|
597
|
+
try { debug.log('task-agent.draft-claim', 'harvest-unconfirmed', { card: input.cardId, pr: claim.pr, outcome: harvest.outcome, reason: reason ?? null }); } catch { /* fail-soft */ }
|
|
598
|
+
return { pr: claim.pr, at, reclaim: false, ...(harvestRecord ? { harvest: harvestRecord } : {}) };
|
|
599
|
+
}
|
|
600
|
+
const judgement = judgeDraftClaim({
|
|
601
|
+
draft: { number: claim.pr, labels: claim.labels,
|
|
602
|
+
...(claim.updatedAt !== undefined ? { updatedAt: claim.updatedAt } : {}),
|
|
603
|
+
...(claim.runId !== undefined ? { runId: claim.runId } : {}) },
|
|
604
|
+
cards: input.cards,
|
|
605
|
+
cardId: input.cardId,
|
|
606
|
+
...(input.seat !== undefined ? { seat: input.seat } : {}),
|
|
607
|
+
now: input.now,
|
|
608
|
+
});
|
|
609
|
+
if (!judgement.ok) {
|
|
610
|
+
try { debug.log('task-agent.draft-claim', 'rejected', { card: input.cardId, pr: claim.pr, reason: judgement.reason }); } catch { /* fail-soft */ }
|
|
611
|
+
throw new TaskDraftClaimRejectedError(input.cardId, judgement.reason);
|
|
612
|
+
}
|
|
613
|
+
try { debug.log('task-agent.draft-claim', judgement.reclaim ? 'reclaimed' : 'claimed', { card: input.cardId, pr: claim.pr, ownerId: judgement.ownerId ?? null }); } catch { /* fail-soft */ }
|
|
614
|
+
return {
|
|
615
|
+
pr: claim.pr, at, reclaim: judgement.reclaim, body: judgement.body,
|
|
616
|
+
...(judgement.ownerId !== undefined ? { ownerId: judgement.ownerId } : {}),
|
|
617
|
+
...(harvestRecord ? { harvest: harvestRecord } : {}),
|
|
618
|
+
};
|
|
369
619
|
}
|
|
370
620
|
|
|
371
621
|
interface TaskAgentStateFile { tasks?: Record<string, TaskCard>; [key: string]: unknown }
|
|
372
622
|
|
|
623
|
+
/**
|
|
624
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손이 draft 를 잡을 때 필요한 관측·게시·수확 리뷰 포트(생산 기본값은 gh CLI ⊕ `elanous self
|
|
625
|
+
* review` 러너 · 시험은 가짜 포트로 몽크). `handDraftClaim` 이 이 포트들로 `draftClaim`(⊕ 손 수확)을 조립한다.
|
|
626
|
+
*/
|
|
627
|
+
export interface DraftClaimGhPorts {
|
|
628
|
+
/** PR 을 관측해 라벨·갱신 시각(·런 id)·머리(headRefOid · 손 수확 `expectedHead` 근거)을 읽는다. */
|
|
629
|
+
observePr: (pr: number) => Promise<{ labels: readonly string[]; updatedAt?: string; runId?: string | null; head?: string }>;
|
|
630
|
+
/** PR 댓글을 게시한다 — 게시 위치(댓글 url·id)를 돌려준다. */
|
|
631
|
+
postComment: (pr: number, body: string) => Promise<string | undefined>;
|
|
632
|
+
/**
|
|
633
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손 수확 리뷰 러너: `elanous self review <pr> --json` 관측 원문(stdout·stderr·exitCode)을
|
|
634
|
+
* 돌려준다(판정은 `runHarvestUnit` 몫). 주면 생산 배선이 관측한 PR 머리와 함께 손 수확을 조립한다 — 없으면 수확 없이 claim 한다.
|
|
635
|
+
*/
|
|
636
|
+
runReview?: (args: { pr: string; intent: string }) => Promise<ReviewInvocation>;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function ghExec(args: readonly string[]): Promise<string> {
|
|
640
|
+
return new Promise((done, fail) => {
|
|
641
|
+
execFile('gh', [...args], { encoding: 'utf8', maxBuffer: 32 * 1024 * 1024 }, (error, stdout) => {
|
|
642
|
+
if (error) fail(new Error(`gh ${args.join(' ')} 실패: ${error.message}`));
|
|
643
|
+
else done(String(stdout));
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손 수확 리뷰 러너(생산 기본값): 지금 도는 진입점으로 같은 우주의
|
|
650
|
+
* `elanous self review <pr> --json --intent <intent>` 를 «기다려» 관측 원문(stdout·stderr·exitCode)을 돌려준다
|
|
651
|
+
* (argv 는 `liveReviewArgs` 정본 — `defaultRequestReview` 가 떼어 띄우는 것과 같다). 판정·파싱은 `runHarvestUnit` 몫이다.
|
|
652
|
+
*/
|
|
653
|
+
export async function defaultDraftClaimReviewRunner(args: { pr: string; intent: string }): Promise<ReviewInvocation> {
|
|
654
|
+
const { ELANOUS_CLI_ENTRY } = await import('../cli/tasks-cli.js');
|
|
655
|
+
const { getElanousConfigDirOverride } = await import('../elanous-config-dir.js');
|
|
656
|
+
const { liveReviewArgs } = await import('./live-moves.js');
|
|
657
|
+
const configDir = getElanousConfigDirOverride() ?? effectiveInstanceRoot();
|
|
658
|
+
const argv = liveReviewArgs(ELANOUS_CLI_ENTRY, configDir, Number(args.pr), args.intent);
|
|
659
|
+
return await new Promise<ReviewInvocation>((done) => {
|
|
660
|
+
execFile(process.execPath, argv, { encoding: 'utf8', maxBuffer: 32 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
661
|
+
const exitCode = error ? (typeof (error as { code?: unknown }).code === 'number' ? (error as { code: number }).code : 1) : 0;
|
|
662
|
+
done({ stdout: String(stdout), stderr: String(stderr), exitCode });
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/** 생산 기본 포트 — gh CLI 로 PR 을 관측(라벨·갱신 시각·머리)하고 댓글을 게시하며, 손 수확 리뷰는 같은 우주의 `elanous self review` 러너로 돌린다(자격·원격 저장소는 각 설정을 따른다). */
|
|
668
|
+
export function defaultDraftClaimGhPorts(): DraftClaimGhPorts {
|
|
669
|
+
return {
|
|
670
|
+
async observePr(pr: number) {
|
|
671
|
+
let parsed: Record<string, unknown>;
|
|
672
|
+
try {
|
|
673
|
+
parsed = JSON.parse(await ghExec(['pr', 'view', String(pr), '--json', 'labels,updatedAt,headRefOid'])) as Record<string, unknown>;
|
|
674
|
+
} catch (error) {
|
|
675
|
+
throw new Error(`PR #${pr} 관측 실패(gh pr view): ${error instanceof Error ? error.message : String(error)}`);
|
|
676
|
+
}
|
|
677
|
+
const labels = Array.isArray(parsed.labels) ? parsed.labels
|
|
678
|
+
.map((label) => typeof label === 'string' ? label : (label as { name?: unknown } | null)?.name)
|
|
679
|
+
.filter((name): name is string => typeof name === 'string') : [];
|
|
680
|
+
const updatedAt = typeof parsed.updatedAt === 'string' ? parsed.updatedAt : undefined;
|
|
681
|
+
const head = typeof parsed.headRefOid === 'string' && /^[0-9a-f]{40}$/i.test(parsed.headRefOid) ? parsed.headRefOid : undefined;
|
|
682
|
+
return { labels, ...(updatedAt !== undefined ? { updatedAt } : {}), ...(head !== undefined ? { head } : {}) };
|
|
683
|
+
},
|
|
684
|
+
async postComment(pr: number, body: string) {
|
|
685
|
+
await ghExec(['pr', 'comment', String(pr), '--body', body]);
|
|
686
|
+
return `PR #${pr} 댓글`;
|
|
687
|
+
},
|
|
688
|
+
// DRAFT-CLAIM-AUTO-2-FU — 손 수확 리뷰 러너(생산): handDraftClaim 이 관측한 머리와 함께 조립한다.
|
|
689
|
+
runReview: defaultDraftClaimReviewRunner,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* DRAFT-CLAIM-AUTO-2-FU — 생산 진입점 배선: 관측 포트로 PR 을 읽어 `draftClaim` 을 «조립해» `handTask` 에 넘긴다
|
|
695
|
+
* (`tasks hand --draft-claim <pr>` 가 부른다). 손 수확도 여기서 조립한다 — 관측한 PR 머리(`expectedHead`) ⊕ 포트의
|
|
696
|
+
* 리뷰 러너(`invokeReview` · 생산 기본값 `elanous self review <pr> --json`)로 `runHarvestUnit` 을 거치게 한다.
|
|
697
|
+
* 시험도 이 경로로 돌며 gh·리뷰 포트만 몽크한다 — `draftClaim` 을 직접 주입하지 않는다. 호출자가 직접 준 `harvest`
|
|
698
|
+
* 가 우선(시험 주입)이고 리뷰 러너가 없는 포트는 종전대로 수확 없이 claim 한다(기본 동작 보존).
|
|
699
|
+
*/
|
|
700
|
+
export async function handDraftClaim(input: {
|
|
701
|
+
pr: number;
|
|
702
|
+
gh: DraftClaimGhPorts;
|
|
703
|
+
/** DRAFT-CLAIM-AUTO-2-FU — 직접 주는 수확(시험 주입). 안 주면 배선이 관측한 머리 ⊕ 포트의 리뷰 러너로 조립한다. */
|
|
704
|
+
harvest?: HandTaskDraftHarvest;
|
|
705
|
+
} & Omit<Parameters<typeof handTask>[0], 'draftClaim'>): Promise<Awaited<ReturnType<typeof handTask>>> {
|
|
706
|
+
const { pr, gh, harvest, ...handOpts } = input;
|
|
707
|
+
const observed = await gh.observePr(pr);
|
|
708
|
+
// DRAFT-CLAIM-AUTO-2-FU — 손 수확 조립(생산): 관측한 PR 머리(expectedHead) + 포트의 리뷰 러너(invokeReview).
|
|
709
|
+
const handHarvest: HandTaskDraftHarvest | undefined = harvest ?? (gh.runReview === undefined ? undefined : {
|
|
710
|
+
...(observed.head !== undefined ? { expectedHead: observed.head } : {}),
|
|
711
|
+
invokeReview: gh.runReview,
|
|
712
|
+
});
|
|
713
|
+
return handTask({
|
|
714
|
+
...handOpts,
|
|
715
|
+
draftClaim: {
|
|
716
|
+
pr,
|
|
717
|
+
labels: observed.labels,
|
|
718
|
+
...(observed.updatedAt !== undefined ? { updatedAt: observed.updatedAt } : {}),
|
|
719
|
+
...(observed.runId !== undefined ? { runId: observed.runId } : {}),
|
|
720
|
+
...(handHarvest !== undefined ? { harvest: handHarvest } : {}),
|
|
721
|
+
postComment: gh.postComment,
|
|
722
|
+
},
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
373
726
|
function isGitWorkTree(path: string): boolean {
|
|
374
727
|
try {
|
|
375
728
|
return execFileSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd: path, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() === 'true';
|
|
@@ -427,22 +780,81 @@ export function writeTaskCards(path: string, cards: readonly TaskCard[]): void {
|
|
|
427
780
|
}
|
|
428
781
|
|
|
429
782
|
/** 카드 하나를 잠금 안에서 읽고 고쳐 쓴다 — `update` 가 undefined 를 돌려주면 쓰지 않는다. 쓴(또는 그대로인) 카드를 돌려준다. */
|
|
430
|
-
export function updateTaskCard(path: string, id: string, update: (card: TaskCard | undefined, tasks: Readonly<Record<string, TaskCard>>) => TaskCard | undefined
|
|
431
|
-
|
|
783
|
+
export function updateTaskCard(path: string, id: string, update: (card: TaskCard | undefined, tasks: Readonly<Record<string, TaskCard>>) => TaskCard | undefined,
|
|
784
|
+
options: { doctorLedgerDir?: string } = {}): TaskCard | undefined {
|
|
785
|
+
let needsOwner: { runId: string; at: string; reason: string; transitionIndex: number } | undefined;
|
|
786
|
+
const result = withFileLockSync(`${path}.lock`, () => {
|
|
432
787
|
const disk = readState(path);
|
|
433
788
|
const current = disk.tasks?.[id];
|
|
434
789
|
const next = update(current, disk.tasks ?? {});
|
|
435
790
|
if (!next) return current;
|
|
791
|
+
const transitionIndex = next.history.length - 1;
|
|
792
|
+
const last = next.history[transitionIndex];
|
|
793
|
+
if (current?.status === 'launched' && next.status === 'failed' && next.runId
|
|
794
|
+
&& next.history.length > (current?.history.length ?? 0) && last?.event === 'failed'
|
|
795
|
+
&& last.detail?.startsWith('failed/needs-owner')) {
|
|
796
|
+
needsOwner = { runId: next.runId, at: last.at, reason: last.detail, transitionIndex };
|
|
797
|
+
}
|
|
436
798
|
mkdirSync(dirname(path), { recursive: true });
|
|
437
799
|
writeFileSync(path, JSON.stringify({ ...disk, tasks: { ...(disk.tasks ?? {}), [id]: next } }));
|
|
438
800
|
return next;
|
|
439
801
|
});
|
|
802
|
+
if (needsOwner) {
|
|
803
|
+
try {
|
|
804
|
+
const visit = recordTaskAgentNeedsOwnerVisit({ ...needsOwner, cardId: id, dir: options.doctorLedgerDir });
|
|
805
|
+
debug.log('task-agent', 'doctor-visit', { card: id, runId: needsOwner.runId, status: visit.status });
|
|
806
|
+
} catch (error) {
|
|
807
|
+
debug.log('task-agent', 'doctor-visit-failed', { card: id, runId: needsOwner.runId,
|
|
808
|
+
reason: error instanceof Error ? error.message : String(error) });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return result;
|
|
440
812
|
}
|
|
441
813
|
|
|
442
814
|
export function readTaskCard(id: string, path = taskAgentStatePath()): TaskCard | undefined {
|
|
443
815
|
return readState(path).tasks?.[id];
|
|
444
816
|
}
|
|
445
817
|
|
|
818
|
+
/** TA-REVIEW-PASS — runId 기준 단일 카드 멱등 생성 결과. `ok: false` 는 임의 생성 없이 사유만 남긴 보류(fail-closed)다. */
|
|
819
|
+
export type IdempotentRunCardCreate =
|
|
820
|
+
| { ok: true; card: TaskCard; created: boolean }
|
|
821
|
+
| { ok: false; reason: string };
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* TA-REVIEW-PASS — runId 기준 단일 카드 결속(멱등 생성). 단일 파일 잠금 안에서 원장을 읽어
|
|
825
|
+
* (a) 같은 runId 카드가 정확히 1건이면 그대로 재사용, (b) 0건이면 runId 해시로 재진입에 안정적인 id 를 만들어
|
|
826
|
+
* `card.runId` 를 검증된 부모 런 ID 와 정확히 일치시켜 원장에 추가한다(종전 칸·다른 카드·원장 기타 필드 보존),
|
|
827
|
+
* (c) 복수 카드·원격 Pod 자식 런·불명 runId·읽기 실패는 임의 생성하지 않고 사유를 남겨 보류한다.
|
|
828
|
+
*/
|
|
829
|
+
export function idempotentCreateCardForRun(path: string, input: { runId: string; text: string; now?: () => Date; env?: NodeJS.ProcessEnv }): IdempotentRunCardCreate {
|
|
830
|
+
const runId = input.runId.trim();
|
|
831
|
+
if (!runId) return { ok: false, reason: 'runId 불명 — 고유한 런 소유를 검증할 수 없어 카드를 만들지 않는다' };
|
|
832
|
+
const env = input.env ?? process.env;
|
|
833
|
+
if (env.ELANOUS_POD_NAME) return { ok: false, reason: `원격 Pod 자식 런(${env.ELANOUS_POD_NAME}) — HQ 결속만 허용한다` };
|
|
834
|
+
const at = (input.now ?? (() => new Date()))().toISOString();
|
|
835
|
+
return withFileLockSync(`${path}.lock`, (): IdempotentRunCardCreate => {
|
|
836
|
+
let disk: TaskAgentStateFile;
|
|
837
|
+
try {
|
|
838
|
+
disk = readState(path);
|
|
839
|
+
} catch (error) {
|
|
840
|
+
return { ok: false, reason: `원장 읽기 실패 — 임의 생성하지 않는다: ${error instanceof Error ? error.message : String(error)}` };
|
|
841
|
+
}
|
|
842
|
+
const tasks = { ...(disk.tasks ?? {}) };
|
|
843
|
+
const bound = Object.values(tasks).filter((candidate) => candidate.runId === runId);
|
|
844
|
+
if (bound.length === 1) return { ok: true, card: bound[0]!, created: false };
|
|
845
|
+
if (bound.length > 1) return { ok: false, reason: `runId ${runId} 카드 ${bound.length}건(모호) — 고유한 런 소유가 아니므로 결속하지 않는다` };
|
|
846
|
+
const id = `${TASK_CARD_PREFIX}run-${createHash('sha256').update(runId).digest('hex').slice(0, 12)}`;
|
|
847
|
+
if (tasks[id]) return { ok: false, reason: `카드 id ${id} 충돌 — 종전 카드를 덮어쓰지 않는다` };
|
|
848
|
+
const card: TaskCard = {
|
|
849
|
+
id, text: input.text, createdAt: at, status: 'launched', runId,
|
|
850
|
+
history: [{ at, event: 'card-created-for-run', detail: `카드 없는 runId(${runId})의 리뷰 필요 판정 — 단일 카드 멱등 결속`, runId }],
|
|
851
|
+
};
|
|
852
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
853
|
+
writeFileSync(path, JSON.stringify({ ...disk, tasks: { ...tasks, [id]: card } }));
|
|
854
|
+
return { ok: true, card, created: true };
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
|
|
446
858
|
function canonicalTargetPaths(paths: readonly string[]): string[] {
|
|
447
859
|
return [...new Set(paths.filter((path): path is string => typeof path === 'string').map((path) => posix.normalize(path))
|
|
448
860
|
.filter((path) => path !== '.' && path !== '..' && !posix.isAbsolute(path)
|
|
@@ -544,6 +956,7 @@ export function launchArgs(card: Pick<TaskCard, 'text' | 'seat' | 'childLlm' | '
|
|
|
544
956
|
? ['--child-llm-provider', card.childLlm.provider, '--child-llm-model', card.childLlm.model, ...(card.childLlm.effort ? ['--child-llm-effort', card.childLlm.effort] : [])]
|
|
545
957
|
: [];
|
|
546
958
|
const runPriority = runIdentityQueuePriority(card.identity);
|
|
959
|
+
// Exact role model pins travel in ELANOUS_ROLE_LLM_*: harness say's argv parser only accepts provider[/tier].
|
|
547
960
|
return ['harness', 'say', ...(card.seat ? ['--seat', card.seat] : []), '--substrate', 'pod', '--merge-by-host', ...(runPriority !== undefined ? ['--run-priority', String(runPriority)] : []), ...child, card.text];
|
|
548
961
|
}
|
|
549
962
|
|
|
@@ -607,6 +1020,7 @@ export interface HandTaskOptions {
|
|
|
607
1020
|
/** TASKS-HAND-CHILD-LLM — `<provider>/<model>`(`parseChildLlm`) ⊕ 선택 추론 노력. effort 만 주면 거부. */
|
|
608
1021
|
childLlm?: string;
|
|
609
1022
|
childLlmEffort?: string;
|
|
1023
|
+
parentRoleLlm?: string[];
|
|
610
1024
|
tier?: TaskCard['tier'];
|
|
611
1025
|
/** TIER-SPLIT-BEFORE-LAUNCH — 조각 카드에 싣는 분해 연결(`tier-split.ts` 만 준다). */
|
|
612
1026
|
tierSplit?: TaskCard['tierSplit'];
|
|
@@ -627,6 +1041,11 @@ export interface HandTaskOptions {
|
|
|
627
1041
|
compositionRoot?: string;
|
|
628
1042
|
/** `--live` 일 때만 불린다. */
|
|
629
1043
|
launcher?: TaskLauncher;
|
|
1044
|
+
/**
|
|
1045
|
+
* 2판 — launcher 'graph-run' 조합을 실제 graph run 으로 발사한다(기본 = src/graph-runner/runner.ts runGraph).
|
|
1046
|
+
* 시험은 이 seam 을 주입해 발사 인자(선택된 조합 경로 ⊕ GraphRunOptions)를 'calls' capture 로 검증한다.
|
|
1047
|
+
*/
|
|
1048
|
+
graphRunner?: (path: string, options: GraphRunOptions) => Promise<GraphRunState>;
|
|
630
1049
|
/** Deterministic contract seam; production uses the pinned-main verifier. */
|
|
631
1050
|
prelaunchInspector?: (text: string, projectTarget?: string) => AlreadyDoneDecision;
|
|
632
1051
|
/** Test-only: inject Git calls into the production verifier; no CLI/config surface. */
|
|
@@ -640,6 +1059,12 @@ export interface HandTaskOptions {
|
|
|
640
1059
|
landed?: ReadonlySet<string>;
|
|
641
1060
|
/** 카드에 그대로 싣는 칸(② 의 넘김 표지·착지 근거) — handTask 가 카드를 새로 적을 때 지워지지 않게. */
|
|
642
1061
|
cardFields?: Pick<TaskCard, 'pr' | 'goalId' | 'handed'>;
|
|
1062
|
+
/**
|
|
1063
|
+
* DRAFT-CLAIM-AUTO-2-FU — 손이 잡으려는 draft(PR)의 «지금» 관측값(라벨·갱신 시각·리뷰 러너).
|
|
1064
|
+
* 주면 `handTask` 가 손 수확(있으면) → `judgeDraftClaim` 을 거쳐 카드 `draftClaim` 에 기록한다. 거부면
|
|
1065
|
+
* 카드를 쓰기 전에 `TaskDraftClaimRejectedError`. 안 주면 종전과 똑같이 claim 을 하지 않는다(기본 동작 보존).
|
|
1066
|
+
*/
|
|
1067
|
+
draftClaim?: HandTaskDraftClaim;
|
|
643
1068
|
/**
|
|
644
1069
|
* 있으면 카드 쓰기마다 잠금 안에서 디스크 카드를 보고 참일 때만 쓴다(② 의 claim 소유 확인).
|
|
645
1070
|
* 거짓이면 쓰지 않고 `TaskCardSupersededError` — 다른 넘김이 그 카드를 가져갔다(발사 전이면 발사하지 않는다).
|
|
@@ -688,6 +1113,57 @@ export function dispatchDeliverableCompletion(id: string, input: { ref: string;
|
|
|
688
1113
|
return closed;
|
|
689
1114
|
}
|
|
690
1115
|
|
|
1116
|
+
/**
|
|
1117
|
+
* ENTRANCE-EVIDENCE-COMMAND-ONLY — 증거 명령 줄의 «형태» 판정. 기존 TA-HAND-PREFLIGHT 의 계약 줄 «존재» 검사
|
|
1118
|
+
* (`inspectGoalDoneBoundary`)와 구분된다: 세 경계 줄이 이미 갖춰진 골에서 증거 명령 줄의 값이 명령 원문인지만 본다.
|
|
1119
|
+
* 설명 접미(예: `→ 0 fail`)와 백틱 장식은 줄마다 이유를 붙여 거부한다. 빈 값·누락은 존재 검사 몫이다.
|
|
1120
|
+
*/
|
|
1121
|
+
const GOAL_EVIDENCE_COMMAND_LINE = /^\s*(?:[-*]\s*)?완료 경계 증거 명령\s*:\s*(.*?)\s*$/;
|
|
1122
|
+
const GOAL_EVIDENCE_COMMAND_DESCRIPTION_SUFFIX = /->|→/;
|
|
1123
|
+
const GOAL_EVIDENCE_COMMAND_BACKTICK_DECORATION = /`/;
|
|
1124
|
+
|
|
1125
|
+
function goalEvidenceCommandFormViolations(document: string): string[] {
|
|
1126
|
+
const violations: string[] = [];
|
|
1127
|
+
for (const line of linesOutsideFencedCode(document)) {
|
|
1128
|
+
const value = GOAL_EVIDENCE_COMMAND_LINE.exec(line.text)?.[1];
|
|
1129
|
+
if (value === undefined || !value.trim()) continue;
|
|
1130
|
+
if (GOAL_EVIDENCE_COMMAND_BACKTICK_DECORATION.test(value)) violations.push(`백틱 장식: ${value}`);
|
|
1131
|
+
else if (GOAL_EVIDENCE_COMMAND_DESCRIPTION_SUFFIX.test(value)) violations.push(`설명 접미: ${value}`);
|
|
1132
|
+
}
|
|
1133
|
+
return violations;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* FIRST-LINE-PATH-LIST-ONLY — 골 «첫 줄»의 형태 판정: `대상 경로:` 뒤의 «경로 조각» 에는 괄호·줄번호·덧말이 붙지 않는다.
|
|
1138
|
+
* 첫 줄만 보는 판정은 `parseAskTargetPathHintsResult` 가 이미 하므로 새 파서를 만들지 않고 그 결과에 얹는다:
|
|
1139
|
+
* 파서가 통과시킨 경로(`paths`)와 버린 조각(`rejected`)을 한 줄씩 보고, «경로 조각»(디렉터리 구분자·확장자가 있는 것)에
|
|
1140
|
+
* 장식이 붙었을 때만 이유를 붙여 거부한다. `· 동작: a 고침` 같은 «산문 조각» 은 경로 조각이 아니다 —
|
|
1141
|
+
* 조각 분해가 합성하는 손 문면(`handTaskWithTierSplit` 경로)이 그 모양으로 첫 줄을 만든다.
|
|
1142
|
+
* 라벨이 없는 문면(첫 줄이 대상 경로 목록이 아닌 손)은 이 축의 몫이 아니다 — 그 모양은 지금과 같다.
|
|
1143
|
+
*/
|
|
1144
|
+
const FIRST_LINE_PATH_DECORATIONS: readonly { readonly label: string; readonly pattern: RegExp }[] = [
|
|
1145
|
+
{ label: '괄호 장식', pattern: /[()[\]{}()【】]/ },
|
|
1146
|
+
{ label: '줄번호', pattern: /:\d/ },
|
|
1147
|
+
{ label: '덧말', pattern: /->|→|—|–/ },
|
|
1148
|
+
];
|
|
1149
|
+
|
|
1150
|
+
function firstLinePathListViolations(hints: AskTargetPathHintsParseResult): string[] {
|
|
1151
|
+
if (hints.labelMissing) return [];
|
|
1152
|
+
const violations: string[] = [];
|
|
1153
|
+
for (const piece of [...hints.paths, ...hints.rejected.map((rejection) => rejection.fragment.trim())]) {
|
|
1154
|
+
if (!/[/.]/.test(piece)) continue;
|
|
1155
|
+
const decoration = FIRST_LINE_PATH_DECORATIONS.find((entry) => entry.pattern.test(piece));
|
|
1156
|
+
if (decoration) violations.push(`${decoration.label}: ${piece}`);
|
|
1157
|
+
// 공백만으로 거부하지 않는다 — «경로 자체에 공백»(`docs/foo bar.md`)은 지금처럼 통과한다.
|
|
1158
|
+
// 덧말은 공백 뒤에 «경로가 아닌 말»이 붙은 경우만이다(마지막 조각에 구분자·확장자가 없다).
|
|
1159
|
+
else {
|
|
1160
|
+
const trailing = piece.split(/\s+/).slice(1).join(' ').trim();
|
|
1161
|
+
if (trailing !== '' && !/[/.]/.test(trailing)) violations.push(`덧말(공백 섞임): ${piece}`);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
return violations;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
691
1167
|
export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
692
1168
|
const text = opts.text.trim();
|
|
693
1169
|
if (!text) throw new Error('과제 한 줄이 비어 있다');
|
|
@@ -720,11 +1196,23 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
720
1196
|
launcher: 'hand',
|
|
721
1197
|
}, birthTags);
|
|
722
1198
|
const childLlm = opts.childLlm !== undefined ? parseChildLlm(opts.childLlm, opts.childLlmEffort) : undefined;
|
|
1199
|
+
const parentRolePins = taskParentRolePinsForChild(opts.parentRoleLlm ?? [], childLlm);
|
|
1200
|
+
const parentRoleEnv = taskParentRoleEnv(parentRolePins); // validate before writing the card
|
|
723
1201
|
const completion = opts.completion ?? 'code-pr';
|
|
724
1202
|
const selected = selectTaskComposition(completion, opts.compositionRoot);
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1203
|
+
// 2판 — launcher 'graph-run' 조합(단위 해석까지 완료)은 실제 graph run 으로 발사한다. 더 이상 거부하지 않는다.
|
|
1204
|
+
const graphRun = selected.composition && selected.launcher === 'graph-run' && !selected.error && selected.unitsResolved
|
|
1205
|
+
? selected.composition : undefined;
|
|
1206
|
+
const graphRunPath = graphRun ? join(opts.compositionRoot ?? COMPOSITION_ROOT, graphRun.file) : undefined;
|
|
1207
|
+
const selectionFailure = graphRun ? undefined
|
|
1208
|
+
: !selected.composition ? `조합 없음: graphs/work/${completion}.yaml`
|
|
1209
|
+
: selected.error ?? (selected.launcher === 'graph-run' && !selected.unitsResolved
|
|
1210
|
+
? `조합 단위 미해석: ${selected.composition.file} — 대상 unit: ${selected.missingUnits.length ? selected.missingUnits.join(', ') : '해석 실패'} (graph-run 발사는 단위 해석이 필요하다)`
|
|
1211
|
+
// DEFAULT-HANDS — 코드 하니스(harness-say 자식 구현 런)는 개발자 팩(code-pr)만 쓴다.
|
|
1212
|
+
: !DEFAULT_HANDS[completion].codeHarness && selected.launcher === 'harness-say'
|
|
1213
|
+
? `조합 실행기 없음: ${selected.composition.file} — ${completion} 은 «실행·조사» 손이라 코드 하니스(harness-say)를 쓰지 않는다(개발자 팩 전용)`
|
|
1214
|
+
: selected.launcher === undefined
|
|
1215
|
+
? `조합 실행기 없음: ${selected.composition.file} (발사 가능한 launcher: harness-say · graph-run)` : undefined);
|
|
728
1216
|
let project: TaskCard['project'];
|
|
729
1217
|
let targetIsGit: boolean | null = null;
|
|
730
1218
|
if (opts.project) {
|
|
@@ -743,7 +1231,15 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
743
1231
|
const now = (opts.now ?? (() => new Date()))();
|
|
744
1232
|
const id = opts.id ?? `${TASK_CARD_PREFIX}${now.toISOString().slice(0, 10).replaceAll('-', '')}-${randomBytes(3).toString('hex')}`;
|
|
745
1233
|
const mode = opts.live ? 'live' : 'shadow';
|
|
746
|
-
|
|
1234
|
+
// DRAFT-CLAIM-AUTO-2-FU — claim 은 카드를 쓰기 «전»에 판정한다(거부면 원장에 아무것도 남기지 않는다).
|
|
1235
|
+
// 견줄 상대는 카드 원장(디스크)의 다른 카드다 — 손이 들고 있는 사본이 아니라 정본을 본다.
|
|
1236
|
+
const draftClaim = opts.draftClaim
|
|
1237
|
+
? await resolveHandDraftClaim({
|
|
1238
|
+
claim: opts.draftClaim, cards: Object.values(readState(path).tasks ?? {}), cardId: id,
|
|
1239
|
+
...(opts.seat !== undefined ? { seat: opts.seat } : {}), now, ask: text,
|
|
1240
|
+
})
|
|
1241
|
+
: undefined;
|
|
1242
|
+
let card: TaskCard = {
|
|
747
1243
|
id, text,
|
|
748
1244
|
...(!targetPathHints.labelMissing ? { targetPaths } : {}),
|
|
749
1245
|
...(opts.seat ? { seat: opts.seat } : {}),
|
|
@@ -758,24 +1254,57 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
758
1254
|
...(opts.milestone ? { milestone: opts.milestone } : {}),
|
|
759
1255
|
...(opts.taLand === true ? { taLand: true as const } : {}),
|
|
760
1256
|
...(childLlm ? { childLlm } : {}),
|
|
1257
|
+
...(parentRolePins.length ? { parentRoleLlm: parentRolePins } : {}),
|
|
761
1258
|
...(opts.tier ? { tier: opts.tier } : {}),
|
|
762
1259
|
...(opts.tierSplit ? { tierSplit: opts.tierSplit } : {}),
|
|
763
1260
|
...(identity ? { identity } : {}),
|
|
764
1261
|
createdAt: now.toISOString(),
|
|
765
1262
|
status: selectionFailure || tierSplitBlocked !== undefined ? 'failed' : 'handed',
|
|
766
|
-
history:
|
|
767
|
-
:
|
|
768
|
-
|
|
1263
|
+
history: [
|
|
1264
|
+
...(selectionFailure ? [{ at: now.toISOString(), event: !selected.composition ? 'composition-missing'
|
|
1265
|
+
: selected.error ? 'composition-invalid' : 'composition-launcher-unavailable', detail: selectionFailure }] : []),
|
|
1266
|
+
...(tierSplitBlocked !== undefined ? [{ at: now.toISOString(), event: 'tier-split-failed', detail: `tier-split-failed: ${tierSplitBlocked}` }] : []),
|
|
1267
|
+
],
|
|
769
1268
|
...(opts.mission ? { mission: opts.mission, after: [...(opts.after ?? [])] } : {}),
|
|
770
1269
|
...(opts.cardFields?.pr !== undefined ? { pr: opts.cardFields.pr } : {}),
|
|
771
1270
|
...(opts.cardFields?.goalId !== undefined ? { goalId: opts.cardFields.goalId } : {}),
|
|
772
1271
|
...(opts.cardFields?.handed !== undefined ? { handed: opts.cardFields.handed } : {}),
|
|
1272
|
+
...(draftClaim ? { draftClaim } : {}),
|
|
773
1273
|
};
|
|
774
|
-
|
|
1274
|
+
// 2판 graph-run 조합의 다음 수는 실제 graph run — harness say 인자를 조립하지 않는다.
|
|
1275
|
+
const move = graphRun && graphRunPath ? { kind: 'launch' as const, command: ['graph', 'run', graphRunPath], reason: `조합 launcher graph-run — ${graphRun.file}` } satisfies TaskCardMove
|
|
1276
|
+
: selectionFailure ? undefined : nextMoveFor(card, opts.landed);
|
|
775
1277
|
// 분해 실패로 막은 카드는 wait(failed 사유)가 정답이다 — 던지지 않고 카드를 적은 뒤 발사 0 으로 돌아간다.
|
|
776
1278
|
if (move && move.kind !== 'launch' && tierSplitBlocked === undefined) throw new Error(`발사할 수 없는 과제다 — ${move.reason}`);
|
|
777
1279
|
const guard = opts.writeGuard;
|
|
778
1280
|
const writeCard = (target: string, next: TaskCard): void => {
|
|
1281
|
+
if (next.draftClaim?.body !== undefined && opts.draftClaim) {
|
|
1282
|
+
let written = false;
|
|
1283
|
+
const saved = updateTaskCard(target, next.id, (current, tasks) => {
|
|
1284
|
+
if (guard && !guard(current)) return undefined;
|
|
1285
|
+
// 같은 파일 잠금 안에서 판정과 기록을 마친다. 댓글은 잠금 밖에서 기록 성공 후 게시한다.
|
|
1286
|
+
const judgement = judgeDraftClaim({
|
|
1287
|
+
draft: { number: opts.draftClaim!.pr, labels: opts.draftClaim!.labels,
|
|
1288
|
+
...(opts.draftClaim!.updatedAt !== undefined ? { updatedAt: opts.draftClaim!.updatedAt } : {}),
|
|
1289
|
+
...(opts.draftClaim!.runId !== undefined ? { runId: opts.draftClaim!.runId } : {}) },
|
|
1290
|
+
cards: Object.values(tasks), cardId: next.id,
|
|
1291
|
+
...(opts.seat !== undefined ? { seat: opts.seat } : {}), now,
|
|
1292
|
+
});
|
|
1293
|
+
if (!judgement.ok) throw new TaskDraftClaimRejectedError(next.id, judgement.reason);
|
|
1294
|
+
written = true;
|
|
1295
|
+
const claim: TaskCardDraftClaimRecord = { ...next.draftClaim!, body: judgement.body, reclaim: judgement.reclaim, mode,
|
|
1296
|
+
...(judgement.ownerId !== undefined ? { ownerId: judgement.ownerId } : {}) };
|
|
1297
|
+
const { pr: _stalePr, goalId: _staleGoal, refSource: _staleSource, ...base } = next;
|
|
1298
|
+
const evidence = current ?? next;
|
|
1299
|
+
return { ...base, draftClaim: claim,
|
|
1300
|
+
...(evidence.pr !== undefined ? { pr: evidence.pr } : {}),
|
|
1301
|
+
...(evidence.goalId !== undefined ? { goalId: evidence.goalId } : {}),
|
|
1302
|
+
...(evidence.refSource ? { refSource: evidence.refSource } : {}) };
|
|
1303
|
+
});
|
|
1304
|
+
if (!written) throw new TaskCardSupersededError(next.id);
|
|
1305
|
+
if (saved) card = saved;
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
779
1308
|
if (!guard) { writeTaskCards(target, [next]); return; }
|
|
780
1309
|
const owned = { ok: false };
|
|
781
1310
|
// 착지 근거(pr·goalId)는 `recordPieceRef` 소유 — claim 뒤에 적힌 최신 근거를 디스크에서 이어 받는다.
|
|
@@ -790,28 +1319,90 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
790
1319
|
};
|
|
791
1320
|
// Production Pod launches use the remote-parent lint's shared boundary judge.
|
|
792
1321
|
// Injected launchers are test seams and opt in explicitly at the contract test.
|
|
793
|
-
if (opts.live && opts.preflightGoalDoneBoundary && !selectionFailure && move?.kind === 'launch') {
|
|
1322
|
+
if (opts.live && opts.preflightGoalDoneBoundary && !selectionFailure && tierSplitBlocked === undefined && move?.kind === 'launch') {
|
|
794
1323
|
readTaskAgentState(path);
|
|
795
1324
|
const { missing } = inspectGoalDoneBoundary(text);
|
|
796
1325
|
if (missing.length > 0) {
|
|
797
1326
|
throw new Error(`goal-revision-required: 완료 경계 누락 ${missing.join(' · ')} — 골 문면에 완료 경계 코드·완료 경계 실물·완료 경계 증거 명령을 적은 뒤 다시 넘기세요`);
|
|
798
1327
|
}
|
|
1328
|
+
// ENTRANCE-EVIDENCE-COMMAND-ONLY — 존재 검사와 구분된 형태 판정: 증거 명령 줄은 명령 원문만 받는다.
|
|
1329
|
+
const formViolations = goalEvidenceCommandFormViolations(text);
|
|
1330
|
+
if (formViolations.length > 0) {
|
|
1331
|
+
throw new Error(`goal-revision-required: 완료 경계 증거 명령은 명령 원문이어야 한다 ${formViolations.join(' · ')} — 증거 명령 줄에 설명 접미(예: → 0 fail)나 백틱 장식을 붙이지 말고 명령만 적은 뒤 다시 넘기세요`);
|
|
1332
|
+
}
|
|
1333
|
+
// FIRST-LINE-PATH-LIST-ONLY — 첫 줄 형태 판정(발사 전 거부): 괄호·줄번호·덧말이 붙은 골은 자식을 띄우지 않는다.
|
|
1334
|
+
// 카드 기록(writeCard)과 launcher 호출 뒤로 밀리면 «발사 전 거부·카드 0» 이 깨지므로 이 자리에서 던진다.
|
|
1335
|
+
const firstLineViolations = firstLinePathListViolations(targetPathHints);
|
|
1336
|
+
if (firstLineViolations.length > 0) {
|
|
1337
|
+
try { debug.log('task-agent.hand', 'first-line-path-list-rejected', { card: id, violations: firstLineViolations }); } catch { /* fail-soft */ }
|
|
1338
|
+
throw new Error(`goal-revision-required: 골 첫 줄은 «대상 경로:» 뒤에 경로 목록만 적어야 한다 ${firstLineViolations.join(' · ')} — 괄호·줄번호·덧말을 떼고 경로만 적은 뒤 다시 넘기세요`);
|
|
1339
|
+
}
|
|
799
1340
|
}
|
|
800
1341
|
writeCard(path, card);
|
|
801
1342
|
try { debug.log('task-agent.hand', 'target-paths', { card: id, count: targetPaths.length, labelMissing: targetPathHints.labelMissing }); } catch { /* fail-soft */ }
|
|
802
1343
|
try { debug.log('task-agent.graph-select', !selected.composition ? 'composition-missing' : selected.error ? 'composition-invalid' : 'composition-selected', {
|
|
803
1344
|
completion, file: selected.composition?.file ?? `graphs/work/${completion}.yaml`,
|
|
1345
|
+
// DEFAULT-HANDS — 어느 손으로 나가는지(«개발»/«실행·조사»)와 코드 하니스 여부를 선택 관측에 싣는다.
|
|
1346
|
+
hand: DEFAULT_HANDS[completion].hand, codeHarness: DEFAULT_HANDS[completion].codeHarness,
|
|
804
1347
|
unitsResolved: selected.unitsResolved, missingUnits: selected.missingUnits,
|
|
805
1348
|
...(selected.error ? { error: selected.error } : {}),
|
|
806
1349
|
}); } catch { /* fail-soft */ }
|
|
1350
|
+
if (tierSplitBlocked !== undefined) return { card, move: move ?? nextMoveFor(card), mode, launched: false, ...(project ? { cwd: project.target } : {}) };
|
|
807
1351
|
if (selectionFailure) throw new Error(`${selectionFailure} (카드 ${id})`);
|
|
808
|
-
if (tierSplitBlocked !== undefined && move) return { card, move, mode, launched: false, ...(project ? { cwd: project.target } : {}) };
|
|
809
1352
|
if (!move || move.kind !== 'launch') throw new Error('조합 선택 뒤 발사 수가 없다');
|
|
1353
|
+
if (opts.live && opts.draftClaim?.postComment && card.draftClaim?.body !== undefined) {
|
|
1354
|
+
let postedTo: string | undefined;
|
|
1355
|
+
try {
|
|
1356
|
+
postedTo = await opts.draftClaim.postComment(opts.draftClaim.pr, card.draftClaim.body);
|
|
1357
|
+
} catch (error) {
|
|
1358
|
+
// 댓글이 없으면 «살아 있는» 예약도 남기지 않는다. 다음 손이 다시 claim 할 수 있다.
|
|
1359
|
+
card = updateTaskCard(path, card.id, (current) => current?.draftClaim
|
|
1360
|
+
? { ...current, draftClaim: { ...current.draftClaim, body: undefined } } : undefined) ?? card;
|
|
1361
|
+
throw error;
|
|
1362
|
+
}
|
|
1363
|
+
if (postedTo !== undefined) {
|
|
1364
|
+
card = updateTaskCard(path, card.id, (current) => current?.draftClaim
|
|
1365
|
+
? { ...current, draftClaim: { ...current.draftClaim, postedTo } } : undefined) ?? card;
|
|
1366
|
+
}
|
|
1367
|
+
try { debug.log('task-agent.draft-claim', 'comment-posted', { card: id, pr: opts.draftClaim.pr,
|
|
1368
|
+
...(postedTo !== undefined ? { postedTo } : {}) }); } catch { /* fail-soft */ }
|
|
1369
|
+
}
|
|
810
1370
|
try { debug.log('task-agent', 'handed', { taskId: id, seat: card.seat ?? null, checklistId: card.checklistId ?? null, mode, projectId: project?.id ?? null, targetIsGit, taLand: card.taLand === true, runPriority: card.identity ? runPriorityClass(card.identity) : null }); } catch { /* fail-soft */ }
|
|
811
1371
|
if (childLlm) {
|
|
812
1372
|
try { debug.log('task-agent', 'child-llm', { taskId: id, input: opts.childLlm, provider: childLlm.provider, model: childLlm.model, effort: childLlm.effort ?? null, mode }); } catch { /* fail-soft */ }
|
|
813
1373
|
}
|
|
814
1374
|
if (mode === 'shadow') return { card, move, mode, launched: false, ...(project ? { cwd: project.target } : {}) };
|
|
1375
|
+
// 2판 — launcher 'graph-run' 조합은 launcher(harness say 발사기) 대신 실제 graph run 진입점(runGraph)으로 발사한다.
|
|
1376
|
+
if (graphRun && graphRunPath) {
|
|
1377
|
+
const runId = mintRunId();
|
|
1378
|
+
const launchId = newLaunchUtteranceId();
|
|
1379
|
+
recordLaunchUtterance({ source: 'hand', utterance: opts.text, launchId });
|
|
1380
|
+
let state: GraphRunState;
|
|
1381
|
+
try {
|
|
1382
|
+
state = await (opts.graphRunner ?? runGraph)(graphRunPath, { runId, input: { ask: text }, quiet: true });
|
|
1383
|
+
} catch (error) {
|
|
1384
|
+
// 조합 파일·대상 node가 없으면 runGraph 가 구체 사유로 던진다 — 임의 성공 처리하지 않는다.
|
|
1385
|
+
const reason = `graph run 실패: ${error instanceof Error ? error.message : String(error)}`;
|
|
1386
|
+
const failed: TaskCard = { ...card, status: 'launch-failed', runId, launchId,
|
|
1387
|
+
history: [...card.history, { at: (opts.now ?? (() => new Date()))().toISOString(), event: 'launch-failed', detail: reason, runId }] };
|
|
1388
|
+
writeCard(path, failed);
|
|
1389
|
+
try { debug.log('task-agent', 'launch-failed', { taskId: id, seat: card.seat ?? null, reason }); } catch { /* fail-soft */ }
|
|
1390
|
+
throw new TaskLaunchError(failed, reason);
|
|
1391
|
+
}
|
|
1392
|
+
const at = (opts.now ?? (() => new Date()))().toISOString();
|
|
1393
|
+
const ok = state.status === 'done';
|
|
1394
|
+
// 실패 종료도 구체 blocker(종료 상태·이유·마지막 node)를 기록한다 — 임의 성공 처리하지 않는다.
|
|
1395
|
+
const blocker = ok ? undefined : `graph run 종료 상태 ${state.status}${state.reason ? ` — ${state.reason}` : ''}`
|
|
1396
|
+
+ `${state.nodes.length ? ` — 마지막 node ${state.nodes.at(-1)?.nodeId} (ok=${state.nodes.at(-1)?.ok})` : ' — node 없음'}`;
|
|
1397
|
+
const launchedGraph: TaskCard = { ...card, status: ok ? 'launched' : 'failed', runId: state.runId, launchId,
|
|
1398
|
+
history: [...card.history,
|
|
1399
|
+
{ at, event: 'launch', detail: `graph run ${graphRunPath} (run ${state.runId})` },
|
|
1400
|
+
{ at, event: 'run-bound', detail: state.runId, runId: state.runId },
|
|
1401
|
+
...(blocker ? [{ at, event: 'graph-run-failed', detail: blocker, runId: state.runId }] : [])] };
|
|
1402
|
+
writeCard(path, launchedGraph);
|
|
1403
|
+
try { debug.log('task-agent', 'launched', { taskId: id, seat: card.seat ?? null, runId: state.runId }); } catch { /* fail-soft */ }
|
|
1404
|
+
return { card: launchedGraph, move, mode, launched: true, ...(project ? { cwd: project.target } : {}) };
|
|
1405
|
+
}
|
|
815
1406
|
if (!opts.launcher) throw new Error('--live 인데 launcher 가 없다');
|
|
816
1407
|
let prelaunch: AlreadyDoneDecision;
|
|
817
1408
|
try { prelaunch = completion === 'code-pr'
|
|
@@ -828,10 +1419,19 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
828
1419
|
writeCard(path, candidate);
|
|
829
1420
|
return { card: candidate, move: nextMoveFor(candidate), mode, launched: false, ...(project ? { cwd: project.target } : {}) };
|
|
830
1421
|
}
|
|
1422
|
+
// Only the code-PR harness Pod consumes podGoal. Keep the card and other launchers unchanged.
|
|
1423
|
+
const podLaunch = completion === 'code-pr' && selected.launcher === 'harness-say';
|
|
1424
|
+
let childGoal = card.text;
|
|
1425
|
+
if (podLaunch) {
|
|
1426
|
+
const knowhow = selectKnowhowPack(project?.target ?? resolve(import.meta.dir, '../..'), card.text, targetPaths);
|
|
1427
|
+
if (knowhow.text) childGoal = `${knowhow.text}\n\n${card.text}`;
|
|
1428
|
+
try { debug.log('task-agent', 'knowhow-pack', { taskId: id, ids: knowhow.ids, bytes: knowhow.bytes, injected: knowhow.bytes > 0 }); } catch { /* fail-soft */ }
|
|
1429
|
+
}
|
|
831
1430
|
const runId = mintRunId();
|
|
832
1431
|
const launchId = newLaunchUtteranceId();
|
|
833
1432
|
recordLaunchUtterance({ source: 'hand', utterance: opts.text, launchId });
|
|
834
1433
|
const context: TaskLaunchContext = { runId, launchId, launchUtterance: opts.text, env: { [HARNESS_RUN_ID_ENV]: runId, ELANOUS_TASK_CARD_ID: card.id,
|
|
1434
|
+
...parentRoleEnv,
|
|
835
1435
|
...(cardPrNumber(card) ? { ELANOUS_TASK_BOUND_PR: String(cardPrNumber(card)) } : {}),
|
|
836
1436
|
...(card.checklistId ? { ELANOUS_POD_SLOT_ID: card.checklistId } : {}),
|
|
837
1437
|
...(card.seat ? { ELANOUS_POD_OWNER_KIND: 'seat', ELANOUS_POD_OWNER_ID: card.seat } : {}),
|
|
@@ -839,10 +1439,10 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
|
|
|
839
1439
|
// An omitted card provider uses the established Pod default. Carry the effective value explicitly so
|
|
840
1440
|
// remote-parent code never has to infer a provider from the serialized CLI argv.
|
|
841
1441
|
effectiveChildProvider: card.childLlm?.provider ?? 'openai-codex',
|
|
842
|
-
...(
|
|
1442
|
+
...(podLaunch ? { substrate: 'pod' as const, podGoal: childGoal } : {}) };
|
|
843
1443
|
let receipt: void | TaskLaunchReceipt;
|
|
844
1444
|
try {
|
|
845
|
-
receipt = await opts.launcher(move.command!, project?.target, context);
|
|
1445
|
+
receipt = await opts.launcher(podLaunch ? [...move.command!.slice(0, -1), childGoal] : move.command!, project?.target, context);
|
|
846
1446
|
} catch (error) {
|
|
847
1447
|
const reason = error instanceof Error ? error.message : String(error);
|
|
848
1448
|
const failed: TaskCard = { ...card, status: 'launch-failed', history: [{ at: (opts.now ?? (() => new Date()))().toISOString(), event: 'launch-failed', detail: reason }] };
|