elanous 0.2.36 → 0.2.38
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 → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.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/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- 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/ask-op-inbox-once.ts +17 -0
- package/scripts/boundary-proof-mapping-audit.ts +88 -0
- package/scripts/brand/check.ts +13 -4
- 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-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +546 -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/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- 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/gate-node.ts +161 -25
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- 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-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +406 -7
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +109 -15
- 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/scripts/video-pipeline.ts +2 -2
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +12 -1
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +537 -57
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- 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/bots/screen-probe.ts +1 -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 +42 -5
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- 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/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- 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/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +58 -5
- package/src/cli/release-checklist-read-cli.ts +112 -4
- package/src/cli/release-cli.ts +89 -18
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +24 -6
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +370 -33
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/context-now.ts +86 -2
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +5 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +115 -30
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- 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/guardian-tick.ts +9 -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/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +34 -7
- package/src/graph-wizard/generate.ts +29 -6
- package/src/grok/credential.ts +107 -36
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +151 -18
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +55 -0
- package/src/llm.ts +203 -21
- 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/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +55 -7
- package/src/maturity/feature-maturity.ts +1 -0
- 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/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -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/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -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/patents/ledger.ts +18 -1
- package/src/policy/llm-policy.ts +3 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +9 -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/pty-manifest.ts +16 -2
- 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/gate-shards.ts +61 -0
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +18 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- 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/decompose.ts +45 -9
- package/src/self-dev/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +254 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +310 -6
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +108 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +99 -1
- package/src/self-implement/gate-cli.ts +231 -82
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +30 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +407 -21
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +110 -27
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +125 -12
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +369 -33
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- 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 +428 -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 +45 -16
- package/src/self-implement/self-implement-cli.ts +26 -2
- 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/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +10 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +6 -0
- package/src/session-runtime/index.ts +18 -23
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/pty.ts +5 -0
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- 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/storage/file-lock.ts +17 -4
- package/src/task-agent/actions.ts +199 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- 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/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- 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 +74 -17
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +108 -8
- package/src/task-agent/repair-next-move.ts +12 -2
- package/src/task-agent/repair-worker.ts +37 -1
- 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 +253 -20
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +40 -5
- 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-failure-reason.ts +31 -4
- 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 +77 -8
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
- package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +722 -30
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +38 -35
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +72 -0
- package/src/tui-client/local-chat-turn.ts +31 -9
- package/src/user-config.ts +30 -3
- 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 +17 -6
- package/src/ux-sim/next-tui-seat-scenarios.ts +176 -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/190.285c832bd9626f8c.js +0 -64
- 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/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/2986.45d7652e4f13557e.js +0 -2
- 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/3757-180308bc61021b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
- 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/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/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/6466-92e65a48490b68a9.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/727.7deb87749b0a343a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.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/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/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/live/page-e2de2e59111c9aad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.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/missions/[id]/page-2af16e62c12f22df.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/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/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/ccae1c4b-0cf414f5eff1b10d.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/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ownerMatches, type ChecklistItem } from './checklist.js';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
2
4
|
|
|
3
5
|
export interface MergedChecklistPr { number: number; title: string; body: string | null; mergedAt: string }
|
|
4
6
|
type PrMatchBasis = 'cell-line' | 'title-strong' | 'mention';
|
|
@@ -113,35 +115,106 @@ export function landedButYellow(items: readonly ChecklistItem[], prs: readonly M
|
|
|
113
115
|
return rows.sort((a, b) => Number(b.newer) - Number(a.newer));
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
export interface MergedPrRunResult { status: number | null; stdout: string; stderr: string }
|
|
118
|
+
export interface MergedPrRunResult { status: number | null; stdout: string; stderr: string; timedOut?: boolean }
|
|
117
119
|
/** One `gh` invocation; resolves when the process exits. */
|
|
118
|
-
export type MergedPrRunner = (command: string, args: readonly string[], cwd: string) => Promise<MergedPrRunResult>;
|
|
120
|
+
export type MergedPrRunner = (command: string, args: readonly string[], cwd: string, timeoutMs?: number) => Promise<MergedPrRunResult>;
|
|
119
121
|
|
|
120
122
|
export const MERGED_PR_LIMIT = 400;
|
|
121
123
|
/** Concurrent `gh pr list` calls once the first page is full (LANDED-YELLOW-FAST · 10-21 prod: 24 sequential calls ≈ 145s). */
|
|
122
124
|
export const MERGED_PR_CONCURRENCY = 6;
|
|
123
125
|
const DAY_MS = 86_400_000;
|
|
124
126
|
|
|
127
|
+
export interface MergedChecklistFetch {
|
|
128
|
+
prs: MergedChecklistPr[];
|
|
129
|
+
truncated: boolean;
|
|
130
|
+
calls: number;
|
|
131
|
+
/** Set when a time budget stopped the window walk before every window was fetched. */
|
|
132
|
+
stopReason: 'time-budget-exceeded' | undefined;
|
|
133
|
+
/** UTC windows not yet fetched when `stopReason` is set. */
|
|
134
|
+
remainingWindows: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const FETCH_CACHE_TTL_MS = 10 * 60_000;
|
|
138
|
+
interface PersistedFetchCache { schema: 1; entries: Record<string, { savedAt: number; result: MergedChecklistFetch }> }
|
|
139
|
+
|
|
140
|
+
function cacheRead(path: string, key: string, nowMs: number): MergedChecklistFetch | undefined {
|
|
141
|
+
try {
|
|
142
|
+
if (!existsSync(path)) return undefined;
|
|
143
|
+
const cache = JSON.parse(readFileSync(path, 'utf8')) as PersistedFetchCache;
|
|
144
|
+
const entry = cache?.schema === 1 ? cache.entries?.[key] : undefined;
|
|
145
|
+
if (!entry || !Number.isFinite(entry.savedAt) || nowMs - entry.savedAt < 0 || nowMs - entry.savedAt >= FETCH_CACHE_TTL_MS) return undefined;
|
|
146
|
+
if (!Array.isArray(entry.result?.prs) || entry.result.stopReason !== undefined) return undefined;
|
|
147
|
+
return { ...entry.result, calls: 0 };
|
|
148
|
+
} catch { return undefined; }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function cacheWrite(path: string, key: string, result: MergedChecklistFetch, nowMs: number): void {
|
|
152
|
+
try {
|
|
153
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
154
|
+
let entries: PersistedFetchCache['entries'] = {};
|
|
155
|
+
try {
|
|
156
|
+
const cache = JSON.parse(readFileSync(path, 'utf8')) as PersistedFetchCache;
|
|
157
|
+
if (cache?.schema === 1 && cache.entries && typeof cache.entries === 'object') entries = cache.entries;
|
|
158
|
+
} catch { /* replace an unreadable cache with a fresh one */ }
|
|
159
|
+
for (const [entryKey, entry] of Object.entries(entries)) if (!Number.isFinite(entry.savedAt) || nowMs - entry.savedAt >= FETCH_CACHE_TTL_MS) delete entries[entryKey];
|
|
160
|
+
entries[key] = { savedAt: nowMs, result };
|
|
161
|
+
const temp = `${path}.${process.pid}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
162
|
+
writeFileSync(temp, `${JSON.stringify({ schema: 1, entries } satisfies PersistedFetchCache)}\n`, { mode: 0o600 });
|
|
163
|
+
renameSync(temp, path);
|
|
164
|
+
} catch { /* cache is an optimization; a failed write must not fail the read-only command */ }
|
|
165
|
+
}
|
|
166
|
+
|
|
125
167
|
/**
|
|
126
168
|
* Merged PRs since `since` (UTC date). One call answers when it returns fewer than the cap. Otherwise the range
|
|
127
169
|
* splits into UTC-day windows fetched with a concurrency cap; a full window is halved down to one second as before,
|
|
128
170
|
* and a full one-second window probes one extra row to tell exactly 400 from truncation.
|
|
171
|
+
* With `timeBudgetMs`, each gh request is bounded by the remaining time; a slow initial request or window returns the
|
|
172
|
+
* partial result with `stopReason: 'time-budget-exceeded'` and UTC window starts in `remainingWindows`.
|
|
129
173
|
* The returned set and the truncation flag match the former sequential bisection; only call shape and time differ.
|
|
174
|
+
* A completed result is cached across CLI processes for ten minutes; a partial (`stopReason`) result is never cached.
|
|
130
175
|
*/
|
|
131
176
|
export async function fetchMergedChecklistPrs(since: string, now: Date, run: MergedPrRunner, cwd: string,
|
|
132
|
-
{ concurrency = MERGED_PR_CONCURRENCY }: { concurrency?: number } = {}): Promise<
|
|
177
|
+
{ concurrency = MERGED_PR_CONCURRENCY, timeBudgetMs, cacheFile }: { concurrency?: number; timeBudgetMs?: number; cacheFile?: string } = {}): Promise<MergedChecklistFetch> {
|
|
178
|
+
const cacheKey = JSON.stringify([since, now.toISOString().slice(0, 10), cwd, concurrency,
|
|
179
|
+
process.env.GH_REPO ?? process.env.GITHUB_REPOSITORY ?? '']);
|
|
180
|
+
const cached = cacheFile ? cacheRead(cacheFile, cacheKey, Date.now()) : undefined;
|
|
181
|
+
if (cached) return cached;
|
|
182
|
+
const deadline = timeBudgetMs === undefined ? undefined : performance.now() + timeBudgetMs;
|
|
183
|
+
const over = (): boolean => deadline !== undefined && performance.now() >= deadline;
|
|
184
|
+
const cacheable = (result: MergedChecklistFetch): MergedChecklistFetch => {
|
|
185
|
+
if (result.stopReason !== undefined || !cacheFile) return result;
|
|
186
|
+
cacheWrite(cacheFile, cacheKey, result, Date.now());
|
|
187
|
+
return result;
|
|
188
|
+
};
|
|
133
189
|
let calls = 0;
|
|
134
|
-
const fetch = async (lower: string, upper?: string, limit = MERGED_PR_LIMIT): Promise<MergedChecklistPr[]> => {
|
|
190
|
+
const fetch = async (lower: string, upper?: string, limit = MERGED_PR_LIMIT): Promise<MergedChecklistPr[] | null> => {
|
|
135
191
|
const search = `merged:>=${lower}${upper ? ` merged:<${upper}` : ''}`;
|
|
192
|
+
if (over()) return null;
|
|
136
193
|
calls++;
|
|
137
|
-
const
|
|
194
|
+
const args = ['pr', 'list', '--state', 'merged', '--search', search, '--limit', String(limit), '--json', 'number,title,body,mergedAt'];
|
|
195
|
+
const remainingMs = deadline === undefined ? undefined : Math.max(1, Math.ceil(deadline - performance.now()));
|
|
196
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
197
|
+
const request = run('gh', args, cwd, remainingMs);
|
|
198
|
+
let r: MergedPrRunResult | null;
|
|
199
|
+
try {
|
|
200
|
+
r = remainingMs === undefined ? await request : await Promise.race([
|
|
201
|
+
request,
|
|
202
|
+
new Promise<null>((resolve) => { timer = setTimeout(() => resolve(null), remainingMs); }),
|
|
203
|
+
]);
|
|
204
|
+
} finally { if (timer !== undefined) clearTimeout(timer); }
|
|
205
|
+
if (r === null || r.timedOut) return null;
|
|
138
206
|
if (r.status !== 0) throw new Error(`병합 PR 조회(gh) 실패 rc=${r.status}: ${(r.stderr || r.stdout).trim().slice(0, 400)}`);
|
|
139
207
|
const page = JSON.parse(r.stdout.trim()) as MergedChecklistPr[];
|
|
140
208
|
if (!Array.isArray(page)) throw new Error('병합 PR 조회(gh): 배열이 아니다');
|
|
141
209
|
return page;
|
|
142
210
|
};
|
|
211
|
+
const lower = Date.parse(`${since}T00:00:00Z`);
|
|
212
|
+
const upper = Math.max(lower + 1000, Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1));
|
|
213
|
+
const windows: Array<[number, number]> = [];
|
|
214
|
+
for (let start = lower; start < upper; start += DAY_MS) windows.push([start, Math.min(start + DAY_MS, upper)]);
|
|
143
215
|
const first = await fetch(since);
|
|
144
|
-
if (first
|
|
216
|
+
if (first === null) return cacheable({ prs: [], truncated: false, calls, stopReason: 'time-budget-exceeded', remainingWindows: windows.map(([start]) => new Date(start).toISOString()) });
|
|
217
|
+
if (first.length < MERGED_PR_LIMIT) return cacheable({ prs: first, truncated: false, calls, stopReason: undefined, remainingWindows: [] });
|
|
145
218
|
// Bounded pool: at most `concurrency` gh processes at once; a failure stops new calls and rejects.
|
|
146
219
|
let active = 0;
|
|
147
220
|
let failed: unknown;
|
|
@@ -155,14 +228,20 @@ export async function fetchMergedChecklistPrs(since: string, now: Date, run: Mer
|
|
|
155
228
|
finally { active--; if (failed !== undefined) for (const wake of waiting.splice(0)) wake(); else waiting.shift()?.(); }
|
|
156
229
|
};
|
|
157
230
|
let truncated = false;
|
|
231
|
+
const remainingWindows: string[] = [];
|
|
158
232
|
const visit = async (start: number, end: number): Promise<MergedChecklistPr[]> => {
|
|
159
233
|
const from = new Date(start).toISOString();
|
|
160
234
|
const to = new Date(end).toISOString();
|
|
161
|
-
|
|
235
|
+
// The budget is checked when the window actually starts (inside the pool), not when `visit` is mapped —
|
|
236
|
+
// every window is mapped at once, so a check here would run before the first fetch resolves.
|
|
237
|
+
const page = await limited(async () => (over() ? null : fetch(from, to)));
|
|
238
|
+
if (page === null) { remainingWindows.push(from); return []; }
|
|
162
239
|
if (page.length < MERGED_PR_LIMIT) return page;
|
|
163
240
|
if (end - start <= 1000) {
|
|
164
241
|
// The second-precision search cannot be subdivided; probe one extra row to distinguish exactly 400 from a real truncation.
|
|
242
|
+
if (over()) { remainingWindows.push(from); return page.slice(0, MERGED_PR_LIMIT); }
|
|
165
243
|
const probe = await limited(() => fetch(from, to, MERGED_PR_LIMIT + 1));
|
|
244
|
+
if (probe === null) { remainingWindows.push(from); return page.slice(0, MERGED_PR_LIMIT); }
|
|
166
245
|
if (probe.length > MERGED_PR_LIMIT) truncated = true;
|
|
167
246
|
return probe.slice(0, MERGED_PR_LIMIT);
|
|
168
247
|
}
|
|
@@ -170,15 +249,17 @@ export async function fetchMergedChecklistPrs(since: string, now: Date, run: Mer
|
|
|
170
249
|
const [left, right] = await Promise.all([visit(start, middle), visit(middle, end)]);
|
|
171
250
|
return [...left, ...right];
|
|
172
251
|
};
|
|
173
|
-
const lower = Date.parse(`${since}T00:00:00Z`);
|
|
174
|
-
const upper = Math.max(lower + 1000, Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1));
|
|
175
|
-
const windows: Array<[number, number]> = [];
|
|
176
|
-
for (let start = lower; start < upper; start += DAY_MS) windows.push([start, Math.min(start + DAY_MS, upper)]);
|
|
177
252
|
const settled = await Promise.allSettled(windows.map(([start, end]) => visit(start, end)));
|
|
178
253
|
const rejected = settled.find((result): result is PromiseRejectedResult => result.status === 'rejected');
|
|
179
254
|
if (rejected) throw failed ?? rejected.reason;
|
|
180
255
|
// Chronological window order, first occurrence wins — the same de-duplication as before.
|
|
181
256
|
const unique = new Map<number, MergedChecklistPr>();
|
|
182
257
|
for (const result of settled) for (const pr of (result as PromiseFulfilledResult<MergedChecklistPr[]>).value) if (!unique.has(pr.number)) unique.set(pr.number, pr);
|
|
183
|
-
|
|
258
|
+
remainingWindows.sort();
|
|
259
|
+
if (remainingWindows.length) {
|
|
260
|
+
// The broad first page is usable partial evidence if the detailed window walk runs out of budget.
|
|
261
|
+
for (const pr of first) if (!unique.has(pr.number)) unique.set(pr.number, pr);
|
|
262
|
+
truncated = true;
|
|
263
|
+
}
|
|
264
|
+
return cacheable({ prs: [...unique.values()], truncated, calls, stopReason: remainingWindows.length ? 'time-budget-exceeded' : undefined, remainingWindows });
|
|
184
265
|
}
|
|
@@ -7,7 +7,7 @@ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
|
7
7
|
import { tmpdir } from 'node:os';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { debug } from '../debug/log.js';
|
|
10
|
-
import {
|
|
10
|
+
import { runSelfGateCliAsync, type SelfGateCliOptions, type SelfGateCliResult } from '../self-implement/gate-cli.js';
|
|
11
11
|
import { dispatchHeavyCheck, isValidGateHost, type DispatchDeps, type DispatchOptions } from '../self-implement/gate-remote.js';
|
|
12
12
|
import { latestPublishedPreviousVersion } from '../../scripts/release-loop/unattended-release.js';
|
|
13
13
|
import { baseVersion, isReleaseVersion } from '../../scripts/release-loop/release-version.js';
|
|
@@ -29,6 +29,8 @@ export interface LightRcOptions {
|
|
|
29
29
|
/** Run on this machine (the remote child is re-invoked with it). */
|
|
30
30
|
local?: boolean;
|
|
31
31
|
shards?: number;
|
|
32
|
+
/** Maximum simultaneously active gate bundles, including per-file RSS samples (default three). */
|
|
33
|
+
shardConcurrency?: number;
|
|
32
34
|
/** OP FU — pass `--fixed-shard-distribution` to self gate (sorted round-robin into `shards`, no RSS pre-measurement).
|
|
33
35
|
* Opt-in; absent = the measured planner, unchanged. Also carried to the remote child. */
|
|
34
36
|
fixedShardDistribution?: boolean;
|
|
@@ -71,7 +73,7 @@ export interface LightRcDeps {
|
|
|
71
73
|
git?: (args: string[], cwd: string) => { rc: number | null; stdout: string };
|
|
72
74
|
previousVersion?: (version: string, ledgerRoot?: string) => string;
|
|
73
75
|
readFile?: (path: string) => string | undefined;
|
|
74
|
-
runGate?: (cwd: string, options: SelfGateCliOptions) => SelfGateCliResult
|
|
76
|
+
runGate?: (cwd: string, options: SelfGateCliOptions) => SelfGateCliResult | Promise<SelfGateCliResult>;
|
|
75
77
|
dispatch?: (opts: DispatchOptions, deps?: DispatchDeps) => Promise<number>;
|
|
76
78
|
/** Extra dispatch deps (runner · settings) — tests drive the real dispatch with a fake host. */
|
|
77
79
|
dispatchDeps?: Omit<DispatchDeps, 'write'>;
|
|
@@ -175,6 +177,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
175
177
|
if (!isReleaseVersion(version)) throw new Error(`release version must be x.y.z: ${version}`);
|
|
176
178
|
const shards = opts.shards ?? LIGHT_RC_DEFAULT_SHARDS;
|
|
177
179
|
if (!Number.isSafeInteger(shards) || shards < 1) throw new Error(`invalid --shards count: ${opts.shards}`);
|
|
180
|
+
if (opts.shardConcurrency !== undefined && (!Number.isSafeInteger(opts.shardConcurrency) || opts.shardConcurrency < 1 || opts.shardConcurrency > 4)) throw new Error(`invalid --shard-concurrency: ${opts.shardConcurrency}`);
|
|
178
181
|
if (opts.remote !== undefined && !isValidGateHost(opts.remote)) throw new Error(`invalid --remote host: ${opts.remote}`);
|
|
179
182
|
const log = opts.log ?? ((line: string) => process.stderr.write(`${line}\n`));
|
|
180
183
|
const cwd = repoRoot(deps);
|
|
@@ -195,7 +198,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
195
198
|
try {
|
|
196
199
|
const dir = checkout?.dir ?? cwd;
|
|
197
200
|
if (checkout) alwaysInclude = readList(dir);
|
|
198
|
-
local = (deps.runGate ??
|
|
201
|
+
local = await (deps.runGate ?? runSelfGateCliAsync)(dir, { base, shards, ...(opts.shardConcurrency !== undefined ? { shardConcurrency: opts.shardConcurrency } : {}), ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), alwaysInclude, includeImporterTests: true });
|
|
199
202
|
if (opts.rehearsalTui) {
|
|
200
203
|
const command = async (cmd: string, args: string[], tree: string, limitMs?: number) => {
|
|
201
204
|
const run = spawnSync(cmd, args, { cwd: tree, encoding: 'utf8', timeout: limitMs });
|
|
@@ -212,7 +215,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
212
215
|
// Keep the self-gate contract: an unavailable remote leaves this release check unmeasured; do not start a heavy gate locally.
|
|
213
216
|
tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
|
|
214
217
|
// The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
|
|
215
|
-
remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), ...(opts.fixedShardDistribution ? ['--fixed-shard-distribution'] : []), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
|
|
218
|
+
remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), ...(opts.shardConcurrency !== undefined ? ['--shard-concurrency', String(opts.shardConcurrency)] : []), ...(opts.fixedShardDistribution ? ['--fixed-shard-distribution'] : []), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
|
|
216
219
|
flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
|
|
217
220
|
runLocal,
|
|
218
221
|
}, {
|
|
@@ -495,7 +495,7 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
|
|
|
495
495
|
const introducedCount: number | null = stamp.outcome === 'unmeasured' || stamp.outcome === 'error' ? null : hard.introduced.length;
|
|
496
496
|
const preexistingCount: number | null = introducedCount === null ? null : hard.preexisting;
|
|
497
497
|
const totalFailures: number | null = introducedCount === null || preexistingCount === null ? null : introducedCount + preexistingCount;
|
|
498
|
-
stamp.summary = oneLine(`hard gate ${hard.outcome} · introduced ${introducedCount ?? 'UNKNOWN'} · preexisting ${preexistingCount ?? 'UNKNOWN'} · total failures ${totalFailures ?? 'UNKNOWN'} ·
|
|
498
|
+
stamp.summary = oneLine(`hard gate ${hard.outcome} · introduced ${introducedCount ?? 'UNKNOWN'} · preexisting ${preexistingCount ?? 'UNKNOWN'} · total failures ${totalFailures ?? 'UNKNOWN'} · 원격 Pod · 12 shards · runId ${hardGateRunId} · evidence ${hardGateLog}${cause ? ` · ${cause}` : ''}`);
|
|
499
499
|
} else {
|
|
500
500
|
const shardPlan = opts.shards === undefined ? (deps.shardPlan ?? planRehearsalShards)(plan.version, root, checkout, { ...deps.shardPlanDeps, remoteGate: true }) : undefined;
|
|
501
501
|
if (shardPlan) stamp.shardPlan = shardPlan;
|
package/src/repl/index.ts
CHANGED
|
@@ -198,6 +198,7 @@ function buildReplTools(): {
|
|
|
198
198
|
specs.push(wakeup.spec);
|
|
199
199
|
dispatchByName.set(wakeup.spec.name, wakeup.dispatch);
|
|
200
200
|
}
|
|
201
|
+
(require('../tui/sidetab/nl-tool.js') as typeof import('../tui/sidetab/nl-tool.js')).registerNextSidetabReplTool(specs, dispatchByName, process as unknown as import('../tui/sidetab/nl-tool.js').NextSidetabIpcProcess);
|
|
201
202
|
const planner = sr.createSearchPlannerState({ maxAutoNarrowCandidates: 2 });
|
|
202
203
|
const dispatch = async (name: string, args: Record<string, unknown>): Promise<unknown> => {
|
|
203
204
|
try {
|
|
@@ -211,6 +212,14 @@ function buildReplTools(): {
|
|
|
211
212
|
searchPlannerState: planner,
|
|
212
213
|
turnIndex: undefined,
|
|
213
214
|
ptyDashboardOn: false,
|
|
215
|
+
// Match the CLI agent path: native Agent fallback needs the parent's
|
|
216
|
+
// catalog and dispatcher so children can actually use inherited tools.
|
|
217
|
+
agentHostTools: specs,
|
|
218
|
+
agentDispatchTool: dispatch,
|
|
219
|
+
buildChildToolCatalog: (childCwd: string) => {
|
|
220
|
+
const cli = require('../cli/agent-cli.js') as typeof import('../cli/agent-cli.js');
|
|
221
|
+
return cli.buildCliAgentTools(undefined, undefined, childCwd);
|
|
222
|
+
},
|
|
214
223
|
getToolRuntime: () => undefined,
|
|
215
224
|
dispatchToolRuntime: async (n) => ({ error: `runtime unavailable in REPL: ${n}` }),
|
|
216
225
|
dispatchPluginTool: async (n) => ({ ok: false as const, error: `plugin unavailable in REPL: ${n}` }),
|
|
@@ -334,6 +343,7 @@ async function runOneTurn(
|
|
|
334
343
|
jsonOutput: boolean,
|
|
335
344
|
nextTuiDelivery?: { pending: PendingTaskNotification[] },
|
|
336
345
|
onJsonDelta?: (delta: string) => void,
|
|
346
|
+
onJsonStatus?: (line: string) => void,
|
|
337
347
|
): Promise<{ reply: string; provider: string; model: string | null; durationMs: number; logPath: string | null }> {
|
|
338
348
|
const startedAt = Date.now();
|
|
339
349
|
const replyChunks: string[] = [];
|
|
@@ -366,6 +376,10 @@ async function runOneTurn(
|
|
|
366
376
|
userText,
|
|
367
377
|
systemPrompt,
|
|
368
378
|
userImages: userImages.length > 0 ? userImages : undefined,
|
|
379
|
+
...(process.env.ELANOUS_TEST_FAKE_LLM === '1' && Number.isFinite(Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS))
|
|
380
|
+
&& Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS) > 0
|
|
381
|
+
? { llmOpts: { streamIdleTimeoutMs: Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS) } }
|
|
382
|
+
: {}),
|
|
369
383
|
onDelta: (d) => {
|
|
370
384
|
if (jsonOutput) {
|
|
371
385
|
replyChunks.push(d);
|
|
@@ -373,6 +387,7 @@ async function runOneTurn(
|
|
|
373
387
|
}
|
|
374
388
|
else process.stdout.write(d);
|
|
375
389
|
},
|
|
390
|
+
onStatusLine: (line) => { onJsonStatus?.(line); },
|
|
376
391
|
tools: replToolSpecs,
|
|
377
392
|
dispatchTool: tools?.dispatch,
|
|
378
393
|
onToolCall: (call) => {
|
|
@@ -777,6 +792,9 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
|
|
|
777
792
|
process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
|
|
778
793
|
? (delta) => { process.stdout.write(`${JSON.stringify({ event: 'delta', turnId: turn.id, text: delta })}\n`); }
|
|
779
794
|
: undefined,
|
|
795
|
+
process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
|
|
796
|
+
? (text) => { process.stdout.write(`${JSON.stringify({ event: 'status', turnId: turn.id, text })}\n`); }
|
|
797
|
+
: undefined,
|
|
780
798
|
);
|
|
781
799
|
} catch (error) {
|
|
782
800
|
if (!backgroundBridge) throw error;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Research-only native fanout. The caller supplies Bloom's question ladder;
|
|
2
|
+
// each axis gets its own direct tool call and evidence stays attributed to it.
|
|
3
|
+
import type { BloomResearchQuestion, ResearchEvidenceEnvelope } from '../auto-research/question-ladder-contract.js';
|
|
4
|
+
import type { WebSearchHit } from '../web-search/provider.js';
|
|
5
|
+
|
|
6
|
+
export interface AxisToolCallPlan {
|
|
7
|
+
questionId: string;
|
|
8
|
+
tool: 'OmniSearch';
|
|
9
|
+
query: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AxisEvidenceGroup {
|
|
13
|
+
questionId: string;
|
|
14
|
+
evidence: ResearchEvidenceEnvelope[];
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AxisFanoutResult {
|
|
19
|
+
plan: AxisToolCallPlan[];
|
|
20
|
+
axes: AxisEvidenceGroup[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type AxisSearchHit = WebSearchHit & { engine?: string };
|
|
24
|
+
export interface AxisSearchResult {
|
|
25
|
+
hits: AxisSearchHit[];
|
|
26
|
+
errors: string[];
|
|
27
|
+
}
|
|
28
|
+
export type AxisSearch = (query: string) => Promise<AxisSearchHit[] | AxisSearchResult>;
|
|
29
|
+
|
|
30
|
+
export interface AxisFanoutDeps {
|
|
31
|
+
search?: AxisSearch;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Keep every query attached to the Bloom question that produced it. */
|
|
35
|
+
export function planAxisToolCalls(questions: readonly BloomResearchQuestion[]): AxisToolCallPlan[] {
|
|
36
|
+
return questions.flatMap(question => question.searchTerms
|
|
37
|
+
.map(query => query.trim())
|
|
38
|
+
.filter(Boolean)
|
|
39
|
+
.map(query => ({ questionId: question.id, tool: 'OmniSearch' as const, query })));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function directOmniSearch(query: string): Promise<AxisSearchResult> {
|
|
43
|
+
const { dispatchOmniSearch } = await import('../skills/tools/omni-search.js');
|
|
44
|
+
const hits: AxisSearchHit[] = [];
|
|
45
|
+
const result = await dispatchOmniSearch({ query }, { onSource: hit => { hits.push(hit); } });
|
|
46
|
+
if (Object.keys(result.metadata.perEngine).length === 0) {
|
|
47
|
+
throw new Error('no available web-search providers');
|
|
48
|
+
}
|
|
49
|
+
const errors = Object.entries(result.metadata.perEngine)
|
|
50
|
+
.flatMap(([engine, info]) => info.error ? [`${engine}: ${info.error}`] : []);
|
|
51
|
+
return { hits, errors };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function evidenceFromHit(question: BloomResearchQuestion, hit: AxisSearchHit): ResearchEvidenceEnvelope {
|
|
55
|
+
const published = hit.publishedAt;
|
|
56
|
+
const date = published !== undefined && Number.isFinite(published) && published > 0
|
|
57
|
+
? new Date(published) : undefined;
|
|
58
|
+
const observedAt = date && Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
|
|
59
|
+
return {
|
|
60
|
+
questionId: question.id,
|
|
61
|
+
sourceKind: hit.engine ? `web-search:${hit.engine}` : 'web-search',
|
|
62
|
+
source: hit.url,
|
|
63
|
+
...(question.requestedWindow ? { requestedWindow: question.requestedWindow } : {}),
|
|
64
|
+
...(observedAt ? { observedAt } : {}),
|
|
65
|
+
content: [hit.title, hit.snippet].filter(Boolean).join(' — '),
|
|
66
|
+
outcome: hit.snippet ? 'complete' : 'partial',
|
|
67
|
+
truncated: true, // Search snippets are excerpts, not the complete source page.
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function failedEvidence(question: BloomResearchQuestion, query: string, message: string): ResearchEvidenceEnvelope {
|
|
72
|
+
return {
|
|
73
|
+
questionId: question.id,
|
|
74
|
+
sourceKind: 'search-query',
|
|
75
|
+
source: query,
|
|
76
|
+
...(question.requestedWindow ? { requestedWindow: question.requestedWindow } : {}),
|
|
77
|
+
content: message,
|
|
78
|
+
outcome: 'failed',
|
|
79
|
+
truncated: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Invoke all axis queries concurrently, preserving ladder order and partial failures. */
|
|
84
|
+
export async function fanOutAxisEvidence(
|
|
85
|
+
questions: readonly BloomResearchQuestion[],
|
|
86
|
+
deps: AxisFanoutDeps = {},
|
|
87
|
+
): Promise<AxisFanoutResult> {
|
|
88
|
+
const plan = planAxisToolCalls(questions);
|
|
89
|
+
if (new Set(questions.map(question => question.id)).size !== questions.length) {
|
|
90
|
+
throw new Error('research axis question IDs must be unique');
|
|
91
|
+
}
|
|
92
|
+
const search = deps.search ?? directOmniSearch;
|
|
93
|
+
const settled = await Promise.allSettled(plan.map(call => search(call.query)));
|
|
94
|
+
const axes: AxisEvidenceGroup[] = questions.map(question => ({ questionId: question.id, evidence: [] }));
|
|
95
|
+
const groups = new Map(axes.map(axis => [axis.questionId, axis]));
|
|
96
|
+
const byQuestion = new Map(questions.map(question => [question.id, question]));
|
|
97
|
+
for (const question of questions) {
|
|
98
|
+
if (!plan.some(call => call.questionId === question.id)) {
|
|
99
|
+
const group = groups.get(question.id)!;
|
|
100
|
+
group.error = 'no search terms';
|
|
101
|
+
group.evidence.push(failedEvidence(question, question.prompt, group.error));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
settled.forEach((outcome, index) => {
|
|
105
|
+
const call = plan[index]!;
|
|
106
|
+
const group = groups.get(call.questionId)!;
|
|
107
|
+
const question = byQuestion.get(call.questionId)!;
|
|
108
|
+
if (outcome.status === 'fulfilled') {
|
|
109
|
+
const response = Array.isArray(outcome.value) ? { hits: outcome.value, errors: [] } : outcome.value;
|
|
110
|
+
if (response.hits.length === 0 && response.errors.length === 0) {
|
|
111
|
+
group.evidence.push({ ...failedEvidence(question, call.query, 'no hits returned'), outcome: 'partial' });
|
|
112
|
+
}
|
|
113
|
+
for (const hit of response.hits) {
|
|
114
|
+
try {
|
|
115
|
+
group.evidence.push(evidenceFromHit(question, hit));
|
|
116
|
+
} catch (err) {
|
|
117
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
118
|
+
group.error = group.error ? `${group.error}; ${message}` : message;
|
|
119
|
+
group.evidence.push(failedEvidence(question, call.query, message));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const message of response.errors) {
|
|
123
|
+
group.error = group.error ? `${group.error}; ${message}` : message;
|
|
124
|
+
group.evidence.push(failedEvidence(question, call.query, message));
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
const message = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
|
|
128
|
+
group.error = group.error ? `${group.error}; ${message}` : message;
|
|
129
|
+
group.evidence.push(failedEvidence(question, call.query, message));
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return { plan, axes };
|
|
133
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { GraphNodeSpec } from '../self-implement/graph-yaml.js';
|
|
2
|
+
|
|
3
|
+
/** Opaque Bloom 4/5 output. The hook owns the decision boundary, not analysis policy. */
|
|
4
|
+
export interface BloomEdgeAssessment {
|
|
5
|
+
gaps: readonly unknown[];
|
|
6
|
+
contradictions: readonly unknown[];
|
|
7
|
+
verdicts: readonly unknown[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ResearchEdgeAction = 'add' | 'prune' | 'deepen' | 'stop';
|
|
11
|
+
|
|
12
|
+
export interface ResearchEdgeProposal {
|
|
13
|
+
node: GraphNodeSpec;
|
|
14
|
+
returnTo?: string;
|
|
15
|
+
reason: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ResearchEdgeDecision {
|
|
19
|
+
action: ResearchEdgeAction;
|
|
20
|
+
reason: string;
|
|
21
|
+
evidence: readonly string[];
|
|
22
|
+
proposal?: ResearchEdgeProposal;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ResolvedResearchEdgeDecision extends ResearchEdgeDecision {
|
|
26
|
+
provider: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ResearchEdgeDecisionProvider = (
|
|
30
|
+
assessment: BloomEdgeAssessment,
|
|
31
|
+
) => ResearchEdgeDecision | Promise<ResearchEdgeDecision>;
|
|
32
|
+
|
|
33
|
+
export interface ResearchEdgeDecisionRegistry {
|
|
34
|
+
register(provider: ResearchEdgeDecisionProvider, name?: string): () => void;
|
|
35
|
+
decide(assessment: BloomEdgeAssessment): Promise<ResolvedResearchEdgeDecision>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const noOpDecision: ResearchEdgeDecision = {
|
|
39
|
+
action: 'stop',
|
|
40
|
+
reason: 'no edge decision provider registered',
|
|
41
|
+
evidence: [],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** One registry belongs to one run. With no provider, the graph takes one round and stops. */
|
|
45
|
+
export function createResearchEdgeDecisionRegistry(): ResearchEdgeDecisionRegistry {
|
|
46
|
+
const providers = new Map<symbol, { name: string; decide: ResearchEdgeDecisionProvider }>();
|
|
47
|
+
return {
|
|
48
|
+
register(provider, name = 'registered') {
|
|
49
|
+
const key = Symbol('research-edge-decision-provider');
|
|
50
|
+
providers.set(key, { name, decide: provider });
|
|
51
|
+
return () => { providers.delete(key); };
|
|
52
|
+
},
|
|
53
|
+
async decide(assessment) {
|
|
54
|
+
const provider = [...providers.values()].at(-1);
|
|
55
|
+
if (!provider) return { ...noOpDecision, provider: 'default-noop' };
|
|
56
|
+
try {
|
|
57
|
+
const decision = await provider.decide(assessment);
|
|
58
|
+
if (!isResearchEdgeDecision(decision)) {
|
|
59
|
+
return { action: 'stop', reason: 'edge decision provider returned an invalid decision', evidence: [], provider: provider.name };
|
|
60
|
+
}
|
|
61
|
+
return { ...decision, evidence: [...decision.evidence], provider: provider.name };
|
|
62
|
+
} catch (error) {
|
|
63
|
+
return { action: 'stop', reason: `edge decision provider failed: ${String(error)}`, evidence: [], provider: provider.name };
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isResearchEdgeDecision(value: unknown): value is ResearchEdgeDecision {
|
|
70
|
+
if (!isRecord(value) || !['add', 'prune', 'deepen', 'stop'].includes(String(value.action))
|
|
71
|
+
|| typeof value.reason !== 'string' || !value.reason.trim()
|
|
72
|
+
|| !Array.isArray(value.evidence) || !value.evidence.every((item) => typeof item === 'string')) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (value.action === 'add') return isResearchEdgeProposal(value.proposal);
|
|
76
|
+
return value.proposal === undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isResearchEdgeProposal(value: unknown): value is ResearchEdgeProposal {
|
|
80
|
+
return isRecord(value) && isRecord(value.node) && typeof value.node.nodeId === 'string'
|
|
81
|
+
&& typeof value.node.kind === 'string' && typeof value.node.recipe === 'string'
|
|
82
|
+
&& typeof value.reason === 'string' && value.reason.trim().length > 0
|
|
83
|
+
&& (value.returnTo === undefined || typeof value.returnTo === 'string');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
87
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
88
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { SkillIndexEntry } from '../skills/index.js';
|
|
2
|
+
import { getSkillIndex } from '../skills/index.js';
|
|
3
|
+
|
|
4
|
+
export type ResearchQuestionWeight = 'light' | 'medium' | 'heavy';
|
|
5
|
+
export type ResearchOutputFormat = 'text' | 'table' | 'card' | 'web-article' | 'diagram';
|
|
6
|
+
export type ResearchOutputFallbackReason = 'no-matching-skill-in-registry';
|
|
7
|
+
|
|
8
|
+
export interface ResearchOutputRouteInput {
|
|
9
|
+
question: string;
|
|
10
|
+
synthesizedResult: string;
|
|
11
|
+
weight?: ResearchQuestionWeight;
|
|
12
|
+
axes?: readonly string[];
|
|
13
|
+
skills?: readonly SkillIndexEntry[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ResearchOutputRouteDecision {
|
|
17
|
+
weight: ResearchQuestionWeight;
|
|
18
|
+
weightSource: 'caller' | 'estimated';
|
|
19
|
+
format: ResearchOutputFormat;
|
|
20
|
+
skillCallPlan?: { skill: string; args: string };
|
|
21
|
+
fallbackReason?: ResearchOutputFallbackReason;
|
|
22
|
+
observation: {
|
|
23
|
+
resultChars: number;
|
|
24
|
+
axisCount: number;
|
|
25
|
+
estimatedWeight: ResearchQuestionWeight;
|
|
26
|
+
selectedSkill?: string;
|
|
27
|
+
fallback?: ResearchOutputFallbackReason;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const OUTPUT_FORMAT_SIGNALS: Record<Exclude<ResearchOutputFormat, 'text'>, readonly string[]> = {
|
|
32
|
+
table: ['comparison table', 'research table', 'data table', 'tabular report', '비교 표', '조사 표'],
|
|
33
|
+
card: ['knowledge card', 'research card', 'summary card', 'flashcard', '지식 카드', '요약 카드'],
|
|
34
|
+
'web-article': ['web article', 'web publishing', 'html article', 'article publishing', '웹 아티클'],
|
|
35
|
+
diagram: ['diagram', '다이어그램', 'visualization', '시각화', 'chart'],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const normalizeMetadata = (value: string): string => value.toLowerCase().replace(/[_-]+/g, ' ').replace(/\s+/g, ' ').trim();
|
|
39
|
+
|
|
40
|
+
function countAxes(axes: readonly string[] | undefined): number {
|
|
41
|
+
return new Set((axes ?? []).map((axis) => normalizeMetadata(axis)).filter(Boolean)).size;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function estimateResearchQuestionWeight(resultChars: number, axisCount: number): ResearchQuestionWeight {
|
|
45
|
+
if (resultChars >= 4_000 || axisCount >= 4) return 'heavy';
|
|
46
|
+
if (resultChars >= 1_200 || axisCount >= 2) return 'medium';
|
|
47
|
+
return 'light';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function chooseFormat(weight: ResearchQuestionWeight, axisCount: number): ResearchOutputFormat {
|
|
51
|
+
if (weight === 'light') return 'text';
|
|
52
|
+
if (weight === 'medium') return axisCount >= 2 ? 'table' : 'card';
|
|
53
|
+
return axisCount >= 4 ? 'diagram' : 'web-article';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function skillScore(format: Exclude<ResearchOutputFormat, 'text'>, skill: SkillIndexEntry): number {
|
|
57
|
+
const metadata = normalizeMetadata([
|
|
58
|
+
skill.name,
|
|
59
|
+
skill.category ?? '',
|
|
60
|
+
skill.description,
|
|
61
|
+
...skill.triggers,
|
|
62
|
+
...skill.extractedTriggers,
|
|
63
|
+
].join(' '));
|
|
64
|
+
return OUTPUT_FORMAT_SIGNALS[format].reduce((score, signal) => {
|
|
65
|
+
const normalizedSignal = normalizeMetadata(signal);
|
|
66
|
+
return metadata.includes(normalizedSignal) ? score + normalizedSignal.length : score;
|
|
67
|
+
}, 0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function findOutputSkill(
|
|
71
|
+
format: Exclude<ResearchOutputFormat, 'text'>,
|
|
72
|
+
skills: readonly SkillIndexEntry[],
|
|
73
|
+
): SkillIndexEntry | undefined {
|
|
74
|
+
return skills
|
|
75
|
+
.map((skill) => ({ skill, score: skillScore(format, skill) }))
|
|
76
|
+
.filter((entry) => entry.score > 0)
|
|
77
|
+
.sort((a, b) => b.score - a.score || a.skill.name.localeCompare(b.skill.name))[0]?.skill;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function buildSkillArgs(question: string, synthesizedResult: string, format: ResearchOutputFormat): string {
|
|
81
|
+
return [
|
|
82
|
+
`Format the synthesized research output as ${format}.`,
|
|
83
|
+
`Question: ${escapeSkillArgument(question)}`,
|
|
84
|
+
'Research synthesis:',
|
|
85
|
+
escapeSkillArgument(synthesizedResult),
|
|
86
|
+
].join('\n\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Keep untrusted research text from closing the XML-like prefill argument block. */
|
|
90
|
+
function escapeSkillArgument(value: string): string {
|
|
91
|
+
return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Deterministic output routing. Weight may be supplied by an upstream axis; otherwise it is inferred from synthesis size and distinct axes. */
|
|
95
|
+
export function routeResearchOutput(input: ResearchOutputRouteInput): ResearchOutputRouteDecision {
|
|
96
|
+
const resultChars = input.synthesizedResult.length;
|
|
97
|
+
const axisCount = countAxes(input.axes);
|
|
98
|
+
const estimatedWeight = estimateResearchQuestionWeight(resultChars, axisCount);
|
|
99
|
+
const weight = input.weight ?? estimatedWeight;
|
|
100
|
+
const desiredFormat = chooseFormat(weight, axisCount);
|
|
101
|
+
const observation = { resultChars, axisCount, estimatedWeight };
|
|
102
|
+
|
|
103
|
+
if (desiredFormat === 'text') {
|
|
104
|
+
return { weight, weightSource: input.weight ? 'caller' : 'estimated', format: 'text', observation };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const registry = input.skills ?? getSkillIndex();
|
|
108
|
+
const selected = findOutputSkill(desiredFormat, registry);
|
|
109
|
+
if (!selected) {
|
|
110
|
+
const fallbackReason: ResearchOutputFallbackReason = 'no-matching-skill-in-registry';
|
|
111
|
+
return {
|
|
112
|
+
weight,
|
|
113
|
+
weightSource: input.weight ? 'caller' : 'estimated',
|
|
114
|
+
format: 'text',
|
|
115
|
+
fallbackReason,
|
|
116
|
+
observation: { ...observation, fallback: fallbackReason },
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
weight,
|
|
122
|
+
weightSource: input.weight ? 'caller' : 'estimated',
|
|
123
|
+
format: desiredFormat,
|
|
124
|
+
skillCallPlan: { skill: selected.name, args: buildSkillArgs(input.question, input.synthesizedResult, desiredFormat) },
|
|
125
|
+
observation: { ...observation, selectedSkill: selected.name },
|
|
126
|
+
};
|
|
127
|
+
}
|