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
|
@@ -3,6 +3,7 @@ import { classifySeatTrafficProposal } from '../../seat-loop/traffic-signal.js';
|
|
|
3
3
|
import { debug } from '../../debug/log.js';
|
|
4
4
|
import { LOOP_MESSAGE_ROUTES } from '../msg-address.js';
|
|
5
5
|
import { replyWithAgent, type AgentReplyInput } from '../agent-reply.js';
|
|
6
|
+
import { knowhowAdvice, type KnowhowAdvice, type KnowhowOptions } from './knowhow-pack.js';
|
|
6
7
|
import type { RoleLlmSpec } from '../../user-config.js';
|
|
7
8
|
import type { LLMProvider } from '../../llm.js';
|
|
8
9
|
|
|
@@ -28,18 +29,59 @@ function trafficProposal(request: Message): 'hold' | 'UNHOLD' | null {
|
|
|
28
29
|
? null : classifySeatTrafficProposal(request.body);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
export interface CoordinatorInboxOptions {
|
|
33
|
+
/** `false` disables the resident knowhow pack (traffic rule only). */
|
|
34
|
+
knowhow?: KnowhowOptions | false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const NO_LOCK_LINE = '실제 잠금 변경은 수행하지 않았습니다.';
|
|
38
|
+
|
|
39
|
+
function flatten(text: string, max: number): string {
|
|
40
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
41
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Propose a resident K item: cite the pack, the item id and the measurement it was judged by. */
|
|
45
|
+
function knowhowProposal(advice: KnowhowAdvice): { proposal: string; evidence: string } {
|
|
46
|
+
const cite = `${advice.packVersion} 팩 ${advice.packHash} · ${advice.item.id} «${advice.item.title}»`;
|
|
47
|
+
const measurement = `재는 명령: \`${advice.item.command}\` → ${advice.detail}`;
|
|
48
|
+
if (advice.freshness === 'stale') {
|
|
49
|
+
return {
|
|
50
|
+
proposal: `모름 — 노하우 낡음 의심 (${advice.item.id})`,
|
|
51
|
+
evidence: `${cite} · ${measurement} — 기대와 어긋나 처방을 제안하지 않습니다. OP 가 항목을 갱신해야 합니다.`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const freshness = advice.freshness === 'confirmed' ? '기대 일치'
|
|
55
|
+
: advice.freshness === 'unverifiable' ? '기대 문면 — 사람 확인' : '재지 못함 — 사람 확인';
|
|
56
|
+
return {
|
|
57
|
+
proposal: `${advice.item.id} — ${flatten(advice.item.prescription, 240)}`,
|
|
58
|
+
evidence: `${cite} · ${measurement} (${freshness}) — 제안만 하고 어떤 쓰기도 하지 않습니다.`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** This loop suggests traffic moves and quotes knowhow; it never changes traffic.json or the ledgers. */
|
|
63
|
+
export function coordinatorReply(request: Message, knowhow: KnowhowOptions | false = {}): string {
|
|
33
64
|
const traffic = trafficProposal(request);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
: '
|
|
38
|
-
|
|
65
|
+
if (traffic !== null) {
|
|
66
|
+
const proposal = traffic === 'hold' ? 'hold 제안' : 'UNHOLD 제안';
|
|
67
|
+
const evidence = traffic === 'hold' ? '자리 메시지에 «손 구현 착수»가 있습니다.'
|
|
68
|
+
: '자리 메시지에 «첫 줄 확정»이 있습니다.';
|
|
69
|
+
return `re #${request.id}\n제안: ${proposal}\n근거: ${evidence}\n${NO_LOCK_LINE}`;
|
|
70
|
+
}
|
|
71
|
+
const advice = knowhow === false ? null : knowhowAdvice(request.body, knowhow);
|
|
72
|
+
if (advice) {
|
|
73
|
+
const { proposal, evidence } = knowhowProposal(advice);
|
|
74
|
+
return `re #${request.id}\n제안: ${proposal}\n근거: ${evidence}\n${NO_LOCK_LINE}`;
|
|
75
|
+
}
|
|
76
|
+
const candidate = flatten(request.body, 200);
|
|
77
|
+
debug.log('loop.coordinator-knowhow', 'candidate', { requestId: request.id, from: request.from, question: candidate });
|
|
78
|
+
return `re #${request.id}\n제안: 모름 — OP/자리 판단 필요\n근거: 착수·첫 줄 확정을 확정 진술로 확인하지 못했고, `
|
|
79
|
+
+ `맞는 K-OP 노하우 항목도 없습니다. 칸·traffic 근거를 사람이 확인해야 합니다.\n`
|
|
80
|
+
+ `노하우 후보: ${candidate} — 새 K-OP 항목의 입력으로 쓸 수 있습니다.\n${NO_LOCK_LINE}`;
|
|
39
81
|
}
|
|
40
82
|
|
|
41
83
|
/** Single reply writer: prefer the durable thread link, while recognizing pre-migration body markers. */
|
|
42
|
-
function writeCoordinatorReply(store: MsgStore, request: Message): { id: number; posted: boolean } {
|
|
84
|
+
function writeCoordinatorReply(store: MsgStore, request: Message, replyText: string): { id: number; posted: boolean } {
|
|
43
85
|
const marker = `re #${request.id}`;
|
|
44
86
|
const linked = store.db.query(`SELECT id FROM msg_messages WHERE sender = ? AND recipient = ?
|
|
45
87
|
AND reply_to = ? AND kind = 'reply' ORDER BY id LIMIT 1`).get(RECIPIENT, request.from, request.id) as { id: number } | null;
|
|
@@ -49,12 +91,14 @@ function writeCoordinatorReply(store: MsgStore, request: Message): { id: number;
|
|
|
49
91
|
.get(RECIPIENT, request.from, marker, marker.length + 1, `${marker}\n`) as { id: number } | null;
|
|
50
92
|
if (legacy) return { id: legacy.id, posted: false };
|
|
51
93
|
const reply = store.post({ from: RECIPIENT, to: request.from,
|
|
52
|
-
body:
|
|
94
|
+
body: replyText.slice(marker.length + 1), kind: 'reply', replyTo: request.id });
|
|
53
95
|
return { id: reply.id, posted: true };
|
|
54
96
|
}
|
|
55
97
|
|
|
56
98
|
/** One transaction ties a reply to its acknowledgement. A retry finds the durable receipt. */
|
|
57
|
-
export function runCoordinatorInbox(inputStore?: MsgStore, limit = 100, path?: string
|
|
99
|
+
export function runCoordinatorInbox(inputStore?: MsgStore, limit = 100, path?: string,
|
|
100
|
+
options: CoordinatorInboxOptions = {}): CoordinatorInboxResult {
|
|
101
|
+
const knowhow = options.knowhow ?? {};
|
|
58
102
|
const store = inputStore ?? openMsgStore(path);
|
|
59
103
|
const ownStore = inputStore === undefined;
|
|
60
104
|
let replied = 0;
|
|
@@ -70,10 +114,14 @@ export function runCoordinatorInbox(inputStore?: MsgStore, limit = 100, path?: s
|
|
|
70
114
|
continue;
|
|
71
115
|
}
|
|
72
116
|
const key = `coord-inbox:${request.id}:${request.from}`;
|
|
117
|
+
// Measurement runs outside the write transaction: a pack command never holds the ledger lock.
|
|
118
|
+
const known = store.db.query('SELECT message_id FROM msg_provenance WHERE provenance_key = ?')
|
|
119
|
+
.get(key) as { message_id: number } | null;
|
|
120
|
+
const replyText = known ? '' : coordinatorReply(request, knowhow);
|
|
73
121
|
const result = store.db.transaction(() => {
|
|
74
122
|
const existing = store.db.query('SELECT message_id FROM msg_provenance WHERE provenance_key = ?')
|
|
75
123
|
.get(key) as { message_id: number } | null;
|
|
76
|
-
const reply = existing ? { id: existing.message_id, posted: false } : writeCoordinatorReply(store, request);
|
|
124
|
+
const reply = existing ? { id: existing.message_id, posted: false } : writeCoordinatorReply(store, request, replyText);
|
|
77
125
|
if (!existing) store.db.query('INSERT INTO msg_provenance(provenance_key, message_id) VALUES (?, ?)').run(key, reply.id);
|
|
78
126
|
store.ack(RECIPIENT, request.id);
|
|
79
127
|
return { posted: reply.posted };
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K3 knowledge pack — the coordinator reads OP knowhow from `내부 문서 `KNOWHOW``
|
|
3
|
+
* on every tick, so a doc landing alone (no code deploy) refreshes what is resident.
|
|
4
|
+
*
|
|
5
|
+
* A pack holds only items whose `상태:` is `active` **and** that carry a `재는 명령:`;
|
|
6
|
+
* every item is ordered by id and the pack carries a content hash so a reply can cite
|
|
7
|
+
* exactly which pack it read.
|
|
8
|
+
*
|
|
9
|
+
* The inbox may then *propose* an item's 처방 — it never writes, and it never changes a lock.
|
|
10
|
+
* A measurement command is executed only when it passes the read-only allowlist; when its
|
|
11
|
+
* output contradicts the item's `기대`, the advice is stale and the inbox answers 모름.
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from 'node:crypto';
|
|
14
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
15
|
+
import { spawnSync } from 'node:child_process';
|
|
16
|
+
import { dirname, join } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import { debug } from '../../debug/log.js';
|
|
19
|
+
|
|
20
|
+
export const KNOWHOW_PACK_VERSION = 'K3';
|
|
21
|
+
export const KNOWHOW_DOC_RELATIVE_PATH = 'docs/roles/OP/KNOWHOW.md';
|
|
22
|
+
|
|
23
|
+
export interface KnowhowItem {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
status: string;
|
|
27
|
+
situation: string;
|
|
28
|
+
signal: string;
|
|
29
|
+
prescription: string;
|
|
30
|
+
command: string;
|
|
31
|
+
expectation: string;
|
|
32
|
+
validWhen: string;
|
|
33
|
+
source: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface KnowhowPack {
|
|
37
|
+
version: string;
|
|
38
|
+
hash: string;
|
|
39
|
+
docPath: string;
|
|
40
|
+
items: KnowhowItem[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface KnowhowCommandRun {
|
|
44
|
+
status: number;
|
|
45
|
+
output: string;
|
|
46
|
+
/** Set when the runner refused to execute (placeholder, timeout, spawn failure). */
|
|
47
|
+
skipped?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type KnowhowCommandRunner = (command: string) => KnowhowCommandRun;
|
|
51
|
+
|
|
52
|
+
export interface KnowhowOptions {
|
|
53
|
+
/** Explicit doc path; otherwise `ELANOUS_KNOWHOW_DOC`, otherwise the repository copy. */
|
|
54
|
+
docPath?: string;
|
|
55
|
+
/** Working directory for measurement commands. */
|
|
56
|
+
cwd?: string;
|
|
57
|
+
/** Measurement seam: replaced by tests, defaults to the guarded read-only runner. */
|
|
58
|
+
runCommand?: KnowhowCommandRunner;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type KnowhowFreshness = 'confirmed' | 'stale' | 'unmeasured' | 'unverifiable';
|
|
62
|
+
|
|
63
|
+
export interface KnowhowMatch {
|
|
64
|
+
item: KnowhowItem;
|
|
65
|
+
score: number;
|
|
66
|
+
matchedTokens: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface KnowhowAdvice extends KnowhowMatch {
|
|
70
|
+
packVersion: string;
|
|
71
|
+
packHash: string;
|
|
72
|
+
freshness: KnowhowFreshness;
|
|
73
|
+
detail: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Label → item field. Labels keep their parenthetical form when the doc uses one. */
|
|
77
|
+
const FIELD_LABELS: Array<[RegExp, keyof KnowhowItem]> = [
|
|
78
|
+
[/^상황$/i, 'situation'],
|
|
79
|
+
[/^신호(?:\(관측\))?$/i, 'signal'],
|
|
80
|
+
[/^처방(?:\(힐링\))?$/i, 'prescription'],
|
|
81
|
+
[/^재는 명령$/i, 'command'],
|
|
82
|
+
[/^기대$/i, 'expectation'],
|
|
83
|
+
[/^유효 조건$/i, 'validWhen'],
|
|
84
|
+
[/^출처$/i, 'source'],
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
function stripTicks(value: string): string {
|
|
88
|
+
const trimmed = value.trim();
|
|
89
|
+
const match = /^`([\s\S]*)`$/.exec(trimmed);
|
|
90
|
+
return match ? match[1]!.trim() : trimmed;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function labeledLine(section: string, field: keyof KnowhowItem): string {
|
|
94
|
+
for (const line of section.split('\n')) {
|
|
95
|
+
const entry = /^-\s+([^:]{1,24}):\s*(.+)$/.exec(line.trim());
|
|
96
|
+
if (!entry) continue;
|
|
97
|
+
const label = entry[1]!.trim();
|
|
98
|
+
if (FIELD_LABELS.some(([pattern, name]) => name === field && pattern.test(label))) return stripTicks(entry[2]!);
|
|
99
|
+
}
|
|
100
|
+
return '';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Split the markdown inventory into K items. Unknown labels are ignored, not fatal. */
|
|
104
|
+
export function parseKnowhowDoc(text: string): KnowhowItem[] {
|
|
105
|
+
const sections = text.split(/^## /m).slice(1);
|
|
106
|
+
const items: KnowhowItem[] = [];
|
|
107
|
+
for (const section of sections) {
|
|
108
|
+
const heading = /^(K-OP-(?:[A-Z]{1,4}-)?\d+)\s+(.*)$/.exec(section.split('\n', 1)[0] ?? '');
|
|
109
|
+
if (!heading) continue;
|
|
110
|
+
const item: KnowhowItem = {
|
|
111
|
+
id: heading[1]!, title: heading[2]!.trim(), status: '', situation: labeledLine(section, 'situation'),
|
|
112
|
+
signal: labeledLine(section, 'signal'), prescription: labeledLine(section, 'prescription'),
|
|
113
|
+
command: labeledLine(section, 'command'), expectation: labeledLine(section, 'expectation'),
|
|
114
|
+
validWhen: labeledLine(section, 'validWhen'), source: labeledLine(section, 'source'),
|
|
115
|
+
};
|
|
116
|
+
const status = /상태:\s*([A-Za-z][A-Za-z-]*)/.exec(item.source);
|
|
117
|
+
if (status) item.status = status[1]!;
|
|
118
|
+
if (item.status !== 'active') continue;
|
|
119
|
+
if (!item.command || /^\(없음/.test(item.command)) continue;
|
|
120
|
+
items.push(item);
|
|
121
|
+
}
|
|
122
|
+
return items.sort((a, b) => a.id.localeCompare(b.id));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function buildKnowhowPack(items: KnowhowItem[], docPath: string): KnowhowPack {
|
|
126
|
+
const body = items.map(item => [item.id, item.title, item.situation, item.signal, item.prescription,
|
|
127
|
+
item.command, item.expectation].join('\n')).join('\n---\n');
|
|
128
|
+
const hash = createHash('sha256').update(`${KNOWHOW_PACK_VERSION}\n${body}`).digest('hex').slice(0, 16);
|
|
129
|
+
return { version: KNOWHOW_PACK_VERSION, hash, docPath, items };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Marker text for a command that still carries `<...>` placeholders from the doc. */
|
|
133
|
+
const PLACEHOLDER_SOURCE = '<[^<>\\n]{1,60}>';
|
|
134
|
+
const PLACEHOLDER = new RegExp(PLACEHOLDER_SOURCE, 'g');
|
|
135
|
+
|
|
136
|
+
function repositoryRoot(): string | null {
|
|
137
|
+
let current = dirname(fileURLToPath(import.meta.url));
|
|
138
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
139
|
+
if (existsSync(join(current, KNOWHOW_DOC_RELATIVE_PATH))) return current;
|
|
140
|
+
const parent = dirname(current);
|
|
141
|
+
if (parent === current) break;
|
|
142
|
+
current = parent;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function resolveKnowhowDocPath(explicit?: string): string | null {
|
|
148
|
+
if (explicit) return existsSync(explicit) ? explicit : null;
|
|
149
|
+
const fromEnv = process.env.ELANOUS_KNOWHOW_DOC;
|
|
150
|
+
if (fromEnv) return existsSync(fromEnv) ? fromEnv : null;
|
|
151
|
+
if (existsSync(join(process.cwd(), KNOWHOW_DOC_RELATIVE_PATH))) return join(process.cwd(), KNOWHOW_DOC_RELATIVE_PATH);
|
|
152
|
+
const root = repositoryRoot();
|
|
153
|
+
return root ? join(root, KNOWHOW_DOC_RELATIVE_PATH) : null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const packCache = new Map<string, { stamp: string; pack: KnowhowPack }>();
|
|
157
|
+
|
|
158
|
+
/** Resident pack for one tick: re-read whenever the doc's mtime/size changes. */
|
|
159
|
+
export function loadKnowhowPack(docPath: string): KnowhowPack | null {
|
|
160
|
+
if (!existsSync(docPath)) return null;
|
|
161
|
+
let stamp: string;
|
|
162
|
+
try {
|
|
163
|
+
const info = statSync(docPath);
|
|
164
|
+
stamp = `${info.mtimeMs}:${info.size}`;
|
|
165
|
+
} catch { return null; }
|
|
166
|
+
const cached = packCache.get(docPath);
|
|
167
|
+
if (cached && cached.stamp === stamp) return cached.pack;
|
|
168
|
+
const pack = buildKnowhowPack(parseKnowhowDoc(readFileSync(docPath, 'utf8')), docPath);
|
|
169
|
+
packCache.set(docPath, { stamp, pack });
|
|
170
|
+
debug.log('loop.knowhow-pack', 'load', { version: pack.version, hash: pack.hash,
|
|
171
|
+
items: pack.items.length, docPath });
|
|
172
|
+
return pack;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const STOPWORDS = new Set(['그리고', '그러나', '하지만', '그러면', '어떻게', '무엇', '뭐가', '뭘', '이거', '그거',
|
|
176
|
+
'저거', '지금', '오늘', '내일', '확인', '요청', '질문', '경우', '때문', '때는', '먼저', '다시', '대한', '위해',
|
|
177
|
+
'에서', '으로', '하는', '하지', '한다', '있다', '없다', '같다', '되는', '되나', '됐다', '있나', '인가', '무슨',
|
|
178
|
+
'어느', '이런', '그런', '저런', '좀', '더', '또는', '그게', '이게', '저게', '합니까', '인지', '하는데',
|
|
179
|
+
'보다', '라며', '해도', '하면', '해서', '부터', '까지', '아직', '이미', '모두', '이후', '이전', '동안',
|
|
180
|
+
'the', 'and', 'for', 'you', 'can', 'this', 'that', 'what', 'which', 'how', 'why', 'when', 'with', 'from',
|
|
181
|
+
'are', 'was', 'were', 'has', 'have', 'had', 'not', 'but', 'all', 'any', 'our', 'your', 'its', 'it', 'is',
|
|
182
|
+
'of', 'to', 'in', 'on', 'do', 'does', 'did', 'please', 'anyone']);
|
|
183
|
+
|
|
184
|
+
const KOREAN_SUFFIXES = ['에서부터', '으로부터', '에서는', '으로는', '이었습니다', '했습니다', '됩니다', '됐습니다',
|
|
185
|
+
'합니까', '했나요', '되나요', '인가요', '에서', '으로', '부터', '까지', '했나', '됐나', '되나', '했지', '하지',
|
|
186
|
+
'됐다', '한다', '된다', '이다', '있다', '없다', '었던', '였던', '라는', '이라', '거나', '면서', '지만',
|
|
187
|
+
'에게', '한테', '보다', '처럼', '만큼', '라고', '하고', '해도', '하면', '인데', '나요', '가요', '세요',
|
|
188
|
+
'은', '는', '을', '를', '이', '가', '의', '에', '와', '과', '로', '도', '만', '라', '며', '서', '나', '고', '면'];
|
|
189
|
+
|
|
190
|
+
function normalizeToken(raw: string): string {
|
|
191
|
+
let token = raw.toLowerCase();
|
|
192
|
+
for (const suffix of KOREAN_SUFFIXES) {
|
|
193
|
+
if (token.length > suffix.length + 1 && token.endsWith(suffix)) {
|
|
194
|
+
token = token.slice(0, -suffix.length);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return token;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function tokenize(text: string): string[] {
|
|
202
|
+
const tokens: string[] = [];
|
|
203
|
+
for (const raw of text.toLowerCase().split(/[^0-9a-z가-힣-]+/)) {
|
|
204
|
+
const token = normalizeToken(raw);
|
|
205
|
+
if (token.length < 2 || STOPWORDS.has(raw) || STOPWORDS.has(token)) continue;
|
|
206
|
+
if (/^\d+$/.test(token)) continue;
|
|
207
|
+
tokens.push(token);
|
|
208
|
+
}
|
|
209
|
+
return tokens;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function tokensMatch(a: string, b: string): boolean {
|
|
213
|
+
if (a === b) return true;
|
|
214
|
+
if (a.length >= 3 && b.length >= 3 && (a.startsWith(b) || b.startsWith(a))) return true;
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const MIN_MATCH_SCORE = 2.2;
|
|
219
|
+
const MIN_MATCH_TOKENS = 2;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Match a question against the pack item text (title ⊕ 상황 ⊕ 신호) using inverse document
|
|
223
|
+
* frequency, so a word shared by most items ("착지", "PR") cannot carry a match alone.
|
|
224
|
+
*/
|
|
225
|
+
export function matchKnowhowItem(pack: KnowhowPack, question: string, minScore = MIN_MATCH_SCORE): KnowhowMatch | null {
|
|
226
|
+
const questionTokens = [...new Set(tokenize(question))];
|
|
227
|
+
if (questionTokens.length === 0 || pack.items.length === 0) return null;
|
|
228
|
+
const itemTokens = pack.items.map(item => [...new Set(tokenize(`${item.title} ${item.situation} ${item.signal}`))]);
|
|
229
|
+
const total = pack.items.length;
|
|
230
|
+
const scored = pack.items.map((item, index) => {
|
|
231
|
+
const matched: string[] = [];
|
|
232
|
+
let score = 0;
|
|
233
|
+
for (const token of questionTokens) {
|
|
234
|
+
const hits = itemTokens.filter(tokens => tokens.some(candidate => tokensMatch(token, candidate))).length;
|
|
235
|
+
if (hits === 0 || !itemTokens[index]!.some(candidate => tokensMatch(token, candidate))) continue;
|
|
236
|
+
matched.push(token);
|
|
237
|
+
score += Math.log((total + 1) / (hits + 0.5));
|
|
238
|
+
}
|
|
239
|
+
return { item, score: Number(score.toFixed(3)), matchedTokens: matched };
|
|
240
|
+
}).sort((a, b) => b.score - a.score || a.item.id.localeCompare(b.item.id));
|
|
241
|
+
const best = scored[0];
|
|
242
|
+
if (!best || best.matchedTokens.length < MIN_MATCH_TOKENS || best.score < minScore) return null;
|
|
243
|
+
return best;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const READ_ONLY_BINARIES = new Set(['rg', 'grep', 'cat', 'head', 'tail', 'wc', 'ls', 'jq', 'awk', 'find',
|
|
247
|
+
'sort', 'uniq', 'cut', 'echo', 'pwd', 'stat', 'file', 'date', 'printf', 'true', 'test']);
|
|
248
|
+
const GIT_READ_ONLY_SUBCOMMANDS = new Set(['status', 'log', 'show', 'diff', 'rev-parse', 'rev-list',
|
|
249
|
+
'ls-files', 'ls-tree', 'worktree', 'shortlog', 'blame', 'describe', 'branch', 'tag', 'remote', 'config', 'cat-file']);
|
|
250
|
+
const GIT_WRITE_ARGS = new Set(['-d', '-D', '-m', '-M', '--delete', '--move', '--force', '--set', '--unset',
|
|
251
|
+
'--add', '--edit', '--prune', 'add', 'commit', 'push', 'merge', 'reset', 'checkout', 'switch', 'clean',
|
|
252
|
+
'rm', 'mv', 'apply', 'stash', 'gc', 'update-ref', 'submodule', 'rebase', 'cherry-pick', 'revert']);
|
|
253
|
+
const ELANOUSH_READ_ONLY: Record<string, string[] | null> = {
|
|
254
|
+
logs: null, 'tasks:show': null, 'tasks:list': null,
|
|
255
|
+
release: ['checklist'], decisions: ['list'], msg: ['list'], memory: ['list'],
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export type ReadOnlyVerdict = { ok: true } | { ok: false; reason: string };
|
|
259
|
+
|
|
260
|
+
/** Allowlist guard: only commands that cannot mutate the repository or the ledgers run. */
|
|
261
|
+
export function isReadOnlyCommand(command: string): ReadOnlyVerdict {
|
|
262
|
+
const stripped = command.replace(PLACEHOLDER, ' ');
|
|
263
|
+
if (!stripped.trim()) return { ok: false, reason: 'empty command' };
|
|
264
|
+
if (/[<>`$]|[;\n]/.test(stripped)) return { ok: false, reason: 'shell redirect, substitution or sequence' };
|
|
265
|
+
const segments = stripped.split(/\s*(?:&&|\|\||\||&)\s*/).map(part => part.trim()).filter(Boolean);
|
|
266
|
+
if (segments.length === 0) return { ok: false, reason: 'empty command' };
|
|
267
|
+
for (const segment of segments) {
|
|
268
|
+
const words = segment.split(/\s+/);
|
|
269
|
+
const binary = words[0]!.replace(/^.*\//, '');
|
|
270
|
+
const args = words.slice(1);
|
|
271
|
+
if (binary === 'git') {
|
|
272
|
+
const sub = args.find(word => !word.startsWith('-'));
|
|
273
|
+
if (!sub) return { ok: false, reason: 'git without subcommand' };
|
|
274
|
+
if (!GIT_READ_ONLY_SUBCOMMANDS.has(sub)) return { ok: false, reason: `git ${sub} is not read-only` };
|
|
275
|
+
if (args.some(word => GIT_WRITE_ARGS.has(word))) return { ok: false, reason: `git ${sub} write flag` };
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (binary === 'eln' || binary === 'elanous') {
|
|
279
|
+
const verbs = args.filter(word => !word.startsWith('-'));
|
|
280
|
+
const [first, second, third] = verbs;
|
|
281
|
+
// `eln tasks show` and `eln release checklist status` name the verb in two words.
|
|
282
|
+
if (first && second && `${first}:${second}` in ELANOUSH_READ_ONLY) {
|
|
283
|
+
const allowed = ELANOUSH_READ_ONLY[`${first}:${second}`];
|
|
284
|
+
if (allowed && (!third || !allowed.includes(third))) {
|
|
285
|
+
return { ok: false, reason: `${binary} ${first} ${second} ${third ?? ''} is not read-only` };
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (!first || !(first in ELANOUSH_READ_ONLY)) return { ok: false, reason: `${binary} ${first ?? ''} is not read-only` };
|
|
290
|
+
const allowed = ELANOUSH_READ_ONLY[first];
|
|
291
|
+
if (allowed && (!second || !allowed.includes(second))) return { ok: false, reason: `${binary} ${first} ${second ?? ''} is not read-only` };
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (!READ_ONLY_BINARIES.has(binary)) return { ok: false, reason: `${binary} is not on the read-only allowlist` };
|
|
295
|
+
}
|
|
296
|
+
return { ok: true };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export type ExpectationVerdict = 'confirmed' | 'stale' | 'unverifiable';
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Compare a measurement output against the item's 기대. Only machine-checkable wordings
|
|
303
|
+
* are judged: `N 줄/건/개` (exact count) and `≥N` / `N 이상` (lower bound).
|
|
304
|
+
*/
|
|
305
|
+
export function evaluateExpectation(expectation: string, output: string): { verdict: ExpectationVerdict; detail: string } {
|
|
306
|
+
const lines = output.split('\n').map(line => line.trim()).filter(line => line.length > 0);
|
|
307
|
+
const counted = /(\d+)\s*(줄|행|건|개|line)/.exec(expectation);
|
|
308
|
+
if (counted) {
|
|
309
|
+
const expected = Number(counted[1]);
|
|
310
|
+
const ok = lines.length === expected;
|
|
311
|
+
return { verdict: ok ? 'confirmed' : 'stale', detail: `기대 ${expected}${counted[2]} · 실제 ${lines.length}줄` };
|
|
312
|
+
}
|
|
313
|
+
const lower = /(?:[≥>=]\s*(\d+))|(?:(\d+)\s*이상)/.exec(expectation);
|
|
314
|
+
if (lower) {
|
|
315
|
+
const expected = Number(lower[1] ?? lower[2]);
|
|
316
|
+
const numbers = (output.match(/\d+/g) ?? []).map(Number);
|
|
317
|
+
const ok = numbers.length > 0 && numbers.every(value => value >= expected);
|
|
318
|
+
return { verdict: ok ? 'confirmed' : 'stale',
|
|
319
|
+
detail: `기대 ≥${expected} · 실제 ${numbers.length > 0 ? numbers.join(',') : '(수 없음)'}` };
|
|
320
|
+
}
|
|
321
|
+
if (!lines.length) return { verdict: 'stale', detail: '기대 비교 불가 · 재는 명령 출력이 비었다' };
|
|
322
|
+
return { verdict: 'unverifiable', detail: `기대 문면: ${expectation.slice(0, 120)} — 자동 비교 규칙 없음` };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Default runner: guarded, bounded, and never shells a doc placeholder. */
|
|
326
|
+
export function readOnlyRunner(cwd: string): KnowhowCommandRunner {
|
|
327
|
+
return (command: string): KnowhowCommandRun => {
|
|
328
|
+
const verdict = isReadOnlyCommand(command);
|
|
329
|
+
if (!verdict.ok) return { status: -1, output: '', skipped: verdict.reason };
|
|
330
|
+
if (new RegExp(PLACEHOLDER_SOURCE).test(command)) return { status: -1, output: '', skipped: 'placeholder 미치환' };
|
|
331
|
+
const run = spawnSync('bash', ['-c', command], { cwd, encoding: 'utf8', timeout: 15_000, maxBuffer: 1 << 20 });
|
|
332
|
+
if (run.error) return { status: -1, output: '', skipped: run.error.message.slice(0, 120) };
|
|
333
|
+
return { status: run.status ?? -1, output: `${run.stdout ?? ''}${run.stderr ?? ''}` };
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function measureKnowhowItem(
|
|
338
|
+
item: KnowhowItem, run: KnowhowCommandRunner,
|
|
339
|
+
): { freshness: KnowhowFreshness; detail: string } {
|
|
340
|
+
const verdict = isReadOnlyCommand(item.command);
|
|
341
|
+
if (!verdict.ok) return { freshness: 'unmeasured', detail: `재지 못함 — ${verdict.reason} (읽기 전용 허용 목록 밖)` };
|
|
342
|
+
const result = run(item.command);
|
|
343
|
+
if (result.skipped) return { freshness: 'unmeasured', detail: `재지 못함 — ${result.skipped}` };
|
|
344
|
+
if (result.status !== 0) return { freshness: 'unmeasured', detail: `재지 못함 — rc=${result.status}` };
|
|
345
|
+
const judged = evaluateExpectation(item.expectation, result.output);
|
|
346
|
+
return { freshness: judged.verdict, detail: judged.detail };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** The advice the inbox may propose: item ⊕ pack identity ⊕ freshness of its measurement. */
|
|
350
|
+
export function knowhowAdvice(question: string, options: KnowhowOptions = {}): KnowhowAdvice | null {
|
|
351
|
+
const docPath = resolveKnowhowDocPath(options.docPath);
|
|
352
|
+
if (!docPath) return null;
|
|
353
|
+
const pack = loadKnowhowPack(docPath);
|
|
354
|
+
if (!pack) return null;
|
|
355
|
+
const match = matchKnowhowItem(pack, question);
|
|
356
|
+
if (!match) return null;
|
|
357
|
+
const run = options.runCommand ?? readOnlyRunner(options.cwd ?? process.cwd());
|
|
358
|
+
const measured = measureKnowhowItem(match.item, run);
|
|
359
|
+
const advice: KnowhowAdvice = { ...match, packVersion: pack.version, packHash: pack.hash,
|
|
360
|
+
freshness: measured.freshness, detail: measured.detail };
|
|
361
|
+
debug.log('loop.knowhow-pack', 'advice', { id: match.item.id, score: match.score,
|
|
362
|
+
freshness: advice.freshness, packHash: pack.hash });
|
|
363
|
+
return advice;
|
|
364
|
+
}
|
|
@@ -11,12 +11,14 @@ import { getUserConfig, ORCHESTRATOR_DEFAULTS, resolveConfiguredAgentRoleLlm, ty
|
|
|
11
11
|
import { rubricPriority } from '../../release-loop/rubric.js';
|
|
12
12
|
import { debug } from '../../debug/log.js';
|
|
13
13
|
import { emitLoopHeartbeat } from '../neighbor-runtime.js';
|
|
14
|
+
import { ConsensusEngine } from '../consensus.js';
|
|
14
15
|
import { listSelfDevRuns, runSummaryLine, selfDevRunsDir } from '../../self-dev/run-store.js';
|
|
15
16
|
import { planAction, runSeatLoopOnce, type SeatDeps, type SeatItem } from '../../seat-loop/seat-loop.js';
|
|
16
17
|
import { addHarnessQueue, harnessQueueOutcome, setQueuedPoolHint } from '../../harness/harness-queue.js';
|
|
17
18
|
import { placeOnGrid, type GridHost } from './grid-place.js';
|
|
18
19
|
import { checkPodPool, parsePodPool, resolvePodPoolSpec } from '../../task-orchestrator/surfaces/pod-pool.js';
|
|
19
20
|
import { leaseKubectl } from '../../task-orchestrator/surfaces/pod-lease.js';
|
|
21
|
+
import { defaultAnomalyCluster, extractContainerExit, type AnomalyCluster } from './anomaly-cluster.js';
|
|
20
22
|
import { isLaunchEligible, isTrafficLaunch, recordDispatchCycle, seatOfTree, type TrafficProcess } from './traffic.js';
|
|
21
23
|
import { defaultListHarnessProcesses } from '../../harness/harness-cli-command.js';
|
|
22
24
|
import * as testGuard from '../../instance/test-write-guard.js';
|
|
@@ -24,6 +26,7 @@ import { seatCapDetails } from '../budget.js';
|
|
|
24
26
|
export { isLaunchEligible } from './traffic.js';
|
|
25
27
|
import { readTaskAgentState, TASK_SEATS, type HandTaskOptions, type TaskCard as TaskAgentCard, type HandTaskResult, type TaskLauncher, type TaskSeat } from '../../task-agent/task-hand.js';
|
|
26
28
|
import { runCoordinatorAgentInbox, runCoordinatorInbox, type CoordinatorInboxResult } from './inbox.js';
|
|
29
|
+
import type { KnowhowOptions } from './knowhow-pack.js';
|
|
27
30
|
import { loadAgentRolePack, type AgentReplyInput } from '../agent-reply.js';
|
|
28
31
|
import type { LLMProvider } from '../../llm.js';
|
|
29
32
|
|
|
@@ -31,7 +34,7 @@ export type Window = '08' | '12' | '18';
|
|
|
31
34
|
export type Node = 'intake' | 'split' | 'place' | 'delegate' | 'launch' | 'reconcile' | 'report';
|
|
32
35
|
export type Mode = 'off' | 'shadow' | 'live';
|
|
33
36
|
const SEAT_LOOP_IDS: Readonly<Record<string, string>> = { OP: 'op-seat', MK: 'cmo-seat', TC: 'tc-seat', UX: 'ux-seat' };
|
|
34
|
-
export interface Cell { id: string; title: string; kind?: string; seat?: string; host?: string; gridHost?: boolean; version?: string; cardId: string; origin: 'candidate' | 'flow1a'; priority?: 'P0' | 'P1' | 'P2' | 'P3' | 'P4'; predecessors?: string[] }
|
|
37
|
+
export interface Cell { id: string; title: string; kind?: string; seat?: string; host?: string; gridHost?: boolean; version?: string; cardId: string; origin: 'candidate' | 'flow1a'; priority?: 'P0' | 'P1' | 'P2' | 'P3' | 'P4'; predecessors?: string[]; consensusProposalId?: string }
|
|
35
38
|
export interface TickState {
|
|
36
39
|
runId: string; window: Window; mode: Mode; day: string;
|
|
37
40
|
cards: TaskCard[]; skippedCards: Array<{ id: string; reason: string }>; cells: Cell[]; placed: number; unplaced?: number; delegated: number; wouldDelegate: number; rebalanced?: number; rebalanceBlocked?: Array<{ id: string; reason: string }>;
|
|
@@ -57,7 +60,7 @@ export interface TickState {
|
|
|
57
60
|
missing: string[];
|
|
58
61
|
}
|
|
59
62
|
/** FLOW1a contract: with `{ shadow: true }` the splitter only proposes cells and writes nothing (cards, ledgers, LLM side effects excepted). */
|
|
60
|
-
export type SplitAdapter = (card: TaskCard, opts?: { shadow?: boolean }) => Promise<Array<{ id: string; title: string; kind?: string; seat?: string; host?: string }>> | Array<{ id: string; title: string; kind?: string; seat?: string; host?: string }>;
|
|
63
|
+
export type SplitAdapter = (card: TaskCard, opts?: { shadow?: boolean }) => Promise<Array<{ id: string; title: string; kind?: string; seat?: string; host?: string; consensusProposalId?: string }>> | Array<{ id: string; title: string; kind?: string; seat?: string; host?: string; consensusProposalId?: string }>;
|
|
61
64
|
/** RELPLAN1 `placeCell(input: PlacementCell)` — owner·priority·predecessors are required; the result carries no seat. */
|
|
62
65
|
export type PlacementInput = { id: string; title: string; owner: string; priority: 'P0' | 'P1' | 'P2'; predecessors: string[] };
|
|
63
66
|
export type PlaceAdapter = (cell: PlacementInput, deps?: { dryRun?: boolean; now?: Date }) => Promise<{ version?: string } | null> | { version?: string } | null;
|
|
@@ -72,6 +75,8 @@ export interface TickDeps {
|
|
|
72
75
|
gridHosts?: readonly GridHost[];
|
|
73
76
|
seatTurn?: (seat: string, root: string, host?: string, options?: Pick<SeatDeps, 'enqueue'>) => Promise<{ status: string; queueId?: string; runId?: string; item?: { source: string; id: string } }>;
|
|
74
77
|
queueOutcome?: (queueId: string, root: string) => 'pending' | 'unknown' | 'retryable' | 'succeeded';
|
|
78
|
+
/** ANOMALY-CLUSTER — grouping state shared with the dispatcher relaunch gate; defaults to the process-wide instance. */
|
|
79
|
+
anomalyCluster?: AnomalyCluster;
|
|
75
80
|
/** Snapshot of running harness processes for launch-cap decisions; an unreadable snapshot blocks launches. */
|
|
76
81
|
launchProcesses?: () => { status: 'ok'; records: readonly TrafficProcess[] } | { status: 'incomplete' };
|
|
77
82
|
/** 발사 전 대기열 항목의 풀 힌트 갱신(주입 안 하면 harness-queue `setQueuedPoolHint`). */
|
|
@@ -90,6 +95,8 @@ export interface TickDeps {
|
|
|
90
95
|
/** Production still uses the restricted turn; tests can supply a deterministic turn. */
|
|
91
96
|
coordinatorAgentRun?: AgentReplyInput['runAgent'];
|
|
92
97
|
coordinatorAgentProvider?: LLMProvider;
|
|
98
|
+
/** Resident knowhow pack seam; the real intake reads 내부 문서 `KNOWHOW` every tick. */
|
|
99
|
+
coordinatorKnowhow?: KnowhowOptions | false;
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
/** ORCH-TA-HAND ledger — one row per handed `orch:<card>:<cell>` key so a cell is handed once across ticks and processes. */
|
|
@@ -450,6 +457,22 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
450
457
|
const root = deps.root ?? effectiveInstanceRoot();
|
|
451
458
|
const runId = deps.runId ?? graphRunId() ?? `${kstDay(now)}-${window}`;
|
|
452
459
|
const path = stateFile(root, runId);
|
|
460
|
+
const consensus = new ConsensusEngine({ stateDir: root });
|
|
461
|
+
const consensusAllows = (cell: Cell): boolean => {
|
|
462
|
+
if (cell.kind !== 'cross-branch-change' && !cell.consensusProposalId) return true;
|
|
463
|
+
const workKey = `orch:${cell.cardId}:${cell.id}`;
|
|
464
|
+
try {
|
|
465
|
+
if (cell.kind === 'cross-branch-change') {
|
|
466
|
+
const proposal = consensus.proposalForWork(workKey);
|
|
467
|
+
if (!proposal || (cell.consensusProposalId && cell.consensusProposalId !== proposal.id)) return false;
|
|
468
|
+
cell.consensusProposalId = proposal.id;
|
|
469
|
+
}
|
|
470
|
+
return !!cell.consensusProposalId && consensus.canExecute(cell.consensusProposalId);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
debug.log('loop.orchestrator', 'consensus-gate-failed', { id: cell.consensusProposalId, workKey, error: String(error) }, { level: 'warn' });
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
};
|
|
453
476
|
const orchestratorConfig = getUserConfig().loops?.orchestrator;
|
|
454
477
|
const configured = deps.mode ?? orchestratorConfig?.mode;
|
|
455
478
|
const mode: Mode = configured === 'off' || configured === 'live' ? configured : 'shadow';
|
|
@@ -498,7 +521,8 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
498
521
|
? runCoordinatorAgentInbox({ role, pack: loadAgentRolePack('coordinator'), path: inboxPath, root,
|
|
499
522
|
...(deps.coordinatorAgentRun ? { runAgent: deps.coordinatorAgentRun } : {}),
|
|
500
523
|
...(deps.coordinatorAgentProvider ? { provider: deps.coordinatorAgentProvider } : {}) })
|
|
501
|
-
: runCoordinatorInbox(undefined, 100, inboxPath
|
|
524
|
+
: runCoordinatorInbox(undefined, 100, inboxPath,
|
|
525
|
+
deps.coordinatorKnowhow === undefined ? {} : { knowhow: deps.coordinatorKnowhow });
|
|
502
526
|
}))();
|
|
503
527
|
if (inbox.replied || inbox.acknowledged) {
|
|
504
528
|
observe('exchange', 'coordinator-inbox-replied', inbox.replied);
|
|
@@ -525,9 +549,12 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
525
549
|
const cells = ruleOnly ? [{ id: card.id, title: card.title }] : split ? await split(card, { shadow: mode === 'shadow' }) : [{ id: card.id, title: card.title }];
|
|
526
550
|
for (const cell of cells) {
|
|
527
551
|
if (!cell.id?.trim() || !cell.title?.trim()) throw new Error('invalid split cell');
|
|
552
|
+
const workKey = `orch:${card.id}:${cell.id}`;
|
|
553
|
+
const proposalId = cell.consensusProposalId ?? (cell.kind === 'cross-branch-change' ? consensus.proposalForWork(workKey)?.id : undefined);
|
|
528
554
|
state.cells.push({ cardId: card.id, id: cell.id, title: cell.title, origin: split ? 'flow1a' : 'candidate',
|
|
529
555
|
...(ruleOnly ? { priority: rubricPriority(card.sections.map(section => section.content).join('\n')) } : {}),
|
|
530
|
-
...(cell.kind !== undefined ? { kind: cell.kind } : {}), ...(cell.seat ? { seat: cell.seat } : {}), ...(cell.host !== undefined ? { host: cell.host } : {})
|
|
556
|
+
...(cell.kind !== undefined ? { kind: cell.kind } : {}), ...(cell.seat ? { seat: cell.seat } : {}), ...(cell.host !== undefined ? { host: cell.host } : {}),
|
|
557
|
+
...(proposalId ? { consensusProposalId: proposalId } : {}) });
|
|
531
558
|
}
|
|
532
559
|
observe('exchange', `split:${card.id}`, cells.length);
|
|
533
560
|
if (split && cells.length && mode === 'live') {
|
|
@@ -563,6 +590,7 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
563
590
|
}
|
|
564
591
|
if (available && (mode === 'live' || !deps.placeCell)) for (const cell of state.cells) {
|
|
565
592
|
if (cell.origin !== 'flow1a' || !cell.seat || !SEAT_LOOP_IDS[cell.seat]) continue;
|
|
593
|
+
if (!consensusAllows(cell)) { observe('consensus-blocked', cell.consensusProposalId, 1); continue; }
|
|
566
594
|
// RELPLAN's dryRun calculates the same release without writing a checklist in shadow.
|
|
567
595
|
try {
|
|
568
596
|
const priority = cell.priority === 'P3' || cell.priority === 'P4' ? 'P2' : cell.priority ?? 'P2';
|
|
@@ -641,6 +669,7 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
641
669
|
};
|
|
642
670
|
for (const cell of state.cells) {
|
|
643
671
|
if (cell.origin !== 'flow1a' || !cell.seat) continue;
|
|
672
|
+
if (!consensusAllows(cell)) { observe('consensus-blocked', cell.consensusProposalId, 1); continue; }
|
|
644
673
|
const targetLoopId = SEAT_LOOP_IDS[cell.seat];
|
|
645
674
|
if (!targetLoopId) continue;
|
|
646
675
|
const key = `orch:${cell.cardId}:${cell.id}`;
|
|
@@ -670,6 +699,17 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
670
699
|
// shadow 표본은 따로 센다 — 자리 경로로 아직 안 간 칸(shadow 틱·배치 전)이 나중에 live 로 바뀌면 그때 뜬다.
|
|
671
700
|
// ⚠️ 이미 자리 저널에 들어간 칸은 live 로 바꿔도 다시 안 넘긴다(keys.has 에서 끝) — 한 칸의 발사 주체는 하나다(의도).
|
|
672
701
|
const handKey = handLive ? key : `shadow:${key}`;
|
|
702
|
+
// ANOMALY-CLUSTER: the goal·host pair is the hold key (never part of the failure signature). While a
|
|
703
|
+
// signature with 3+ runs is un-judged, its relaunch is held and the cell is carried to the next tick.
|
|
704
|
+
const anomalyGoal = cell.cardId;
|
|
705
|
+
const anomalyHost = cell.seat;
|
|
706
|
+
const anomaly = deps.anomalyCluster ?? defaultAnomalyCluster();
|
|
707
|
+
const hold = anomaly.hold(anomalyGoal, anomalyHost);
|
|
708
|
+
if (hold.hold) {
|
|
709
|
+
(state.deferredCells ??= []).push(cell);
|
|
710
|
+
observe('anomaly-cluster-hold', `${key}:${hold.reason}`, 1, 'task-agent');
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
673
713
|
mkdirSync(dirname(ledger), { recursive: true });
|
|
674
714
|
mkdirSync(dirname(path), { recursive: true });
|
|
675
715
|
// Claim under the seat-journal lock — the same lock the seat append takes, so a live claim and a seat row never both land.
|
|
@@ -689,9 +729,18 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
689
729
|
withFileLockSync(`${path}.lock`, () => appendFileSync(ledger, `${JSON.stringify({ key: handKey, cell: cell.id, cardId: result.card.id, mode: result.mode, launched: result.launched, status: 'handed', runId, at: now.toISOString() })}\n`));
|
|
690
730
|
(state.handed ??= []).push({ key, cell: cell.id, cardId: result.card.id, mode: result.mode, launched: result.launched });
|
|
691
731
|
observe('hand-to-task-agent', `${key}:${result.card.id}:${result.mode}${result.launched ? ':launched' : ''}`, 1, 'task-agent');
|
|
732
|
+
// A hand that went through is the cause verdict for this goal·host — clear a pending hold.
|
|
733
|
+
if (anomaly.isHeld(anomalyGoal, anomalyHost)) anomaly.release(anomalyGoal, anomalyHost, '원인 판정: hand-to-task-agent 성공');
|
|
692
734
|
// A live hand is an assignment: it counts toward maxDelegatePerTick like a seat row (COORD-HA ②).
|
|
693
735
|
if (handLive) { keys.add(key); state.delegatedKeys?.push(key); continue; }
|
|
694
736
|
} catch (error) {
|
|
737
|
+
// ANOMALY-CLUSTER record point: signature from kind·container exit·stage·reason tail of lastLines.
|
|
738
|
+
const failureLines = [String(error)];
|
|
739
|
+
anomaly.record({
|
|
740
|
+
goal: anomalyGoal, host: anomalyHost, runId,
|
|
741
|
+
kind: 'hand-to-task-agent-failed', containerExit: extractContainerExit(failureLines[0]!),
|
|
742
|
+
stage: 'delegate', lastLines: failureLines, at: now.toISOString(),
|
|
743
|
+
});
|
|
695
744
|
observe('hand-to-task-agent-failed', `${key}:${String(error).slice(0, 160)}`, 1, 'task-agent');
|
|
696
745
|
// A failed live hand stays claimed (no relaunch loop) and does not fall back to the seat path — one launcher per cell.
|
|
697
746
|
if (handLive) { keys.add(key); continue; }
|
|
@@ -750,7 +799,7 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
750
799
|
// shadow 는 저널을 읽지 않는다 — 깨진 live 저널이 관측 전용 틱을 넘어뜨리지 않게.
|
|
751
800
|
const latestRequests = new Map(mode === 'live' && state.degradation?.level !== 2 ? readRequests(root).map(row => [row.key, row]) : []);
|
|
752
801
|
const eligible = state.cells.filter(cell => state.degradation?.level !== 2 && cell.origin === 'flow1a' && cell.seat && SEAT_LOOP_IDS[cell.seat]
|
|
753
|
-
&& validVersion(cell.version) && (mode === 'shadow' || latestRequests.get(`orch:${cell.cardId}:${cell.id}`)?.status === 'queued')
|
|
802
|
+
&& consensusAllows(cell) && validVersion(cell.version) && (mode === 'shadow' || latestRequests.get(`orch:${cell.cardId}:${cell.id}`)?.status === 'queued')
|
|
754
803
|
&& (orchestratorConfig?.maxDelegatePerTick === undefined || state.delegatedKeys?.includes(`orch:${cell.cardId}:${cell.id}`)
|
|
755
804
|
|| (mode === 'live' && latestRequests.has(`orch:${cell.cardId}:${cell.id}`))));
|
|
756
805
|
const seats = [...new Set(eligible.map(cell => cell.seat!))];
|