elanous 0.2.36 → 0.2.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 1262.a89bb27a5b2f844e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 1746.3563617ea64023a3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 2002-a43a3f380df873ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 2283.edd9627b7bdfb546.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 2375.bf364c85dbb6f085.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +27 -0
- package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 3199.6a1a9b0e6cd01dc6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2986.45d7652e4f13557e.js → 3578.4e9f9948a9a6f2f4.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +226 -0
- package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +287 -0
- package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7481.39f7a4654907bf6e.js → 4313.76f232c304a15bde.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4337e36d.f42c3b391b3d8f20.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 4383.18e5c54db3a22c88.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3757-180308bc61021b05.js → 4725-34bed25720cc326b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 4931.95cc6dbd230774ca.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5046.7fd5cbd859299448.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +104 -0
- package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +1 -0
- package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 58edce7d.f1b0c72acf13b123.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 5952.294fc574a8625184.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 5f6af561-f90b7a67f4f75d13.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +74 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 6252.240578f10952e091.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 6680.6a693c28aae4cd19.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 6745-5a63492933959dd9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 6819.be5c9c4d67f22922.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → 709a918c.4fd3b4e2a32cb4e3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 7424.c0fe2a595d4232b5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +1 -0
- package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 7867.e8725745ddd1d940.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{6466-92e65a48490b68a9.js → 7893-e444a1b0809cd1e4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{ccae1c4b-0cf414f5eff1b10d.js → 7c5ed21f-f286708e57cf88f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{3840-5825d56d46976a92.js → 8080-40d781e7704d3671.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +77 -0
- package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +1 -0
- package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +286 -0
- package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +79 -0
- package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → 8c58d09b.e8724a299658d86f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 9151.a2c51e93f9156dae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +94 -0
- package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{190.285c832bd9626f8c.js → 958.53a8dcf4729e6997.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-e2de2e59111c9aad.js → page-3337c6a1328c2674.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-f2b2e4bf6e981450.js → page-89acd5d68c0bc560.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2af16e62c12f22df.js → page-fe986fe79b107546.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → d9815f84.4918f682a45a8502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → de8446d3.31b73eb239fecd7b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +1 -0
- package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/drafts/recipes.yaml +27 -7
- package/graphs/work/draft-close.yaml +54 -0
- package/graphs/work/green-close.yaml +37 -0
- package/graphs/work/recipes.yaml +46 -1
- package/graphs/work/run-research.yaml +35 -0
- package/package.json +1 -1
- package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
- package/scripts/boundary-proof-mapping-audit.ts +88 -0
- package/scripts/codex-fallback-live-probe.ts +17 -15
- package/scripts/fleet/node-setup.sh +32 -2
- package/scripts/fleet/run-light-worker.sh +9 -0
- package/scripts/gate-0226-failure-census.ts +507 -0
- package/scripts/goals/authoring-metrics.ts +258 -0
- package/scripts/graph-units/draft-close-node.ts +222 -0
- package/scripts/hook-order-sweep.ts +7 -4
- package/scripts/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- package/scripts/release-loop/docs-node.ts +140 -0
- package/scripts/release-loop/gate-closure.ts +48 -0
- package/scripts/release-loop/gate-diff.ts +2 -1
- package/scripts/release-loop/known-issues-node.ts +6 -4
- package/scripts/release-loop/notes-repair.ts +216 -0
- package/scripts/release-loop/prepare-node.ts +61 -5
- package/scripts/release-loop/resume-release.ts +114 -4
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/version-node.ts +81 -12
- package/scripts/train/green-leg.ts +176 -0
- package/scripts/tui-continue-real-evidence.ts +47 -0
- package/scripts/ux-sim.ts +1 -1
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +6 -0
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/self-review-cli.ts +343 -31
- package/src/autopilot/lineage/sources.ts +1 -1
- package/src/autopilot/pr-manager.ts +64 -13
- package/src/boot/daemon-runtime.ts +35 -3
- package/src/boot/daemon-tools/pty-shell.ts +2 -1
- package/src/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/capture/tui-self-report.ts +32 -3
- package/src/cli/autopilot-cli.ts +24 -9
- package/src/cli/decisions-cli.ts +7 -4
- package/src/cli/doctor-cli.ts +116 -7
- package/src/cli/logs-cli.ts +357 -2
- package/src/cli/memory-cli.ts +30 -1
- package/src/cli/msg-cli.ts +15 -11
- package/src/cli/pr-granularity.ts +5 -3
- package/src/cli/release-checklist-read-cli.ts +109 -4
- package/src/cli/release-cli.ts +43 -10
- package/src/cli/self-update.ts +23 -5
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-cli.ts +309 -11
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +97 -13
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/display/coordinator.ts +45 -12
- package/src/display/resize-listener.ts +41 -20
- package/src/display/synchronized-output-region.ts +60 -0
- package/src/domains/surface-events.ts +80 -1
- package/src/exec-requests/planner.ts +37 -2
- package/src/execution-loop/launch-gate.ts +4 -3
- package/src/git-fs/cli-stderr.ts +45 -0
- package/src/git-fs/gh-cli.ts +6 -3
- package/src/git-fs/git-cli.ts +11 -5
- package/src/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +17 -5
- package/src/graph-wizard/generate.ts +29 -6
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/index.ts +116 -13
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +35 -0
- package/src/llm.ts +123 -11
- package/src/loops/checker.ts +100 -0
- package/src/loops/consensus.ts +26 -2
- package/src/loops/loop-cli.ts +9 -4
- package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
- package/src/loops/orchestrator/tick.ts +49 -4
- package/src/model-tier/llm-tier-map.ts +12 -17
- package/src/msg/msg-store.ts +17 -0
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/graph-wizard-api.ts +27 -2
- package/src/nexus/api/grid.ts +24 -4
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +14 -6
- package/src/nexus/state/state.ts +7 -1
- package/src/oauth/codex-account-store.ts +34 -1
- package/src/ops/loops-map.ts +46 -0
- package/src/ops/overview-cache.ts +22 -4
- package/src/ops/overview.ts +41 -5
- package/src/policy/llm-policy.ts +3 -1
- package/src/prompt-enhance/enhance.ts +4 -4
- package/src/pty-shell/availability.ts +7 -0
- package/src/pty-shell/herdr-agent-report.ts +40 -31
- package/src/pty-shell/herdr-prune-stale.ts +17 -0
- package/src/pty-shell/herdr-sequence-lease.ts +60 -0
- package/src/pty-shell/pty-control-ipc.ts +187 -18
- package/src/pty-shell/registry.ts +25 -15
- package/src/pty-shell/tui-run-state.ts +235 -1
- package/src/release-loop/checklist.ts +50 -5
- package/src/release-loop/feature-store.ts +9 -9
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/repl/index.ts +8 -0
- package/src/seat-loop/seat-report.ts +1 -0
- package/src/self-dev/ask-launch-flow.ts +86 -10
- package/src/self-dev/decompose-proposal.ts +29 -18
- package/src/self-dev/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-sweep.ts +241 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +50 -3
- package/src/self-implement/doctor-visit.ts +83 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +64 -1
- package/src/self-implement/gate-cli.ts +93 -9
- package/src/self-implement/gate-remote.ts +28 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +333 -18
- package/src/self-implement/goal-supervisor-fill.ts +75 -26
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +5 -5
- package/src/self-implement/orchestrator.ts +318 -25
- package/src/self-implement/review-round-brief.ts +300 -0
- package/src/self-implement/rework-policy.ts +14 -0
- package/src/self-implement/run-ledger.ts +170 -6
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/running-runs.ts +17 -3
- package/src/self-implement/seams.ts +12 -6
- package/src/self-implement/stop-autoheal.ts +1 -0
- package/src/self-implement/test-seams.ts +13 -1
- package/src/self-implement/train-reach-grouping.ts +8 -2
- package/src/session/chat.ts +7 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +4 -0
- package/src/session-runtime/index.ts +9 -1
- package/src/skills/tools/pty.ts +5 -0
- package/src/status/metrics.ts +12 -1
- package/src/steward/rejudge-tick.ts +12 -5
- package/src/steward/resync-tick.ts +31 -4
- package/src/task-agent/actions.ts +199 -4
- package/src/task-agent/boundary-proof-mapping.ts +12 -0
- package/src/task-agent/boundary-proof-producer.ts +147 -0
- package/src/task-agent/completion-evidence.ts +2 -1
- package/src/task-agent/green-close-recipe.ts +239 -0
- package/src/task-agent/green-sweep.ts +64 -10
- package/src/task-agent/live-moves.ts +48 -3
- package/src/task-agent/map-host-adapter.ts +134 -0
- package/src/task-agent/map-reduce.ts +158 -0
- package/src/task-agent/map-run-ledger.ts +226 -0
- package/src/task-agent/parent-host.ts +21 -11
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +41 -0
- package/src/task-agent/repair-next-move.ts +12 -2
- package/src/task-agent/review-prior-fix.ts +12 -2
- package/src/task-agent/shadow.ts +188 -5
- package/src/task-agent/task-hand.ts +158 -13
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +4 -3
- package/src/task-agent/work-order.ts +53 -2
- package/src/task-orchestrator/dispatcher.ts +46 -1
- package/src/task-orchestrator/generator-prompt.ts +6 -0
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +50 -4
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +217 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +4 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +258 -4
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/slash/resume.ts +35 -12
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +71 -0
- package/src/tui-client/local-chat-turn.ts +4 -3
- package/src/user-config.ts +19 -1
- package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
- package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
- package/src/ux-sim/fake-gh.ts +174 -0
- package/src/ux-sim/fake-kubectl.ts +142 -0
- package/src/ux-sim/fake-llm.ts +6 -1
- package/src/ux-sim/next-tui-seat-scenarios.ts +124 -6
- package/src/ux-sim/resume-picker-device.ts +173 -0
- package/src/ux-sim/session-id-seed.ts +60 -0
- package/src/ux-sim/skills-tools-shell-device.ts +156 -0
- package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
- package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
- package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
- package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2812ca6a.3b9f4a7a08885744.js +0 -1
- package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3148-98efd4869d660a87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
- package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
- package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
- package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
- package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
- package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/599.c39c571b6733f2a2.js +0 -41
- package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
- package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6925.562d532110879886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
- package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
- /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
|
@@ -9,11 +9,10 @@
|
|
|
9
9
|
// 마지막 턴 상태를 잠시 뒤 다시 신고하고(새 seq · 더 새 턴이 오면 그만) 이후 턴 신고도 그대로 보낸다.
|
|
10
10
|
//
|
|
11
11
|
// herdr 는 같은 pane·source 에서 «직전보다 큰 seq» 만 받는다(작으면 rc0 인데 무시).
|
|
12
|
-
// 같은 pane 에서 TUI 를 다시 띄워도 신고가 살도록 seq 는 max(직전+1 · 시각 ·
|
|
13
|
-
// pane 기록 =
|
|
14
|
-
// ⛔ 턴 경로는 파일을 안 만진다:
|
|
12
|
+
// 같은 pane 에서 TUI 를 다시 띄워도 신고가 살도록 seq 는 max(직전+1 · 시각 · 예약 high-watermark+1) 이다.
|
|
13
|
+
// pane 기록 = 예약한 seq 범위의 high-watermark(기본 tmpdir 파일) — 정상·비정상 재기동에서 뒤 범위를 쓴다.
|
|
14
|
+
// ⛔ 턴 경로는 보통 파일을 안 만진다: 범위가 소진되면 next()가 새 범위를 파일에 예약한다.
|
|
15
15
|
// 기록을 못 읽고 못 쓰면(관측 `seq-store-failed` 한 번) 시각·직전+1 로만 간다.
|
|
16
|
-
// 한계: release 없이 죽은 프로세스의 마지막 seq 는 기록되지 않는다 — 그때 뒤 프로세스는 시각에 기댄다.
|
|
17
16
|
//
|
|
18
17
|
// 실패로 꺼지는 것은 «이후 turn» 뿐이다. release(권한 반납)는 start 실패가 «확인»됐을 때만 건너뛴다.
|
|
19
18
|
// start 의 비동기 신고가 아직 안 끝났으면(결과 모름) 반납을 미루지 않고 바로 동기로 시도한다(관측 `release-start-pending`) —
|
|
@@ -27,6 +26,9 @@ import { tmpdir } from 'node:os';
|
|
|
27
26
|
import { join } from 'node:path';
|
|
28
27
|
|
|
29
28
|
import { debug } from '../debug/log.js';
|
|
29
|
+
import { pruneStaleHerdrAgent } from './herdr-prune-stale.js';
|
|
30
|
+
import { HerdrSequenceLease, type HerdrSeqStore } from './herdr-sequence-lease.js';
|
|
31
|
+
export type { HerdrSeqStore } from './herdr-sequence-lease.js';
|
|
30
32
|
|
|
31
33
|
/** 턴 값 — tui-run-state 의 PtyTurnState 와 같은 낱말이지만 순환 import 를 피하려 여기 둔다. */
|
|
32
34
|
export type HerdrTurn = 'busy' | 'idle';
|
|
@@ -55,10 +57,12 @@ export interface HerdrAgentReporterDeps {
|
|
|
55
57
|
readonly sessionId?: string;
|
|
56
58
|
/** seq 시작값의 시계(ms). 기본 Date.now. */
|
|
57
59
|
readonly now?: () => number;
|
|
58
|
-
/** pane 별
|
|
60
|
+
/** pane 별 예약 범위 끝 기록. 기본 = tmpdir 파일(`createFileSeqStore`). */
|
|
59
61
|
readonly seqStore?: HerdrSeqStore;
|
|
60
62
|
/** 재신고 타이머 — 기본 setTimeout(unref). 시험이 가짜 시계를 준다. */
|
|
61
63
|
readonly schedule?: (fn: () => void, ms: number) => void;
|
|
64
|
+
/** Injected runners skip production startup cleanup unless explicitly enabled. */
|
|
65
|
+
readonly pruneStaleOnStart?: boolean;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
const defaultSchedule = (fn: () => void, ms: number): void => {
|
|
@@ -66,12 +70,6 @@ const defaultSchedule = (fn: () => void, ms: number): void => {
|
|
|
66
70
|
(t as unknown as { unref?: () => void }).unref?.();
|
|
67
71
|
};
|
|
68
72
|
|
|
69
|
-
/** 같은 pane 에서 마지막으로 낸 seq — 프로세스 사이 단조를 잇는다. 실패는 던져도 된다(신고기가 삼킨다). */
|
|
70
|
-
export interface HerdrSeqStore {
|
|
71
|
-
read(): number | undefined;
|
|
72
|
-
write(seq: number): void;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
73
|
export function defaultHerdrSeqDir(): string {
|
|
76
74
|
return join(tmpdir(), 'elanous-herdr-seq');
|
|
77
75
|
}
|
|
@@ -277,13 +275,17 @@ export function createHerdrAgentReporter(deps: HerdrAgentReporterDeps = {}): Her
|
|
|
277
275
|
}
|
|
278
276
|
const run = deps.run ?? defaultHerdrRunner(env);
|
|
279
277
|
const sessionId = deps.sessionId ?? '';
|
|
280
|
-
return new Reporter(
|
|
278
|
+
return new Reporter(
|
|
279
|
+
paneId, sessionId, run, log, deps.now ?? Date.now,
|
|
280
|
+
deps.seqStore ?? createFileSeqStore(paneId), deps.schedule ?? defaultSchedule,
|
|
281
|
+
deps.pruneStaleOnStart ?? deps.run === undefined,
|
|
282
|
+
);
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
type IssueResult = boolean | Promise<boolean>;
|
|
284
286
|
|
|
285
287
|
class Reporter implements HerdrAgentReporterLike {
|
|
286
|
-
private
|
|
288
|
+
private readonly sequence: HerdrSequenceLease;
|
|
287
289
|
private disabled = false;
|
|
288
290
|
/**
|
|
289
291
|
* idle 신고(에이전트 등록)의 상태: none → (pending →) ok | failed.
|
|
@@ -291,8 +293,6 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
291
293
|
*/
|
|
292
294
|
private startState: 'none' | 'pending' | 'ok' | 'failed' = 'none';
|
|
293
295
|
private released = false;
|
|
294
|
-
/** start 때 한 번 읽은 pane 기록(턴 경로는 파일을 안 만진다). */
|
|
295
|
-
private storedSeq: number | undefined;
|
|
296
296
|
/** idle 신고(비동기 포함)가 실패했다 — 등록된 적이 없으니 반납할 것이 없다. */
|
|
297
297
|
private idleFailed = false;
|
|
298
298
|
private seqStoreFailed = false;
|
|
@@ -313,9 +313,12 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
313
313
|
private readonly run: HerdrRunner,
|
|
314
314
|
private readonly log: (event: string, data: Record<string, unknown>) => void,
|
|
315
315
|
private readonly now: () => number,
|
|
316
|
-
|
|
316
|
+
seqStore: HerdrSeqStore,
|
|
317
317
|
private readonly schedule: (fn: () => void, ms: number) => void,
|
|
318
|
-
|
|
318
|
+
private readonly pruneStaleOnStart: boolean,
|
|
319
|
+
) {
|
|
320
|
+
this.sequence = new HerdrSequenceLease(seqStore, now, (error) => this.seqStoreFail(error));
|
|
321
|
+
}
|
|
319
322
|
|
|
320
323
|
/** 마지막으로 요청된 턴 상태와 그 세대 — 재신고는 세대가 그대로일 때만(더 새 턴이 오면 그만). */
|
|
321
324
|
private lastTurn: HerdrTurn | null = null;
|
|
@@ -324,7 +327,17 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
324
327
|
|
|
325
328
|
start(): void {
|
|
326
329
|
if (this.startState !== 'none') return;
|
|
327
|
-
|
|
330
|
+
if (this.pruneStaleOnStart) {
|
|
331
|
+
const pruneSeq = this.nextSeq();
|
|
332
|
+
try {
|
|
333
|
+
const pruned = pruneStaleHerdrAgent(this.paneId, pruneSeq, this.run);
|
|
334
|
+
this.log(pruned.ok ? 'startup-prune-complete' : 'startup-prune-failed', {
|
|
335
|
+
seq: pruneSeq, ...(pruned.stderr ? { stderrHead: stderrHead(pruned.stderr) } : {}),
|
|
336
|
+
});
|
|
337
|
+
} catch (error) {
|
|
338
|
+
this.log('startup-prune-failed', { seq: pruneSeq, stderrHead: stderrHead(error instanceof Error ? error.message : String(error)) });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
328
341
|
const idleOk = this.issue([
|
|
329
342
|
'pane', 'report-agent',
|
|
330
343
|
'--source', HERDR_SOURCE, '--agent', HERDR_AGENT,
|
|
@@ -365,8 +378,6 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
365
378
|
this.releasedWhilePending = false;
|
|
366
379
|
this.log('release-resend-after-late-start', {});
|
|
367
380
|
const seq = this.nextSeq();
|
|
368
|
-
// 재반납 seq 도 pane 기록에 남긴다 — 같은 ms 재기동의 첫 seq 가 이 값보다 커야 한다(r7 리뷰 mf).
|
|
369
|
-
try { this.seqStore.write(this.seq); } catch (error) { this.seqStoreFail(error); }
|
|
370
381
|
void this.runAndJudge([
|
|
371
382
|
'pane', 'release-agent',
|
|
372
383
|
this.paneId,
|
|
@@ -418,8 +429,6 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
418
429
|
], true, 'release');
|
|
419
430
|
}
|
|
420
431
|
const seq = this.nextSeq();
|
|
421
|
-
// pane 기록 쓰기는 여기(동기 종료 경로)뿐이다.
|
|
422
|
-
try { this.seqStore.write(this.seq); } catch (error) { this.seqStoreFail(error); }
|
|
423
432
|
// ⛔ herdr 0.9.1 `release-agent` 는 PANE_ID 를 옵션 «앞»에 둬야 받는다 — 뒤에 두면
|
|
424
433
|
// «unknown option: custom:elanous» rc2 로 반납이 영영 안 됐다(10-18 라이브 실측 · report-agent 는 뒤도 받음).
|
|
425
434
|
this.issue([
|
|
@@ -457,20 +466,16 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
457
466
|
this.log('seq-store-failed', { error: error instanceof Error ? error.message : String(error) });
|
|
458
467
|
}
|
|
459
468
|
|
|
460
|
-
/**
|
|
469
|
+
/** Reserved sequence lease advances monotonically across same-millisecond restarts. */
|
|
461
470
|
private nextSeq(): string {
|
|
462
|
-
|
|
463
|
-
let next = Number.isFinite(clock) ? Math.max(this.seq + 1, clock) : this.seq + 1;
|
|
464
|
-
if (this.storedSeq !== undefined) next = Math.max(next, this.storedSeq + 1);
|
|
465
|
-
this.seq = next;
|
|
466
|
-
return String(this.seq);
|
|
471
|
+
return String(this.sequence.next());
|
|
467
472
|
}
|
|
468
473
|
|
|
469
474
|
/**
|
|
470
475
|
* release 는 꺼진 뒤에도 보낸다(권한 반납 · start 성공 조건은 release() 가 본다).
|
|
471
476
|
* @returns false = 동기 실패(신고기 꺼짐) · true = 동기 성공 · Promise = 비동기 결과(성공이면 true).
|
|
472
477
|
*/
|
|
473
|
-
private issue(argv: string[], sync: boolean, phase: 'start' | 'session' | 'turn' | 'release'): IssueResult {
|
|
478
|
+
private issue(argv: string[], sync: boolean, phase: 'start' | 'session' | 'turn' | 'release' | 'stale-cleanup'): IssueResult {
|
|
474
479
|
if (this.disabled && phase !== 'release') return false;
|
|
475
480
|
const opts: HerdrRunOpts = { sync, timeoutMs: sync ? SYNC_TIMEOUT_MS : ASYNC_TIMEOUT_MS };
|
|
476
481
|
if (!sync && this.pending) {
|
|
@@ -520,7 +525,7 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
520
525
|
}
|
|
521
526
|
|
|
522
527
|
/** 줄 선 비동기 한 건 — 러너 결과(동기·비동기 모두)를 성패로 접는다. */
|
|
523
|
-
private async runAndJudge(argv: string[], opts: HerdrRunOpts, phase: 'start' | 'session' | 'turn' | 'release'): Promise<boolean> {
|
|
528
|
+
private async runAndJudge(argv: string[], opts: HerdrRunOpts, phase: 'start' | 'session' | 'turn' | 'release' | 'stale-cleanup'): Promise<boolean> {
|
|
524
529
|
try {
|
|
525
530
|
const r = await this.run(argv, opts);
|
|
526
531
|
if (r.ok) return true;
|
|
@@ -532,7 +537,7 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
532
537
|
}
|
|
533
538
|
}
|
|
534
539
|
|
|
535
|
-
private fail(argv: string[], phase: 'start' | 'session' | 'turn' | 'release', stderr: string | undefined, timedOut = false): void {
|
|
540
|
+
private fail(argv: string[], phase: 'start' | 'session' | 'turn' | 'release' | 'stale-cleanup', stderr: string | undefined, timedOut = false): void {
|
|
536
541
|
if (phase === 'turn' && timedOut && !this.disabled) {
|
|
537
542
|
this.retryTurnAfterTimeout(argv, stderr);
|
|
538
543
|
return;
|
|
@@ -543,6 +548,10 @@ class Reporter implements HerdrAgentReporterLike {
|
|
|
543
548
|
this.log('release-failed', { stderrHead: stderrHead(stderr) });
|
|
544
549
|
return;
|
|
545
550
|
}
|
|
551
|
+
if (phase === 'stale-cleanup') {
|
|
552
|
+
this.log('stale-agent-cleanup-failed', { stderrHead: stderrHead(stderr) });
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
546
555
|
if (this.disabled) return;
|
|
547
556
|
this.disabled = true;
|
|
548
557
|
const cmd = argv[1] ?? '';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HerdrRunResult, HerdrRunner } from './herdr-agent-report.js';
|
|
2
|
+
|
|
3
|
+
const PRUNE_TIMEOUT_MS = 300;
|
|
4
|
+
|
|
5
|
+
/** Best-effort removal of a prior custom agent left behind in this pane. */
|
|
6
|
+
export function pruneStaleHerdrAgent(
|
|
7
|
+
paneId: string,
|
|
8
|
+
seq: string,
|
|
9
|
+
run: HerdrRunner,
|
|
10
|
+
): HerdrRunResult {
|
|
11
|
+
const result = run([
|
|
12
|
+
'pane', 'release-agent', paneId,
|
|
13
|
+
'--source', 'custom:elanous', '--agent', 'elanous', '--seq', seq,
|
|
14
|
+
], { sync: true, timeoutMs: PRUNE_TIMEOUT_MS });
|
|
15
|
+
if (result instanceof Promise) throw new Error('startup prune requires a synchronous herdr runner');
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface HerdrSeqStore {
|
|
2
|
+
read(): number | undefined;
|
|
3
|
+
write(seq: number): void;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const DEFAULT_SEQ_WINDOW = 65_536;
|
|
7
|
+
|
|
8
|
+
/** Reserve future sequence values before reporting so a SIGKILL restart can advance past the dead process. */
|
|
9
|
+
export class HerdrSequenceLease {
|
|
10
|
+
private seq = 0;
|
|
11
|
+
private end = 0;
|
|
12
|
+
private stored: number | undefined;
|
|
13
|
+
private ready = false;
|
|
14
|
+
private failed = false;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly store: HerdrSeqStore,
|
|
18
|
+
private readonly now: () => number,
|
|
19
|
+
private readonly onFailure: (error: unknown) => void,
|
|
20
|
+
private readonly seqWindow = DEFAULT_SEQ_WINDOW,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
next(): number {
|
|
24
|
+
this.initialize();
|
|
25
|
+
const clock = Math.floor(this.now());
|
|
26
|
+
let next = Number.isFinite(clock) ? Math.max(this.seq + 1, clock) : this.seq + 1;
|
|
27
|
+
if (this.stored !== undefined) next = Math.max(next, this.stored + 1);
|
|
28
|
+
if (next > this.end) this.reserve(next);
|
|
29
|
+
this.seq = next;
|
|
30
|
+
return next;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private initialize(): void {
|
|
34
|
+
if (this.ready) return;
|
|
35
|
+
try {
|
|
36
|
+
const stored = this.store.read();
|
|
37
|
+
this.stored = typeof stored === 'number' && Number.isSafeInteger(stored) && stored >= 0 ? stored : undefined;
|
|
38
|
+
} catch (error) { this.fail(error); }
|
|
39
|
+
const clock = Math.floor(this.now());
|
|
40
|
+
this.seq = Number.isFinite(clock) ? Math.max(clock + this.seqWindow, this.stored ?? 0) : (this.stored ?? 0);
|
|
41
|
+
this.reserve(this.seq);
|
|
42
|
+
this.ready = true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private reserve(from: number): void {
|
|
46
|
+
const end = from + this.seqWindow;
|
|
47
|
+
try { this.store.write(end); } catch (error) { this.fail(error); }
|
|
48
|
+
this.end = end;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private fail(error: unknown): void {
|
|
52
|
+
if (this.failed) return;
|
|
53
|
+
this.failed = true;
|
|
54
|
+
this.onFailure(error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function staleHerdrReleaseArgs(paneId: string, source: string, agent: string, seq: number): string[] {
|
|
59
|
+
return ['pane', 'release-agent', paneId, '--source', source, '--agent', agent, '--seq', String(seq)];
|
|
60
|
+
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite';
|
|
2
2
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
|
-
import { ptyManifestDbPath, getPtyManifest, markPtyControlled } from './pty-manifest.js';
|
|
4
|
+
import { ptyManifestDbPath, getPtyManifest, markPtyControlled, listPtyManifestRows, listPtyManifestRowsAt } from './pty-manifest.js';
|
|
5
5
|
import { getHarnessRunId } from '../harness/harness-space.js';
|
|
6
6
|
import { renamePty, type PtyControlTarget } from './registry.js';
|
|
7
7
|
import { resizePtyWithOutcome, writePtyWithOutcome, writePtyWithOutcomeDetail } from './pty-write-outcome.js';
|
|
8
8
|
import { resetExternalWriteProvenanceForTesting } from './pty-write-provenance.js';
|
|
9
9
|
import { parsePtyWriteActor, resolveRemoteControlActor, type PtyWriteActor } from './pty-write-arbiter.js';
|
|
10
|
-
import { isPtyAccessMode } from './pty-ref.js';
|
|
10
|
+
import { isPtyAccessMode, resolvePtyRef, type PtyRefReason } from './pty-ref.js';
|
|
11
|
+
import { RemotesStore } from '../cli/remotes.js';
|
|
12
|
+
import { bookmarkToElanousRemote } from '../cli/remote-resolve.js';
|
|
11
13
|
import { debug } from '../debug/log.js';
|
|
12
14
|
import { encodeSgrMouse, mouseModeOffReason, type PtyMouseInput } from './pty-mouse.js';
|
|
13
15
|
import { startPtyRecording, stopPtyRecording } from './pty-recording.js';
|
|
@@ -53,6 +55,12 @@ export interface PtyControlRequestOptions {
|
|
|
53
55
|
readonly now?: () => number;
|
|
54
56
|
/** 요청자 poll 루프의 대기(기본 `Bun.sleep`) — 기본값에서 25ms cadence 계약은 그대로다. */
|
|
55
57
|
readonly sleep?: (ms: number) => Promise<void>;
|
|
58
|
+
/** 사람 타이핑 세션 — 있으면 재해석·재캡처 없이 이 «고정값»만 쓴다(`beginPtyHumanTypingSession`). */
|
|
59
|
+
readonly typingSession?: PtyHumanTypingSession;
|
|
60
|
+
/** 아직 세션이 없을 때 캡처할 북마크 이름(없으면 remotes.json 의 default · 그것도 없으면 로컬). */
|
|
61
|
+
readonly bookmarkName?: string;
|
|
62
|
+
/** 호출자가 이미 캡처해 둔 북마크 핀 — 재조회하지 않는다. */
|
|
63
|
+
readonly typingBookmark?: PtyTypingBookmarkPin;
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
export interface PtyControlResult {
|
|
@@ -185,6 +193,27 @@ const PTY_CONTROL_DEEP_IDLE_AFTER_MS = 10 * 60_000;
|
|
|
185
193
|
/** 깊은 유휴에서의 재읽기 간격. 요청 wake 는 이 간격을 «기다리지 않는다». */
|
|
186
194
|
const PTY_CONTROL_DEEP_IDLE_POLL_MS = 1_500;
|
|
187
195
|
|
|
196
|
+
/** 감속 계단의 두 값과 «계측» 훅 — 생산 기본값은 위 상수 ⊕ env override 다. */
|
|
197
|
+
interface ControlCadenceLimits {
|
|
198
|
+
readonly deepIdleAfterMs: number;
|
|
199
|
+
readonly deepIdlePollMs: number;
|
|
200
|
+
/** 큐를 실제로 다시 읽을 때마다 1회 — 감속 계측용(생산 진입점은 넘기지 않는다). */
|
|
201
|
+
readonly onQueueRead?: () => void;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** 생산 폴러는 옵션 없이 호출되므로 env override 뒤 상수 기본값만 사용한다. */
|
|
205
|
+
function resolveCadenceMs(envName: string, fallback: number): number {
|
|
206
|
+
return positiveInteger(Number(process.env[envName])) ?? fallback;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function cadenceLimits(options: PtyControlProcessOptions): ControlCadenceLimits {
|
|
210
|
+
return {
|
|
211
|
+
deepIdleAfterMs: resolveCadenceMs('ELANOUS_PTY_CONTROL_DEEP_IDLE_AFTER_MS', PTY_CONTROL_DEEP_IDLE_AFTER_MS),
|
|
212
|
+
deepIdlePollMs: resolveCadenceMs('ELANOUS_PTY_CONTROL_DEEP_IDLE_POLL_MS', PTY_CONTROL_DEEP_IDLE_POLL_MS),
|
|
213
|
+
...(options.onQueueRead ? { onQueueRead: options.onQueueRead } : {}),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
188
217
|
/** 깨어움 표식은 큐와 같은 원장 디렉터리에 둔다 — 요청자와 owner 가 같은 원장(`ptyManifestDbPath`)을
|
|
189
218
|
* 볼 때 owner 의 tick 이 곧바로 그 자리를 본다. 연합 큐(`manifestDbPath`)로 남의 원장에 요청하면
|
|
190
219
|
* 표식은 그 원장 자리에 남고 그 owner 는 감속 간격만큼만 늦다(요청 timeout 안쪽 · fail-soft).
|
|
@@ -236,7 +265,7 @@ function observeControlCadence(state: ControlCadenceState, mode: 'active' | 'dee
|
|
|
236
265
|
* ⛔ 첫 tick 은 언제나 읽는다(기동 직후 도착한 요청을 감속 뒤에 두지 않는다).
|
|
237
266
|
* ⛔ 감속 시계는 `pollClock`(기본 `Date.now`) 뿐이다 — `now`(takeover TTL 시계)를 섞으면 시험이
|
|
238
267
|
* 주입한 값이 실제 tick 을 감속시키는 회귀가 난다. */
|
|
239
|
-
function shouldReadControlQueue(dbPath: string, nowMs: number): boolean {
|
|
268
|
+
function shouldReadControlQueue(dbPath: string, nowMs: number, limits: ControlCadenceLimits): boolean {
|
|
240
269
|
const state = cadenceState(dbPath);
|
|
241
270
|
// 시계가 뒤로 갔다 = 이전 관측과 다른 시계다. 그 앵커로는 유휴를 못 재므로 버리고 다시 센다.
|
|
242
271
|
if (state.lastSeenAt !== null && nowMs < state.lastSeenAt) {
|
|
@@ -248,14 +277,15 @@ function shouldReadControlQueue(dbPath: string, nowMs: number): boolean {
|
|
|
248
277
|
const woke = consumePtyControlWake(dbPath);
|
|
249
278
|
if (state.lastControlAt === null || woke) state.lastControlAt = nowMs;
|
|
250
279
|
const idleMs = nowMs - state.lastControlAt;
|
|
251
|
-
const deepIdle = idleMs >=
|
|
280
|
+
const deepIdle = idleMs >= limits.deepIdleAfterMs;
|
|
252
281
|
const sinceReadMs = state.lastDbReadAt === null ? Number.POSITIVE_INFINITY : nowMs - state.lastDbReadAt;
|
|
253
|
-
if (!woke && deepIdle && sinceReadMs <
|
|
282
|
+
if (!woke && deepIdle && sinceReadMs < limits.deepIdlePollMs) {
|
|
254
283
|
observeControlCadence(state, 'deep-idle', idleMs);
|
|
255
284
|
return false;
|
|
256
285
|
}
|
|
257
286
|
state.lastDbReadAt = nowMs;
|
|
258
287
|
observeControlCadence(state, deepIdle ? 'deep-idle' : 'active', idleMs);
|
|
288
|
+
limits.onQueueRead?.();
|
|
259
289
|
return true;
|
|
260
290
|
}
|
|
261
291
|
|
|
@@ -271,6 +301,124 @@ export async function requestRemotePtyControlCapabilities(id: string, options: P
|
|
|
271
301
|
return { status: 'owner-result', result };
|
|
272
302
|
}
|
|
273
303
|
|
|
304
|
+
// ── PTY-HUMAN-TYPING-REMOTE (0.2.36 · UX 칸) — 사람 타이핑의 ref 해석·bookmark 캡처는 «한 번» ──
|
|
305
|
+
//
|
|
306
|
+
// `--remote --human` 타이핑은 호출자가 준 ref(alias·nickname)를 그대로 원장에 흘리면 안 된다:
|
|
307
|
+
// 타이핑 도중 nickname 이 바뀌면 같은 입력이 다른 PTY 로 풀리고, 북마크(host·token·url)가 갈라지면
|
|
308
|
+
// «어느 원격에 쓰는가» 자체가 흔들린다. ⇒ 첫 글자를 넣기 前에 한 번 해석·캡처하고 그 값을 세션 전체에
|
|
309
|
+
// 고정한다. 해석이 확정되기 前에는 원장 행을 «쓰지 않는다»(fail-closed).
|
|
310
|
+
//
|
|
311
|
+
// ⛔ 여기서 해석기를 새로 만들지 않는다 — 목록은 `pty-manifest`(listPtyManifestRows/…At),
|
|
312
|
+
// 해석은 `pty-ref`(resolvePtyRef), 북마크는 `cli/remotes`(RemotesStore) 가 정본이다.
|
|
313
|
+
|
|
314
|
+
/** 사람 타이핑 세션이 고정하는 원격 북마크 신원 — 캡처는 세션 시작 때 한 번뿐이다. */
|
|
315
|
+
export interface PtyTypingBookmarkPin {
|
|
316
|
+
readonly name: string;
|
|
317
|
+
readonly host: string;
|
|
318
|
+
readonly url: string;
|
|
319
|
+
readonly token?: string;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** 타이핑 세션의 고정값 — 이 객체가 사는 동안 재해석·재조회가 없다. */
|
|
323
|
+
export interface PtyHumanTypingSession {
|
|
324
|
+
/** 호출자가 준 ref(그대로 보존 — 원장·로그 대조용). */
|
|
325
|
+
readonly ref: string;
|
|
326
|
+
/** 해석된 canonical pty id — 이후 모든 요청이 쓰는 유일한 주소. */
|
|
327
|
+
readonly ptyId: string;
|
|
328
|
+
/** 어느 단계로 확정됐나(`exact-id`·`nickname-exact`·`kind`·`id-prefix`·`nickname-substr`). */
|
|
329
|
+
readonly resolvedBy: PtyRefReason;
|
|
330
|
+
/** 캡처된 원격 북마크(로컬이면 null). */
|
|
331
|
+
readonly bookmark: PtyTypingBookmarkPin | null;
|
|
332
|
+
/** 해석에 쓴 매니페스트 뿌리 — 연합 요청이면 그 원장이다. */
|
|
333
|
+
readonly manifestDbPath?: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface PtyHumanTypingOptions {
|
|
337
|
+
/** 해석에 쓸 매니페스트 뿌리 — 없으면 이 프로세스의 원장(`ptyManifestDbPath`). */
|
|
338
|
+
readonly manifestDbPath?: string;
|
|
339
|
+
/** 이미 읽어 둔 핀(호출자가 캡처를 마친 경우) — 재조회하지 않는다. */
|
|
340
|
+
readonly bookmark?: PtyTypingBookmarkPin;
|
|
341
|
+
/** 캡처할 북마크 이름. 없으면 default 북마크, 그것도 없으면 로컬(null). */
|
|
342
|
+
readonly bookmarkName?: string;
|
|
343
|
+
/** remotes.json 저장소 재정의(시험·연합). */
|
|
344
|
+
readonly remotes?: RemotesStore;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export type PtyHumanTypingResolution =
|
|
348
|
+
| { readonly ok: true; readonly session: PtyHumanTypingSession }
|
|
349
|
+
| {
|
|
350
|
+
readonly ok: false;
|
|
351
|
+
readonly status: 'ambiguous-ref' | 'unresolved-ref' | 'unknown-bookmark';
|
|
352
|
+
/** ambiguous 면 후보 canonical id 들(사람이 고를 수 있게). */
|
|
353
|
+
readonly candidates: readonly string[];
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
type BookmarkCapture = { readonly ok: true; readonly pin: PtyTypingBookmarkPin | null } | { readonly ok: false };
|
|
357
|
+
|
|
358
|
+
function captureTypingBookmark(options: PtyHumanTypingOptions): BookmarkCapture {
|
|
359
|
+
if (options.bookmark) return { ok: true, pin: options.bookmark };
|
|
360
|
+
const wanted = options.bookmarkName?.trim() ?? '';
|
|
361
|
+
try {
|
|
362
|
+
const store = options.remotes ?? new RemotesStore();
|
|
363
|
+
const listed = wanted ? undefined : store.listRemotes().find((item) => item.isDefault);
|
|
364
|
+
const entry = wanted ? store.getRemote(wanted) : listed?.entry;
|
|
365
|
+
if (!entry) return wanted ? { ok: false } : { ok: true, pin: null };
|
|
366
|
+
const token = store.readToken(entry);
|
|
367
|
+
return {
|
|
368
|
+
ok: true,
|
|
369
|
+
pin: {
|
|
370
|
+
name: wanted || listed?.name || entry.host,
|
|
371
|
+
host: entry.host,
|
|
372
|
+
url: bookmarkToElanousRemote(entry),
|
|
373
|
+
...(token ? { token } : {}),
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
} catch {
|
|
377
|
+
return { ok: false };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* ★ 사람 타이핑 세션 시작 — ref(alias·nickname·id)를 canonical id 로 **한 번** 해석하고
|
|
383
|
+
* bookmark host/token/URL 을 **한 번** 캡처한다. 해석이 확정되지 않으면 세션을 만들지 않는다.
|
|
384
|
+
*
|
|
385
|
+
* 목록은 «한 번의 스냅숏»이다(살아 있는 행만) — 해석 도중 목록이 바뀌어도 이 세션은 흔들리지 않는다.
|
|
386
|
+
*/
|
|
387
|
+
export function beginPtyHumanTypingSession(ref: string, options: PtyHumanTypingOptions = {}): PtyHumanTypingResolution {
|
|
388
|
+
const items = (options.manifestDbPath ? listPtyManifestRowsAt(options.manifestDbPath) : listPtyManifestRows())
|
|
389
|
+
.filter((row) => row.alive)
|
|
390
|
+
.map((row) => ({ id: row.id, kind: row.kind, ...(row.nickname ? { nickname: row.nickname } : {}) }));
|
|
391
|
+
const resolution = resolvePtyRef(ref, items);
|
|
392
|
+
if (!resolution.match) {
|
|
393
|
+
const candidates = resolution.candidates.map((item) => item.id);
|
|
394
|
+
debug.log('pty.control', 'typing-ref-unresolved', { ref, reason: resolution.reason, candidates });
|
|
395
|
+
return { ok: false, status: resolution.reason === 'ambiguous' ? 'ambiguous-ref' : 'unresolved-ref', candidates };
|
|
396
|
+
}
|
|
397
|
+
const captured = captureTypingBookmark(options);
|
|
398
|
+
if (!captured.ok) {
|
|
399
|
+
// ⛔ 명시적으로 부른 북마크를 못 읽었으면 fail-closed. (부르지 않은 default 캡처 실패는 로컬로 떨어진다 — 아래)
|
|
400
|
+
if (options.bookmarkName?.trim()) {
|
|
401
|
+
debug.log('pty.control', 'typing-bookmark-unavailable', { ref, bookmark: options.bookmarkName.trim() });
|
|
402
|
+
return { ok: false, status: 'unknown-bookmark', candidates: [] };
|
|
403
|
+
}
|
|
404
|
+
debug.log('pty.control', 'typing-bookmark-skipped', { ref, reason: 'default-bookmark-unreadable' });
|
|
405
|
+
}
|
|
406
|
+
const session: PtyHumanTypingSession = {
|
|
407
|
+
ref,
|
|
408
|
+
ptyId: resolution.match.id,
|
|
409
|
+
resolvedBy: resolution.reason,
|
|
410
|
+
bookmark: captured.ok ? captured.pin : null,
|
|
411
|
+
...(options.manifestDbPath ? { manifestDbPath: options.manifestDbPath } : {}),
|
|
412
|
+
};
|
|
413
|
+
debug.log('pty.control', 'typing-session-pinned', {
|
|
414
|
+
ref: session.ref,
|
|
415
|
+
ptyId: session.ptyId,
|
|
416
|
+
resolvedBy: session.resolvedBy,
|
|
417
|
+
bookmark: session.bookmark?.name ?? 'local',
|
|
418
|
+
});
|
|
419
|
+
return { ok: true, session };
|
|
420
|
+
}
|
|
421
|
+
|
|
274
422
|
export async function requestRemotePtyControl(id: string, action: PtyControlAction, payloadOrTimeout?: PtyControlPayload | number, timeoutOrOptions: PtyControlRequestOptions | number = {}): Promise<PtyControlResult> {
|
|
275
423
|
const payload = typeof payloadOrTimeout === 'number' ? undefined : payloadOrTimeout;
|
|
276
424
|
const options = typeof timeoutOrOptions === 'number' ? { timeoutMs: timeoutOrOptions } : timeoutOrOptions;
|
|
@@ -280,23 +428,48 @@ export async function requestRemotePtyControl(id: string, action: PtyControlActi
|
|
|
280
428
|
// 시험만 가상 시각으로 deadline·grace 경계와 cadence 를 결정론적으로 민다(벽시계 판별 없음).
|
|
281
429
|
const pollNow = options.now ?? Date.now;
|
|
282
430
|
const pollWait = options.sleep ?? ((ms: number): Promise<void> => Bun.sleep(ms));
|
|
283
|
-
|
|
431
|
+
// ⭐ 사람 타이핑(input-text/input-key)은 원장에 «쓰기 前» ref 를 canonical id 로 확정한다.
|
|
432
|
+
// 확정 전에는 행을 안 쓴다(fail-closed) — 미해석·모호한 ref 가 남의 PTY 에 닿지 않게.
|
|
433
|
+
const typingAction = action === 'input-text' || action === 'input-key';
|
|
434
|
+
let session = options.typingSession;
|
|
435
|
+
let targetId = id;
|
|
436
|
+
if (typingAction) {
|
|
437
|
+
if (!session) {
|
|
438
|
+
const started = beginPtyHumanTypingSession(id, {
|
|
439
|
+
...(options.manifestDbPath ? { manifestDbPath: options.manifestDbPath } : {}),
|
|
440
|
+
...(options.bookmarkName ? { bookmarkName: options.bookmarkName } : {}),
|
|
441
|
+
...(options.typingBookmark ? { bookmark: options.typingBookmark } : {}),
|
|
442
|
+
});
|
|
443
|
+
if (!started.ok) {
|
|
444
|
+
return started.status === 'ambiguous-ref'
|
|
445
|
+
? { status: 'denied', reason: 'pty-ref-ambiguous' }
|
|
446
|
+
: started.status === 'unknown-bookmark'
|
|
447
|
+
? { status: 'denied', reason: 'typing-bookmark-unavailable' }
|
|
448
|
+
: { status: 'unknown-pty' };
|
|
449
|
+
}
|
|
450
|
+
session = started.session;
|
|
451
|
+
}
|
|
452
|
+
targetId = session.ptyId;
|
|
453
|
+
}
|
|
454
|
+
// 세션 핀이 연합 원장을 정했으면 그 원장을 쓴다(재해석·재조회 없음).
|
|
455
|
+
const queuePath = options.manifestDbPath ?? session?.manifestDbPath;
|
|
456
|
+
const opened = dbAt(queuePath);
|
|
284
457
|
const d = opened.database;
|
|
285
458
|
try {
|
|
286
459
|
cleanupStale(d);
|
|
287
|
-
const target =
|
|
288
|
-
? d.query('SELECT owner_pid, alive FROM pty_manifest WHERE id=?').get(
|
|
289
|
-
: getPtyManifest(
|
|
460
|
+
const target = queuePath
|
|
461
|
+
? d.query('SELECT owner_pid, alive FROM pty_manifest WHERE id=?').get(targetId) as { owner_pid: number; alive: number } | null
|
|
462
|
+
: getPtyManifest(targetId);
|
|
290
463
|
if (!target || !target.alive) return { status: 'unknown-pty' };
|
|
291
464
|
const ownerPid = 'owner_pid' in target ? target.owner_pid : target.ownerPid;
|
|
292
465
|
const requestId = crypto.randomUUID();
|
|
293
466
|
const now = Date.now();
|
|
294
467
|
// ⭐ 요청자의 run anchor 를 요청에 실어 보낸다 — 인가는 **owner 가** 자기 PTY 의 run 과 대조해 내린다
|
|
295
468
|
// (요청자 자기 신고를 그대로 믿지 않는다는 뜻이 아니라, 판정 지점이 자원 소유자라는 뜻).
|
|
296
|
-
d.run(`INSERT INTO pty_control_requests (request_id, pty_id, action, payload_json, actor, requester_run_id, owner_pid, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [requestId,
|
|
469
|
+
d.run(`INSERT INTO pty_control_requests (request_id, pty_id, action, payload_json, actor, requester_run_id, owner_pid, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [requestId, targetId, action, payload ? JSON.stringify(payload) : null, actor, getHarnessRunId(process.env), ownerPid, 'pending', now, now]);
|
|
297
470
|
// ⭐ 깊은 유휴 감속 중인 owner 를 즉시 깨운다 — 행을 넣은 «뒤» 표식을 남기므로 그 재읽기가 이 행을 본다.
|
|
298
471
|
// 표식은 그 행의 `ownerPid` «별» 파일이다 — 같은 원장을 공유하는 다른 owner 가 가져가지 못한다.
|
|
299
|
-
signalPtyControlWake(
|
|
472
|
+
signalPtyControlWake(queuePath ?? ptyManifestDbPath(), ownerPid);
|
|
300
473
|
const readback = (): ControlRow | null => d.query(SELECT_ROW).get(requestId) as ControlRow | null;
|
|
301
474
|
const del = (): void => { d.run('DELETE FROM pty_control_requests WHERE request_id=?', [requestId]); };
|
|
302
475
|
const deadline = pollNow() + timeoutMs;
|
|
@@ -369,6 +542,8 @@ export interface PtyControlProcessOptions {
|
|
|
369
542
|
readonly takeoverTtlMs?: number;
|
|
370
543
|
/** 깊은 유휴 감속 계단 **전용** 시계(기본 `Date.now`). `now` 는 takeover TTL 시계라 섞지 않는다. */
|
|
371
544
|
readonly pollClock?: () => number;
|
|
545
|
+
/** 큐를 실제로 다시 읽을 때마다 1회 — 감속 계측용. 생산 진입점은 넘기지 않는다. */
|
|
546
|
+
readonly onQueueRead?: () => void;
|
|
372
547
|
}
|
|
373
548
|
|
|
374
549
|
function positiveInteger(value: unknown): number | undefined {
|
|
@@ -409,17 +584,11 @@ export function processPtyControlRequests(getHandle: (id: string) => PtyControlT
|
|
|
409
584
|
// 감속 구간에서는 여기서 «큐를 다시 읽지 않는» 것으로 끝나고, 첫 원격 요청의 표식이 오면 즉시 통과한다.
|
|
410
585
|
// ⛔ 감속 열쇠는 아래 `processPtyControlRequestsOnce` 가 실제로 여는 원장(`db()` = `ptyManifestDbPath()`)과
|
|
411
586
|
// 같은 경로다 — 상태는 한 큐, 읽기는 다른 큐로 갈라지지 않는다.
|
|
412
|
-
if (!shouldReadControlQueue(ptyManifestDbPath(), (options.pollClock ?? Date.now)())) return Promise.resolve();
|
|
587
|
+
if (!shouldReadControlQueue(ptyManifestDbPath(), (options.pollClock ?? Date.now)(), cadenceLimits(options))) return Promise.resolve();
|
|
413
588
|
inFlight = processPtyControlRequestsOnce(getHandle, takeover, options).finally(() => { inFlight = null; });
|
|
414
589
|
return inFlight;
|
|
415
590
|
}
|
|
416
591
|
|
|
417
|
-
/** 요청이 실제로 들어간 원장 — 깨어움 표식은 «그 원장의 owner» 가 보는 자리에 남겨야 한다.
|
|
418
|
-
* 연합 요청(`manifestDbPath`)이면 그 원장 디렉터리, 내 요청이면 내 원장. */
|
|
419
|
-
function requestQueuePath(options: { readonly manifestDbPath?: string }): string {
|
|
420
|
-
return options.manifestDbPath ?? ptyManifestDbPath();
|
|
421
|
-
}
|
|
422
|
-
|
|
423
592
|
async function processPtyControlRequestsOnce(getHandle: (id: string) => PtyControlTarget | undefined, takeover: (id: string, actor: 'human') => boolean, options: PtyControlProcessOptions): Promise<void> {
|
|
424
593
|
const d = db();
|
|
425
594
|
const now = options.now ?? Date.now;
|
|
@@ -23,6 +23,8 @@ import { getSessionCwd } from '../session/working-dir.js';
|
|
|
23
23
|
import { buildPtyEnv } from '../agent/identity-env.js';
|
|
24
24
|
import { getCurrentPtyId } from '../agent/pty-identity.js';
|
|
25
25
|
import { bunNativePtyAvailable, bunSpawnPty } from './bun-native-pty.js';
|
|
26
|
+
import { ptyAvailable } from './availability.js';
|
|
27
|
+
export { ptyAvailable } from './availability.js';
|
|
26
28
|
import { resolvePtyRef, canTransitionAccessMode, ptyIdSeparatorIndex, type PtyAccessMode, type PtyTransitionPolicy } from './pty-ref.js';
|
|
27
29
|
import { resolveWriteDecision, resolveTakeover, type PtyWriteActor } from './pty-write-arbiter.js';
|
|
28
30
|
import { addPtyManifestOutputBytes, upsertPtyManifest, updatePtyManifestSnapshot, updatePtyManifestNickname, markPtyManifestClosed, removePtyManifest, touchLivePtyManifest } from './pty-manifest.js';
|
|
@@ -513,7 +515,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
513
515
|
set nickname(v: string | undefined) { nickname = v; },
|
|
514
516
|
setNickname(name: string): void {
|
|
515
517
|
nickname = name.trim() || undefined;
|
|
516
|
-
if (
|
|
518
|
+
if (ptyManifestEnabled()) updatePtyManifestNickname(id, nickname, Date.now());
|
|
517
519
|
},
|
|
518
520
|
get accessMode() { return accessMode; },
|
|
519
521
|
set accessMode(v: PtyAccessMode) { accessMode = v; },
|
|
@@ -718,7 +720,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
718
720
|
catch (error) { debug.log('pty.record', 'tap-error', { ptyId: id, error: String(error) }); }
|
|
719
721
|
emitPtyEvent({ type: 'output', id, chunk });
|
|
720
722
|
// ★ 크로스-프로세스 관측(2026-07-23) — throttled 스냅샷을 공유 매니페스트에(데몬 PWA 유니온). getter 라 throttle 통과 시에만 snapshot().
|
|
721
|
-
if (
|
|
723
|
+
if (ptyManifestEnabled()) {
|
|
722
724
|
pendingManifestOutputBytes += Buffer.byteLength(chunk, 'utf8');
|
|
723
725
|
const now = Date.now();
|
|
724
726
|
// ⛔⭐ throttle 이 막은 출력도 «반드시» 실린다 — 안 그러면 마지막 버스트 뒤 조용해진 PTY 의
|
|
@@ -741,7 +743,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
741
743
|
try { autoStopPtyRecording(id); }
|
|
742
744
|
catch (error) { debug.log('pty.record', 'auto-stop-error', { ptyId: id, error: String(error) }); }
|
|
743
745
|
emitPtyEvent({ type: 'exit', id, exitCode: code, signal });
|
|
744
|
-
if (
|
|
746
|
+
if (ptyManifestEnabled()) {
|
|
745
747
|
const now = Date.now();
|
|
746
748
|
// Manifest closure and output durability are separate: a closed row keeps retrying trailing bytes until committed.
|
|
747
749
|
manifestOutputFlush.close(now);
|
|
@@ -754,7 +756,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
754
756
|
// ★ 크로스-프로세스 관측 — startPty 를 공유 매니페스트에 등록(다른 프로세스 데몬이 /v1/terminals 로 봄). fail-soft.
|
|
755
757
|
// ⚠️ 테스트 런(NODE_ENV=test·bun test)은 skip — 테스트가 띄우는 임시 셸(self-implement gate·CI·수동 bun test)이
|
|
756
758
|
// 운영 매니페스트(~/.elanous/pty)로 새어들어 관측소를 오염시키던 근본 차단(격리). 실 세션(NODE_ENV≠test)만 등록.
|
|
757
|
-
if (
|
|
759
|
+
if (ptyManifestEnabled()) {
|
|
758
760
|
const childSpaceId = opts.env?.ELANOUS_HARNESS_SPACE_ID;
|
|
759
761
|
const childParentPtyId = opts.env?.ELANOUS_PARENT_PTY_ID ?? getCurrentPtyId();
|
|
760
762
|
const childController = opts.env?.ELANOUS_CONTROLLER?.trim();
|
|
@@ -800,8 +802,24 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
800
802
|
return handle;
|
|
801
803
|
}
|
|
802
804
|
|
|
803
|
-
/** 공유 PTY 매니페스트 등록 활성 여부 — 테스트 런(bun test=NODE_ENV=test)은 운영 매니페스트 오염 방지 위해 off.
|
|
804
|
-
|
|
805
|
+
/** 공유 PTY 매니페스트 등록 활성 여부 — 테스트 런(bun test=NODE_ENV=test)은 운영 매니페스트 오염 방지 위해 off.
|
|
806
|
+
*
|
|
807
|
+
* ⭐ 자리(seat) 수명주기는 이 기록자에서만 원장에 실린다 — spawned/exited 사건의 seat·
|
|
808
|
+
* 누적 outputBytesTotal·exitCode 를 남기는 곳이 `upsertPtyManifest`/`markPtyManifestClosed` 이기
|
|
809
|
+
* 때문이다. 그런데 NODE_ENV 판정만 있으면 **격리 test 우주에서는 이 경로를 한 번도 지날 수 없어**
|
|
810
|
+
* 자리 수명주기가 실행 증거를 가질 수 없다(합성 manifest 직접 호출만 남는다 — 완료 경계가 금지).
|
|
811
|
+
* ⇒ 판정을 호출 시점 함수로 두고, 격리 우주(전용 `ELANOUS_STATE_DIR`·전용 manifest db)가 **명시적으로**
|
|
812
|
+
* 켤 수 있는 seam 을 둔다. override 가 없으면 종전과 같은 NODE_ENV 판정이라 운영 동작은 불변이다. */
|
|
813
|
+
let _ptyManifestEnabledOverride: boolean | null = null;
|
|
814
|
+
|
|
815
|
+
/** 테스트 전용 seam — 격리 우주에서 생산 기록 경로를 그대로 지나기 위해 켠다. null = NODE_ENV 판정 복귀. */
|
|
816
|
+
export function setPtyManifestEnabledForTesting(enabled: boolean | null): void {
|
|
817
|
+
_ptyManifestEnabledOverride = enabled;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function ptyManifestEnabled(): boolean {
|
|
821
|
+
return _ptyManifestEnabledOverride ?? process.env.NODE_ENV !== 'test';
|
|
822
|
+
}
|
|
805
823
|
|
|
806
824
|
// ★ 라이브 PTY 하트비트(2026-07-23) — 소유 프로세스가 자기 라이브 PTY 의 updated_at 을 주기 갱신해
|
|
807
825
|
// "살아있음"을 증명한다. 데몬의 stale reap 이 하트비트 끊긴 유령만 제거하도록(pid 재활용 견고). unref 로 프로세스 종료 방해 X.
|
|
@@ -904,7 +922,7 @@ export function renamePty(id: string, nickname: string): boolean {
|
|
|
904
922
|
// 별명은 manifest 행에만 산다. 여기서 받지 않으면 IPC rename 이 그 행에 `unknown-pty` 로 진다.
|
|
905
923
|
const target = controlTargets.get(id);
|
|
906
924
|
if (!target || !target.isAlive()) return false;
|
|
907
|
-
if (
|
|
925
|
+
if (ptyManifestEnabled()) updatePtyManifestNickname(id, nickname.trim() || undefined, Date.now());
|
|
908
926
|
debug.log('pty.rename', 'control-target-renamed', { ptyId: id, nickname: nickname.trim() });
|
|
909
927
|
return true;
|
|
910
928
|
}
|
|
@@ -1012,14 +1030,6 @@ export function killNonDetached(): number {
|
|
|
1012
1030
|
return killed;
|
|
1013
1031
|
}
|
|
1014
1032
|
|
|
1015
|
-
/** Probe-compatible. Under Bun the native PTY (Bun.spawn terminal) is
|
|
1016
|
-
* used instead of node-pty, so PTY is available even if node-pty can't
|
|
1017
|
-
* resolve. Under node we still require node-pty. */
|
|
1018
|
-
export function ptyAvailable(): boolean {
|
|
1019
|
-
if (bunNativePtyAvailable()) return true;
|
|
1020
|
-
try { require.resolve('node-pty'); return true; } catch { return false; }
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
1033
|
// ─── Adapter wiring ──────────────────────────────────────────────
|
|
1024
1034
|
|
|
1025
1035
|
let cachedSpawn: ((opts: StartOpts) => PtyAdapter) | null | undefined = undefined;
|