elanous 0.2.19 → 0.2.21
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/MObU8ujkMciAKr6ljAV05/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/088d8e8a.8069543d082bec12.js +160 -0
- package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +148 -0
- package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +32 -0
- package/apps/pwa/out/_next/static/chunks/119fc678.6f591cdb84ca5791.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +309 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 1268.0840ff91e083fcbd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +122 -0
- package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +79 -0
- package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1948.5f35b39eef222a94.js +5 -0
- package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2977-e38442e86289f1d3.js → 211-9c9090c59e2c5907.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +36 -0
- package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +286 -0
- package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522-1de1319d028ac89c.js +25 -0
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +115 -0
- package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.ad3364cb7fb97ada.js +86 -0
- package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +77 -0
- package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +90 -0
- package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +1 -0
- package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{4847.56f5bc454fbcc827.js → 6110.1297d4093fdfbb0d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6158.566c890adc06a459.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +287 -0
- package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +226 -0
- package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6767.8e6c5f6e744fcd9f.js +38 -0
- package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7175-350f4ce2873bc038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +41 -0
- package/apps/pwa/out/_next/static/chunks/{1470.98a6ab61ccb4131c.js → 726.83532d69452ee24b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 7327-2d69fb321ba73389.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7630.2b9a68659053ff4e.js +193 -0
- package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7899.597af4a9996c907f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79b78388.663188133449d707.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8194.484f51e273d9abd2.js +217 -0
- package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/88729267.9c6c000157c83f2f.js +62 -0
- package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7647.2fcd30d894d5ee30.js → 935.4ddaa99fc1d1126c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +23 -0
- package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/9832.2ab2e818013574c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-40c16bd0efdb04b8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-111cabe4d1fd69ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-b70cd005d9169e25.js → page-be8b4615c919e36c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/d70879db.c66c56a95a91efc6.js +66 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → f6231284-45726550aba08fca.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2ea96958.e8c7e112de50b067.js → f6b7c9ba.64a895b8b2fedbdc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/f8626309.a4e5d362b1d55e59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +1 -0
- package/apps/pwa/out/_next/static/css/{d3427996da11e480.css → b9d8151e48998417.css} +1 -1
- package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +1 -0
- 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 +24 -24
- 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 +23 -23
- 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 -0
- package/apps/pwa/out/live-run/index.txt +35 -0
- 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/demo/editor-recipes.yaml +22 -0
- package/graphs/drafts/recipes.yaml +4 -4
- package/graphs/implement-loop.yaml +277 -5
- package/graphs/retro/daily.yaml +25 -0
- package/graphs/retro/recipes.yaml +24 -0
- package/package.json +1 -1
- package/scripts/ask-marker-check.ts +3 -1
- package/scripts/coord-channel-watch.sh +31 -4
- package/scripts/docs-lint.ts +4 -1
- package/scripts/land-global-checks.ts +89 -0
- package/scripts/lib/pch-regress-map.ts +2 -1
- package/scripts/marketing/generate-ax-brief.ts +18 -1
- package/scripts/measure-nl-routing-corpus.ts +11 -3
- package/scripts/release-loop/gate-node.ts +296 -25
- package/scripts/release-loop/gate-timing.ts +116 -7
- package/scripts/release-loop/preflight.ts +6 -4
- package/scripts/release-loop/publish-window.ts +141 -0
- package/scripts/release-loop/release-docs.ts +1 -4
- package/scripts/release-loop/release-universe.ts +38 -0
- package/scripts/release-loop/resume-release.ts +4 -1
- package/scripts/release-loop/shard-plan.ts +50 -5
- package/scripts/release-loop/unattended-release.ts +10 -2
- package/scripts/release-story/draft.ts +5 -1
- package/scripts/retro/shadow-compare.ts +71 -0
- package/scripts/rhythm/daily.ts +8 -2
- package/src/agent-mission/driver.ts +34 -6
- package/src/autopilot/build/llm-conflict-merge.ts +132 -7
- package/src/autopilot/build/merge-intent.ts +135 -7
- package/src/away/release-watch.ts +20 -3
- package/src/browser-cdp/client.ts +10 -5
- package/src/cli/config-drift.ts +513 -0
- package/src/cli/log-event-names.ts +4 -0
- package/src/cli/ops-cli.ts +11 -0
- package/src/cli/ops-overview-cli.ts +50 -0
- package/src/cli/pod-cli.ts +1 -0
- package/src/cli/pr-cli.ts +20 -0
- package/src/cli/release-cli.ts +20 -5
- package/src/cli/retro-cli.ts +78 -0
- package/src/cli/tasks-cli.ts +200 -8
- package/src/dashboard/index.ts +40 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -4
- package/src/dashboard/slash-runtime/help-from-registry.ts +57 -31
- package/src/domains/outbound-log-probe.ts +6 -1
- package/src/esc-abort-gate.ts +3 -1
- package/src/graph-runner/graph-cli.ts +57 -0
- package/src/graph-runner/graph-run-api.ts +218 -0
- package/src/graph-runner/runner.ts +11 -1
- package/src/graph-wizard/archetypes.ts +88 -0
- package/src/graph-wizard/generate.ts +545 -0
- package/src/graph-wizard/saved-steps.ts +120 -0
- package/src/graph-wizard/steps.ts +193 -0
- package/src/harness/harness-cli-command.ts +482 -59
- package/src/harness/harness-queue.ts +315 -25
- package/src/harness/harness-salvage-cli.ts +62 -0
- package/src/hq/fence-outcomes.ts +63 -0
- package/src/hq/fence-wrapper.ts +33 -0
- package/src/hq/hq.ts +11 -1
- package/src/index.ts +76 -10
- package/src/intake-plane/digest.ts +18 -11
- package/src/maturity/feature-maturity.ts +4 -3
- package/src/nexus/api/draft-metrics.ts +114 -0
- package/src/nexus/api/graph-kinds.ts +10 -4
- package/src/nexus/api/graph-wizard-api.ts +53 -0
- package/src/nexus/api/graphs-api.ts +220 -10
- package/src/nexus/api/harness-traversal.ts +205 -0
- package/src/nexus/api/http-server.ts +69 -3
- package/src/nexus/api/loop-edges.ts +4 -2
- package/src/nexus/api/ops-api.ts +22 -7
- package/src/nexus/api/ops-board-route.ts +48 -0
- package/src/nexus/outbound/router.ts +28 -8
- package/src/onboarding/entry-hints.ts +5 -0
- package/src/onboarding/first-run.ts +3 -0
- package/src/onboarding.ts +24 -6
- package/src/ops/overview-collect.ts +345 -0
- package/src/ops/overview-seat-era.ts +90 -0
- package/src/ops/overview.ts +223 -0
- package/src/release-loop/feature-store.ts +14 -11
- package/src/release-loop/gate-shards.ts +163 -0
- package/src/release-loop/release-schedule.ts +6 -2
- package/src/retro/daily.ts +372 -0
- package/src/seat-loop/op-decide.ts +173 -0
- package/src/seat-loop/seat-loop.ts +60 -3
- package/src/seat-loop/seat-report.ts +58 -3
- package/src/self-dev/ask-launch-flow.ts +9 -6
- package/src/self-dev/ask-launch-io.ts +52 -2
- package/src/self-dev/ask-path-candidates.ts +40 -2
- package/src/self-dev/draft-sweep.ts +371 -16
- package/src/self-dev/draft-triage-rules.ts +19 -4
- package/src/self-dev/graph-journey-nodes.ts +157 -0
- package/src/self-dev/graph-journey-route.ts +105 -0
- package/src/self-dev/launch-preflight.ts +43 -3
- package/src/self-dev/pr-preview.ts +84 -16
- package/src/self-dev/release-path-guard.ts +7 -4
- package/src/self-implement/blocked-draft-policy.ts +101 -0
- package/src/self-implement/execution-clarification.ts +11 -0
- package/src/self-implement/frozen-merges.ts +23 -0
- package/src/self-implement/gate-env-retry.ts +83 -0
- package/src/self-implement/goal-author.ts +14 -0
- package/src/self-implement/heal-intake.ts +3 -0
- package/src/self-implement/orchestrator.ts +234 -6
- package/src/self-implement/run-stop.ts +123 -0
- package/src/self-implement/run-ttl.ts +258 -0
- package/src/self-implement/salvage-retention.ts +123 -0
- package/src/self-implement/seams.ts +7 -0
- package/src/self-implement/self-implement-cli.ts +2 -0
- package/src/self-implement/self-implement-runtime.ts +12 -0
- package/src/self-implement/sibling-resync.ts +223 -0
- package/src/self-implement/stop-autoheal.ts +204 -0
- package/src/session-runtime/index.ts +5 -3
- package/src/shell-env-bootstrap.ts +17 -3
- package/src/task-agent/board.ts +1 -1
- package/src/task-agent/card-evidence.ts +105 -10
- package/src/task-agent/judge.ts +7 -0
- package/src/task-agent/live-moves.ts +120 -20
- package/src/task-agent/mission.ts +1 -1
- package/src/task-agent/parent-host.ts +315 -0
- package/src/task-agent/shadow.ts +10 -1
- package/src/task-agent/task-hand.ts +16 -4
- package/src/task-orchestrator/surfaces/pod-command-job.ts +60 -11
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-gate-deps.ts +123 -0
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +89 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +93 -10
- package/src/task-orchestrator/surfaces/pod-pool.ts +147 -34
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +58 -9
- package/src/telegram-commands.ts +41 -0
- package/src/testing/real-cli-spawn.ts +106 -0
- package/src/tool-runtime/browser-runtime.ts +87 -3
- package/src/tool-runtime/index.ts +1 -0
- package/src/user-config.ts +76 -7
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/J5H7BvqgSI8DUjtRRcA_S/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1157-cba0e8553d35a980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/171-23a877ed11720de9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2336-e830c777eb6bce04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-e061bb24cd2b5cde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3094.67339318c7f72a3a.js +0 -2
- package/apps/pwa/out/_next/static/chunks/338-ceb956612dcfaa86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3395-835e4ceaa6335ba4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3441-be82e3595aef3a20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3689-89905039bf3e7257.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3822-6f268bc26c6a84ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4457-d7df81c90f9d0268.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4551-77dadae76f6cbace.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4978.6fd93b974441e87f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-f746f6549b869f91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-5bfed1e23790b745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-9bc8561fde416e07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/649-ca96d1c5d09e02b8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726-85a7db59b288c53f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6735-33267c4630d0d963.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-141682015873beb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-143791231c99bd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8430-a10cfba8ef282d4e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8870-9614a213b990b10b.js +0 -25
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-12c2f30dea62291c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/976-4a9b4ebdca7c739a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-15cdf568bafa9fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-e5b1ef00b2dbceca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-deef5ee191830f14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-b193da485f9a14b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b6e1a79df0e214f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-e84df4d907f703c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a5fb9a5db89ae4ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1499f481d7fc52d6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c7cf753aeb648790.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4118469e514e10fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-e968f7630654332a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-505915052f947022.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c2f962fb4a3b06c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7b5ed0bd8a589ec4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-cf8193250dd42dd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-cf3f5dfa35dea8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-5b29d9b06ceadade.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a15e7fcc283e9ca7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-d2915e7b70ff3d0e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2595f0eba29f57e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-c776322454156e36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-77bbd17f4435aa10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-049689e611ecc936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-85954a4fb09c44eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e773e552e1068ee6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5633c4bfa7684b4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d829b92bd01b4994.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-061c317fc771becf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a45ece8865ed4b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-0be990618c0d56bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-bfea4865dc244b73.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d6ba8e337741484.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-76a88b55d816482e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-bba1542df59f61ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4185c95689bb372e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b699e1a8d5d34b8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c225e338c31bf274.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-449353f70507ca1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-90b889714102476d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f1ee7fbeb7f96ddc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-d59a95e1434dfaa0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-71491a23414d1a47.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-de7112bdb65fa4fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-feb4d0d88079660d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f17d887b40dd6b1d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-8da77be2192bcd5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-72c3b9a5e9582b29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3afe4c8d0c48c39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-b9308f2d8a931531.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-6f35f9d892fa630b.js +0 -1
- package/apps/pwa/out/_next/static/css/85f53c6f35d11382.css +0 -1
- /package/apps/pwa/out/_next/static/{J5H7BvqgSI8DUjtRRcA_S → MObU8ujkMciAKr6ljAV05}/_ssgManifest.js +0 -0
- /package/skills/project-onboarding/{skill.md → SKILL.md} +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// OP-LOOP-DECIDE — the OP seat loop filters open decision cards instead of a Claude OP session doing it by hand.
|
|
2
|
+
// Delegation = 대표 10-06 COO card filtering rule (feedback_coo_filters_decision_cards) ⊕ 10-07 scope-card default b.
|
|
3
|
+
// Config `loops.seat.opDecide.mode` = shadow (default · record only) | live (decide / route).
|
|
4
|
+
import { debug } from '../debug/log.js';
|
|
5
|
+
import type { DecisionEntry, DecisionLedger } from '../decisions/decision-ledger.js';
|
|
6
|
+
import type { SeatId } from '../seat-dispatch/seat-questions.js';
|
|
7
|
+
import { releasePathHold } from '../self-dev/release-path-guard.js';
|
|
8
|
+
|
|
9
|
+
export type OpDecideMode = 'shadow' | 'live';
|
|
10
|
+
export type OpDecideRule = 'repeat-stop' | 'scope-expand' | 'scope-sensitive' | 'scope-release-path' | 'scope-unknown' | 'run-blocking' | 'forbidden';
|
|
11
|
+
export type OpDecideVerdict =
|
|
12
|
+
| { verdict: 'auto'; rule: OpDecideRule; choice: string; reason: string }
|
|
13
|
+
| { verdict: 'route'; rule: OpDecideRule; to: SeatId | 'CEO'; reason: string };
|
|
14
|
+
export type OpDecideCandidate = { kind: 'decision-filter'; id: string; mode: OpDecideMode } & OpDecideVerdict;
|
|
15
|
+
|
|
16
|
+
export const OP_DECIDE_AGENT = 'seat-loop:OP';
|
|
17
|
+
export const OP_DECIDE_DELEGATION = '대표 10-06 COO 카드 거르기 규칙 · 10-07 범위 카드 기본 b(돈·보안·비밀·공개 경로만 유지)';
|
|
18
|
+
|
|
19
|
+
/** Categories that must reach the CEO whatever the recommendation says (rule 3). */
|
|
20
|
+
const FORBIDDEN_CATEGORIES: ReadonlySet<DecisionEntry['category']> = new Set(['money', 'security', 'secret', 'publish']);
|
|
21
|
+
const FORBIDDEN_WORDS = /특허|patent|외부\s*계약|계약서|contract/i;
|
|
22
|
+
|
|
23
|
+
/** Path segments that keep a scope card open — money · security · secret · public (rule 2 exception). */
|
|
24
|
+
const SENSITIVE_PATH: ReadonlyArray<{ kind: 'money' | 'security' | 'secret' | 'public'; pattern: RegExp }> = [
|
|
25
|
+
{ kind: 'secret', pattern: /(^|[/._-])(secrets?|credentials?|\.env|keychain|apns|backup-key)([/._-]|$)|\.(pem|p8|p12|key)$/i },
|
|
26
|
+
{ kind: 'security', pattern: /(^|[/._-])(auth|oauth|security|sandbox|permissions?|acl|csp|tokens?|crypto)([/._-]|$)/i },
|
|
27
|
+
{ kind: 'money', pattern: /(^|[/._-])(money|finance|billing|payments?|payouts?|refunds?|revenue|pricing|stripe|invoices?|checkout|wallet|trad(e|ing)|broker|budget|quota)([/._-]|$)/i },
|
|
28
|
+
{ kind: 'public', pattern: /(^|\/)(README|CHANGELOG|LICENSE|NOTICE)(\.[a-z]+)?$|(^|[/._-])(publish|public|homepage|site|npm)([/._-]|$)|^\.github\/workflows\/|^scripts\/release-loop\/release-publish/i },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export function sensitivePathKind(file: string): 'money' | 'security' | 'secret' | 'public' | undefined {
|
|
32
|
+
return SENSITIVE_PATH.find(({ pattern }) => pattern.test(file))?.kind;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const SCOPE_QUESTION = /outside the authored target paths/i;
|
|
36
|
+
|
|
37
|
+
/** Outside-file names listed on a harness scope card; undefined when the card carries no complete list. */
|
|
38
|
+
export function scopeOutsideFiles(card: Pick<DecisionEntry, 'pendingQuestion'>): string[] | undefined {
|
|
39
|
+
const text = card.pendingQuestion ?? '';
|
|
40
|
+
const at = text.indexOf('Outside files:');
|
|
41
|
+
if (at < 0) return undefined;
|
|
42
|
+
// «… N more outside file(s) not shown» anywhere after the list header — a hidden file cannot be vetted.
|
|
43
|
+
if (/more outside file/i.test(text.slice(at))) return undefined;
|
|
44
|
+
const lines = text.slice(at + 'Outside files:'.length).split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
45
|
+
const files: string[] = [];
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
if (!line.startsWith('- ')) break;
|
|
48
|
+
// «… N more outside file(s) not shown» — a hidden file cannot be vetted.
|
|
49
|
+
if (/more outside file/i.test(line)) return undefined;
|
|
50
|
+
const name = line.slice(2).replace(/\s+\(declared-path sibling test: [a-z]+\)$/, '').trim();
|
|
51
|
+
if (name) files.push(name);
|
|
52
|
+
}
|
|
53
|
+
return files.length ? files : undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function optionKey(card: DecisionEntry, label: RegExp): string | undefined {
|
|
57
|
+
return card.options.find((option) => label.test(option.label))?.key;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function isRepeatStopCard(card: DecisionEntry): boolean {
|
|
61
|
+
return card.raisedBy.agent === 'seat-loop' && / 반복 착지 0$/.test(card.title);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function isScopeCard(card: DecisionEntry): boolean {
|
|
65
|
+
return card.raisedBy.agent === 'harness' && (card.category === 'scope' || card.category === 'irreversible')
|
|
66
|
+
&& SCOPE_QUESTION.test(`${card.title}\n${card.pendingQuestion ?? ''}`) && !!card.resume;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Judge one open card. undefined = not this filter's card (left alone). */
|
|
70
|
+
export function judgeOpDecision(card: DecisionEntry, runOwner: (runId: string) => SeatId | undefined = () => undefined): OpDecideVerdict | undefined {
|
|
71
|
+
if (card.status !== 'open') return undefined;
|
|
72
|
+
const repeat = isRepeatStopCard(card);
|
|
73
|
+
const scope = isScopeCard(card);
|
|
74
|
+
const runId = card.resume?.runId;
|
|
75
|
+
if (!repeat && !scope && !runId) return undefined;
|
|
76
|
+
if (FORBIDDEN_CATEGORIES.has(card.category) || FORBIDDEN_WORDS.test(`${card.title}\n${card.scqa.s}`)) {
|
|
77
|
+
return { verdict: 'route', rule: 'forbidden', to: 'CEO', reason: `${card.category} 범주·금지 낱말 — 자동 결정 금지, 대표 카드로 남김` };
|
|
78
|
+
}
|
|
79
|
+
if (repeat) {
|
|
80
|
+
const stop = optionKey(card, /^멈춘다$/);
|
|
81
|
+
const recommended = 'option' in card.recommendation ? card.recommendation.option : undefined;
|
|
82
|
+
if (stop && recommended === stop) {
|
|
83
|
+
return { verdict: 'auto', rule: 'repeat-stop', choice: stop, reason: `반복 착지 0 — 권고 ${stop}(멈춘다) · 그냥 둔 것과 같은 결과` };
|
|
84
|
+
}
|
|
85
|
+
return { verdict: 'route', rule: 'repeat-stop', to: 'CEO', reason: '반복 정지 카드인데 권고가 «멈춘다»가 아님 — 확신 없음' };
|
|
86
|
+
}
|
|
87
|
+
if (scope) {
|
|
88
|
+
const expand = optionKey(card, /^Expand scope$/i);
|
|
89
|
+
const files = scopeOutsideFiles(card);
|
|
90
|
+
const owner = runId ? runOwner(runId) : undefined;
|
|
91
|
+
const route = (rule: OpDecideRule, reason: string): OpDecideVerdict =>
|
|
92
|
+
({ verdict: 'route', rule, to: owner && owner !== 'OP' ? owner : 'CEO', reason });
|
|
93
|
+
if (!expand) return route('scope-unknown', '범위 카드에 «Expand scope» 선택지가 없음');
|
|
94
|
+
if (!files) return route('scope-unknown', '바깥 파일 목록이 없거나 일부만 보임 — 경로를 확인 못 함');
|
|
95
|
+
const sensitive = files.map((file) => ({ file, kind: sensitivePathKind(file) })).filter((row) => row.kind);
|
|
96
|
+
if (sensitive.length) {
|
|
97
|
+
return { verdict: 'route', rule: 'scope-sensitive', to: 'CEO',
|
|
98
|
+
reason: `바깥 파일 중 ${sensitive[0]!.kind} 경로(${sensitive[0]!.file}${sensitive.length > 1 ? ` 외 ${sensitive.length - 1}` : ''}) — 유지 여부는 대표 판단` };
|
|
99
|
+
}
|
|
100
|
+
// Release/gate paths follow the release-path SSOT (src/self-dev/release-path-guard.ts) — never auto-widen; TC owns the gate.
|
|
101
|
+
// TODO(0.2.21 RELEASE-PATH-GUARD-GATE): src/task-orchestrator/surfaces/pod-command-job.ts and src/release-loop/gate-shards.ts
|
|
102
|
+
// are gate paths not yet in RELEASE_PATH_PREFIXES; they become covered here once that list grows.
|
|
103
|
+
const release = releasePathHold(files);
|
|
104
|
+
if (release) {
|
|
105
|
+
return { verdict: 'route', rule: 'scope-release-path', to: 'TC',
|
|
106
|
+
reason: `바깥 파일 중 발행·게이트 경로(${release}) — 게이트 주인 TC 판단` };
|
|
107
|
+
}
|
|
108
|
+
return { verdict: 'auto', rule: 'scope-expand', choice: expand,
|
|
109
|
+
reason: `범위 넓힘 b — 바깥 ${files.length}개 모두 돈·보안·비밀·공개 경로 아님 · 게이트·리뷰가 가린다` };
|
|
110
|
+
}
|
|
111
|
+
const owner = runOwner(runId!);
|
|
112
|
+
return { verdict: 'route', rule: 'run-blocking', to: owner && owner !== 'OP' ? owner : 'CEO',
|
|
113
|
+
reason: owner && owner !== 'OP' ? `런 ${runId} 을 막는 카드 — 런 주인 ${owner} 자리로` : `런 ${runId} 을 막는 카드 — 주인 자리 모름, 대표 카드로 남김` };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type OpDecideDeps = {
|
|
117
|
+
mode: OpDecideMode;
|
|
118
|
+
ledger: Pick<DecisionLedger, 'list' | 'decide'>;
|
|
119
|
+
runOwner?: (runId: string) => SeatId | undefined;
|
|
120
|
+
/** Route a run-blocking card to its owner seat (live only); returns false when delivery failed. */
|
|
121
|
+
routeToSeat?: (to: SeatId, card: DecisionEntry, reason: string) => boolean;
|
|
122
|
+
/** Candidates already recorded for this card (dedup across ticks). */
|
|
123
|
+
recorded?: (id: string) => readonly OpDecideCandidate[];
|
|
124
|
+
record: (candidate: OpDecideCandidate) => void;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** One filtering pass over open cards. Never throws for a single card; returns what it recorded. */
|
|
128
|
+
export function runOpDecide(deps: OpDecideDeps): OpDecideCandidate[] {
|
|
129
|
+
const out: OpDecideCandidate[] = [];
|
|
130
|
+
let cards: DecisionEntry[];
|
|
131
|
+
try { cards = deps.ledger.list({ status: 'open' }); }
|
|
132
|
+
catch (error) {
|
|
133
|
+
observeOpDecide({ event: 'ledger-unreadable', error: String(error).slice(0, 200) });
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
for (const card of cards) {
|
|
137
|
+
let judged: OpDecideVerdict | undefined;
|
|
138
|
+
try { judged = judgeOpDecision(card, deps.runOwner); }
|
|
139
|
+
catch (error) {
|
|
140
|
+
observeOpDecide({ event: 'judge-failed', id: card.id, error: String(error).slice(0, 200) });
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (!judged) continue;
|
|
144
|
+
const candidate: OpDecideCandidate = { kind: 'decision-filter', id: card.id, mode: deps.mode, ...judged };
|
|
145
|
+
const same = (row: OpDecideCandidate) => row.mode === candidate.mode && row.verdict === candidate.verdict && row.rule === candidate.rule
|
|
146
|
+
&& ('to' in row ? row.to : row.choice) === ('to' in candidate ? candidate.to : candidate.choice);
|
|
147
|
+
if ((deps.recorded?.(card.id) ?? []).some(same)) continue;
|
|
148
|
+
if (deps.mode === 'live' && candidate.verdict === 'auto') {
|
|
149
|
+
try {
|
|
150
|
+
deps.ledger.decide(card.id, candidate.choice,
|
|
151
|
+
{ kind: 'auto', agent: OP_DECIDE_AGENT, track: 'OP', delegation: OP_DECIDE_DELEGATION }, candidate.reason);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
observeOpDecide({ event: 'decide-failed', id: card.id, rule: candidate.rule, error: String(error).slice(0, 200) });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (deps.mode === 'live' && candidate.verdict === 'route' && candidate.to !== 'CEO' && deps.routeToSeat) {
|
|
158
|
+
let delivered = false;
|
|
159
|
+
try { delivered = deps.routeToSeat(candidate.to, card, candidate.reason); }
|
|
160
|
+
catch (error) { observeOpDecide({ event: 'route-failed', id: card.id, to: candidate.to, error: String(error).slice(0, 200) }); }
|
|
161
|
+
if (!delivered) continue;
|
|
162
|
+
}
|
|
163
|
+
deps.record(candidate);
|
|
164
|
+
out.push(candidate);
|
|
165
|
+
observeOpDecide({ event: 'op-decide', id: card.id, mode: candidate.mode, verdict: candidate.verdict, rule: candidate.rule,
|
|
166
|
+
...(candidate.verdict === 'auto' ? { choice: candidate.choice } : { to: candidate.to }), category: card.category, reason: candidate.reason });
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function observeOpDecide(data: Record<string, unknown>): void {
|
|
172
|
+
try { debug.log('seat.loop', 'op-decide', data); } catch { /* observation cannot change a decision */ }
|
|
173
|
+
}
|
|
@@ -26,6 +26,7 @@ import { answerCrossCheck, answerSeat, askCrossCheck, askSeat, crossCheckAnswer,
|
|
|
26
26
|
import { queryRunningRuns } from '../self-implement/running-runs.js';
|
|
27
27
|
import { checklistHistory, listChecklist, type Checklist } from '../release-loop/checklist.js';
|
|
28
28
|
import { readSchedules, releasedVersion } from '../release-loop/feature-store.js';
|
|
29
|
+
import { runOpDecide, type OpDecideCandidate } from './op-decide.js';
|
|
29
30
|
|
|
30
31
|
// `kind`/`createdAt` are the V3 shadow-compare keys (내부 문서 `METHOD-v3-shadow-compare-2026-10-02` · MK 10-02 18:54).
|
|
31
32
|
export type SeatItem = { source: 'request' | 'checklist' | 'hook' | 'seat-question'; kind?: 'request' | 'cell' | 'hook-task' | 'seat-question'; id: string; title: string; text: string; evidence?: string; status?: string; version?: string; seat?: string; evidenceHash?: string; asOf?: string; queuedAt?: string; createdAt?: string; from?: SeatId };
|
|
@@ -43,7 +44,7 @@ export type TcCandidate =
|
|
|
43
44
|
| { kind: 'publication-pr-approval-wait'; pr: number; title: string; readyAt: string; approvalWaitAt: string; paths: string[] }
|
|
44
45
|
| { kind: 'other-seat-cell-defect'; version: string; id: string; title: string; to: SeatId };
|
|
45
46
|
export type TcPullRequest = { number: number; title: string; body?: string; state: 'OPEN' | 'MERGED' | 'CLOSED'; isDraft: boolean; createdAt: string; updatedAt?: string; mergedAt?: string | null; readyAt?: string; approvalWaitAt?: string; paths?: string[]; reviewDecision?: string };
|
|
46
|
-
export type SeatEntry = { seat: string; ts?: string; at: string; modeDowngradeReason?: string; status: 'shadow' | 'attempting' | 'outcome-unknown' | 'queued' | 'refused' | 'held' | 'launched' | 'hitl' | 'wait' | 'asked' | 'answered' | 'awaiting-answer' | 'awaiting-xcheck' | 'awaiting-resolution' | 'resolved-by-neighbor' | 'resolved' | 'rejected-no-evidence' | 'skipped-budget' | 'skipped-empty'; item?: SeatItem; candidate?: OpCandidate | TcCandidate; action?: SeatAction; reason?: string; runId?: string; queueId?: string; inquiry?: SeatInquiry; answer?: string; escalated?: boolean; xcheckRequestedAt?: string; xcheckQuestionId?: number; xcheckNeighbor?: SeatId; xcheckNote?: string; xcheckJudgmentEvidence?: string; xcheckWaitMinutes?: number };
|
|
47
|
+
export type SeatEntry = { seat: string; ts?: string; at: string; modeDowngradeReason?: string; status: 'shadow' | 'attempting' | 'outcome-unknown' | 'queued' | 'refused' | 'held' | 'launched' | 'hitl' | 'wait' | 'asked' | 'answered' | 'awaiting-answer' | 'awaiting-xcheck' | 'awaiting-resolution' | 'resolved-by-neighbor' | 'resolved' | 'rejected-no-evidence' | 'skipped-budget' | 'skipped-empty'; item?: SeatItem; candidate?: OpCandidate | TcCandidate | OpDecideCandidate; action?: SeatAction; reason?: string; runId?: string; queueId?: string; inquiry?: SeatInquiry; answer?: string; escalated?: boolean; xcheckRequestedAt?: string; xcheckQuestionId?: number; xcheckNeighbor?: SeatId; xcheckNote?: string; xcheckJudgmentEvidence?: string; xcheckWaitMinutes?: number };
|
|
47
48
|
export type SeatLoopResult = SeatEntry | { seat: string; status: 'skipped-off'; modeDowngradeReason?: string };
|
|
48
49
|
|
|
49
50
|
export function seatLoopTickLine(result: SeatLoopResult): string {
|
|
@@ -99,6 +100,8 @@ export type SeatDeps = {
|
|
|
99
100
|
/** Judge a decision draft against the receiving seat's evidence; null leaves the request pending. */
|
|
100
101
|
crossCheck?: (seat: SeatId, draft: string, from: SeatId) => Promise<CrossCheckJudgment | null> | CrossCheckJudgment | null;
|
|
101
102
|
decisionsConfig?: UserConfig['decisions'];
|
|
103
|
+
/** OP-LOOP-DECIDE: who owns a run (for run-blocking cards). Default = today's seat ledgers' launched rows. */
|
|
104
|
+
runOwner?: (runId: string) => SeatId | undefined;
|
|
102
105
|
};
|
|
103
106
|
|
|
104
107
|
const repoRoot = resolve(import.meta.dir, '../..');
|
|
@@ -291,6 +294,8 @@ function personReopened(ledger: readonly SeatEntry[], seat: string, item: SeatIt
|
|
|
291
294
|
const ref = decisionRef(seat, item);
|
|
292
295
|
return new DecisionLedger({ stateDir: root }).list({ status: 'all' }).some((card) => {
|
|
293
296
|
if (!card.refs?.includes(ref) || card.status !== 'decided' || !card.decidedAt) return false;
|
|
297
|
+
// «멈춘다» on a repeat-stop card keeps the cell held — only a reopen (or any other card's decision) frees it (OP-LOOP-DECIDE).
|
|
298
|
+
if (/ 반복 착지 0$/.test(card.title) && card.options.find((option) => option.key === card.choice)?.label === '멈춘다') return false;
|
|
294
299
|
const decidedAt = Date.parse(card.decidedAt);
|
|
295
300
|
return Number.isFinite(decidedAt) && decidedAt > heldAt;
|
|
296
301
|
});
|
|
@@ -551,6 +556,40 @@ export async function gatherSeatInputs(seat: string, deps: SeatDeps = {}, ledger
|
|
|
551
556
|
return { requests: pending, checklist, role: read(join(deps.repo ?? repoRoot, 'docs', 'roles', `${seat}.md`)).slice(0, 4_000) };
|
|
552
557
|
}
|
|
553
558
|
|
|
559
|
+
/** OP-LOOP-DECIDE: filter open decision cards each OP turn. Shadow records; live decides/routes. A failure never blocks the turn. */
|
|
560
|
+
function opDecidePass(config: SeatLoopConfig, deps: SeatDeps, now: Date, path: string, stateRoot: string, ledger: readonly SeatEntry[]): void {
|
|
561
|
+
const mode = config.opDecide?.mode === 'live' ? 'live' : 'shadow';
|
|
562
|
+
let owners: Map<string, SeatId> | undefined;
|
|
563
|
+
try {
|
|
564
|
+
const append = deps.append ?? defaultAppend;
|
|
565
|
+
const recorded = new Map<string, OpDecideCandidate[]>();
|
|
566
|
+
for (const row of ledger) {
|
|
567
|
+
if (row.candidate?.kind === 'decision-filter') recorded.set(row.candidate.id, [...(recorded.get(row.candidate.id) ?? []), row.candidate]);
|
|
568
|
+
}
|
|
569
|
+
runOpDecide({
|
|
570
|
+
mode,
|
|
571
|
+
ledger: cardLedger(stateRoot, deps, now),
|
|
572
|
+
runOwner: deps.runOwner ?? ((runId) => {
|
|
573
|
+
owners ??= new Map((['OP', 'UX', 'MK', 'TC'] as const).flatMap((owner) =>
|
|
574
|
+
readSeatLedger(owner, deps, now).filter((row) => row.runId).map((row) => [row.runId!, owner] as const)));
|
|
575
|
+
return owners.get(runId);
|
|
576
|
+
}),
|
|
577
|
+
routeToSeat: (to, card, reason) => {
|
|
578
|
+
askSeat(stateRoot, 'OP', to, `결정 카드 ${card.id} «${card.title}» — ${reason}. 런 주인이 판단해 elanous decisions decide ${card.id} 로 닫아 주세요.`,
|
|
579
|
+
`op-decide:${card.id}:${to}`);
|
|
580
|
+
return true;
|
|
581
|
+
},
|
|
582
|
+
recorded: (id) => recorded.get(id) ?? [],
|
|
583
|
+
record: (candidate) => {
|
|
584
|
+
append(path, { seat: 'OP', ts: now.toISOString(), at: now.toISOString(),
|
|
585
|
+
status: mode === 'shadow' ? 'shadow' : candidate.verdict === 'auto' ? 'resolved' : 'hitl',
|
|
586
|
+
...(candidate.verdict === 'route' && candidate.to === 'CEO' ? { escalated: true } : {}),
|
|
587
|
+
candidate, reason: candidate.reason });
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
} catch (error) { observe('op-decide', { event: 'pass-failed', mode, error: String(error).slice(0, 200) }); }
|
|
591
|
+
}
|
|
592
|
+
|
|
554
593
|
const OP_CUTOFF_WINDOW_MS = 2 * 60 * 60_000;
|
|
555
594
|
const RUN_REFERENCE = /\brun-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
556
595
|
|
|
@@ -870,10 +909,25 @@ const SEAT_ACTION_RULES: ReadonlyArray<{ kind: 'wait' | 'harness' | 'decision';
|
|
|
870
909
|
{ kind: 'wait', signal: /실측\s*대기|(?:사람|실제)\s*기기(?!\s*(?:(?:실측|측정|확인)\s*)?완료)(?:\s*(?:실측|측정|확인|대기))?|실물\s*측정(?!\s*완료)/iu, source: 'content', resolvedBy: /(?:실측|측정|(?:사람|실제)\s*기기|실물\s*측정)\s*완료/iu },
|
|
871
910
|
{ kind: 'wait', signal: /\u{1F451}\s*확인\s*대기/iu, source: 'content', resolvedBy: /\u{1F451}\s*확인\s*완료/iu },
|
|
872
911
|
{ kind: 'decision', signal: TRACK_AGENT_FORBIDDEN_ACTION_REGEX, source: 'task' },
|
|
912
|
+
{ kind: 'decision', signal: /토큰\s*(?:을|를)?\s*(?:출력|노출|공개|첨부|붙여)/iu, source: 'task' },
|
|
873
913
|
{ kind: 'decision', signal: /(?:마켓|레지스트리)(?:에|로)?\s*(?:게시|등록|발행)|사이트\s*운영\s*반영|SNS(?:에|로)?\s*(?:게시|발행|업로드)|공개\s*발행/iu, source: 'task' },
|
|
874
914
|
{ kind: 'harness', signal: /(?:마켓|레지스트리|사이트|SNS|공개)?(?:에|로)?\s*(?:게시|발행|배포|등록|운영\s*반영)(?:를?\s*위한)?\s*(?:준비|초안|원고|자료|구현|점검|테스트)|(?:마켓|레지스트리|사이트|SNS|공개)?(?:에|로)?\s*(?:게시|발행|배포|등록)(?:용|를?\s*위한)\s*(?:초안|원고|자료|코드|기능)/iu, source: 'task' },
|
|
875
915
|
];
|
|
876
916
|
|
|
917
|
+
// SEAT-FORBID-NEGATION: «비밀 0» · «비밀 제외» · «no secret» name the word to exclude it, not to act on it.
|
|
918
|
+
// Only a negation right next to the hit (optionally after a short noun such as 키 · 증명 and a particle) clears it;
|
|
919
|
+
// «비밀 키를 붙여라» keeps its imperative and stays a decision.
|
|
920
|
+
const FORBID_NEGATION = '(?:0(?![\\dx.,])|제외|없이|빼고|금지|없음|none\\b|no\\b|without\\b|excluding\\b)';
|
|
921
|
+
const FORBID_NEGATION_AFTER = new RegExp(`^(?:\\s*(?:증명|정보|키|값|토큰|keys?|tokens?)(?![A-Za-z]))?\\s*(?:은|는|이|가|을|를|:)?\\s*${FORBID_NEGATION}`, 'iu');
|
|
922
|
+
const FORBID_NEGATION_BEFORE = /(?:^|[\s(\[«"'·,:])(?:no|without|excluding|none|제외|금지)\s*[:·-]?\s*$/iu;
|
|
923
|
+
|
|
924
|
+
export const FORBID_JUDGMENT_LINE = (word: string | undefined): string =>
|
|
925
|
+
`판정 근거: «${word ?? '?'}» 바로 앞뒤에 부정 문면(0·제외·없이·빼고·금지·없음·no·without·excluding)이 없어 실행 요청으로 봤다`;
|
|
926
|
+
|
|
927
|
+
export function forbiddenHitNegated(text: string, index: number, length: number): boolean {
|
|
928
|
+
return FORBID_NEGATION_AFTER.test(text.slice(index + length)) || FORBID_NEGATION_BEFORE.test(text.slice(0, index));
|
|
929
|
+
}
|
|
930
|
+
|
|
877
931
|
export function planAction(item: SeatItem, seat?: string): { kind: 'decision' | 'harness' | 'wait'; text: string; reason?: string } {
|
|
878
932
|
const task = `${item.id}\n${item.title}\n${item.text}`;
|
|
879
933
|
const content = `${task}\n${item.evidence ?? ''}`;
|
|
@@ -884,7 +938,9 @@ export function planAction(item: SeatItem, seat?: string): { kind: 'decision' |
|
|
|
884
938
|
if (resolvedBy?.test(item.evidence ?? '')) return null;
|
|
885
939
|
const hits = [...text.matchAll(new RegExp(signal.source, `${signal.flags.replace('g', '')}g`))];
|
|
886
940
|
const hit = kind === 'decision' ? hits.find((match) => !prepared.some((prep) =>
|
|
887
|
-
match.index! >= prep.index! && match.index! + match[0].length <= prep.index! + prep[0].length)
|
|
941
|
+
match.index! >= prep.index! && match.index! + match[0].length <= prep.index! + prep[0].length)
|
|
942
|
+
&& !(forbiddenHitNegated(text, match.index!, match[0].length)
|
|
943
|
+
&& (observe('forbid-negated', { item: item.id, word: match[0] }), true))) : hits[0];
|
|
888
944
|
return hit ? { kind, reason: hit[0] } : null;
|
|
889
945
|
}).find((hit) => hit !== null);
|
|
890
946
|
const kind = rule?.kind ?? 'harness';
|
|
@@ -1004,6 +1060,7 @@ export async function runSeatLoopOnce(seat: string, deps: SeatDeps = {}): Promis
|
|
|
1004
1060
|
} catch (error) { observe('heartbeat-write-failed', { seat, error: String(error).slice(0, 200) }); }
|
|
1005
1061
|
const recorded = readSeatLedger(seat, deps, now);
|
|
1006
1062
|
const ledger = config.mode === 'live-safe' ? reconciledQueueLedger(recorded, stateRoot, deps) : recorded;
|
|
1063
|
+
if (seat === 'OP') opDecidePass(config, deps, now, path, stateRoot, ledger);
|
|
1007
1064
|
let turnError: unknown;
|
|
1008
1065
|
try {
|
|
1009
1066
|
if (config.mode === 'on' && config.questions === 'on') {
|
|
@@ -1494,7 +1551,7 @@ export async function runSeatLoopOnce(seat: string, deps: SeatDeps = {}): Promis
|
|
|
1494
1551
|
: undefined;
|
|
1495
1552
|
} catch (error) { observe('decision-source-unreadable', { seat, item: item.id, error: String(error).slice(0, 200) }); }
|
|
1496
1553
|
const material = decisionCardMaterial({ what: `${seat} 배정 항목: ${item.title} 역할: ${inputs.role || '역할 근거 없음'}`, soFar: `요청 내용: ${item.text}`,
|
|
1497
|
-
current: `밑바탕 재측: ${currentStatus ?? '상태 미확인'}; 요청에서 금지 문면 «${action.reason}» 발견 — 실행 전 사람 승인
|
|
1554
|
+
current: `밑바탕 재측: ${currentStatus ?? '상태 미확인'}; 요청에서 금지 문면 «${action.reason}» 발견 — 실행 전 사람 승인 필요; ${FORBID_JUDGMENT_LINE(action.reason)}`,
|
|
1498
1555
|
question: `금지 문면 «${action.reason}»이 걸린 요청을 승인할까?`, answer: '승인 전에는 집행하지 않고 보류한다',
|
|
1499
1556
|
options, recommendation, confidence: '높음 — 요청에 금지 문면 직접 일치',
|
|
1500
1557
|
ifUntouched: '자동 집행되지 않고 해당 칸은 보류 상태로 남는다',
|
|
@@ -6,6 +6,7 @@ import { promisify } from 'node:util';
|
|
|
6
6
|
import { debug } from '../debug/log.js';
|
|
7
7
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
8
8
|
import { getUserConfig, type SeatLoopConfig } from '../user-config.js';
|
|
9
|
+
import { collectDraftMetrics, collectOverlapMetrics, countSalvagedToday, type DraftMetrics, type OverlapMetrics } from '../self-dev/draft-sweep.js';
|
|
9
10
|
import { seatDay, seatLedgerPath, type OpCandidate, type SeatEntry } from './seat-loop.js';
|
|
10
11
|
|
|
11
12
|
export type SeatReportDeps = {
|
|
@@ -16,6 +17,10 @@ export type SeatReportDeps = {
|
|
|
16
17
|
config?: SeatLoopConfig;
|
|
17
18
|
post?: boolean;
|
|
18
19
|
send?: (body: string, seat: string, pr: number) => Promise<void> | void;
|
|
20
|
+
draftMetrics?: (now: Date) => Promise<DraftMetrics>;
|
|
21
|
+
overlapMetrics?: (now: Date) => Promise<OverlapMetrics>;
|
|
22
|
+
/** DRAFT-NOT-ARCHIVE salvage branches since the KST day start; null = unreadable. */
|
|
23
|
+
salvagedToday?: (dayStart: Date, now: Date) => Promise<number | null>;
|
|
19
24
|
};
|
|
20
25
|
export type SeatReportResult = { seat: string; date: string; body: string; posted: boolean };
|
|
21
26
|
const repoRoot = resolve(import.meta.dir, '../..');
|
|
@@ -36,6 +41,21 @@ function opJudgment(candidate: OpCandidate): { kind: 'card' | 'todo'; text: stri
|
|
|
36
41
|
text: `${text} (${candidate.category ?? '범주 없음'})` };
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
/** OVERLAP-METRIC line; ⛔ an unmeasured value says so instead of printing 0. */
|
|
45
|
+
function overlapLine(metrics: OverlapMetrics): string {
|
|
46
|
+
if (metrics.sourceIncomplete || metrics.launches24h === null) return ' · 겹침 발사 24h 못 잼(원천 불완전)';
|
|
47
|
+
const launched = metrics.launched === null ? '' : metrics.unmeasured
|
|
48
|
+
? ` 이상 (발사 ${metrics.launched} 중 ${metrics.unmeasured} 못 잼)` : ` (발사 ${metrics.launched})`;
|
|
49
|
+
const rate = metrics.autoRate === null || metrics.linked === null || metrics.autoLanded === null
|
|
50
|
+
? (metrics.linked === 0 ? '표본 없음' : '못 잼')
|
|
51
|
+
: `${(metrics.autoRate * 100).toFixed(1)}% (${metrics.autoLanded}/${metrics.linked})`;
|
|
52
|
+
const median = metrics.secondSiblingMedianHours === null ? (metrics.linked === null ? '못 잼' : '표본 없음')
|
|
53
|
+
: `${metrics.secondSiblingMedianHours.toFixed(1)}h`;
|
|
54
|
+
const salvage = (metrics.salvaged ? ` · 수확 가지 형제 ${metrics.salvaged}(미착지)` : '')
|
|
55
|
+
+ (metrics.salvageUnmeasured ? ` · 수확 가지 ${metrics.salvageUnmeasured} 못 잼` : '');
|
|
56
|
+
return ` · 겹침 발사 24h ${metrics.launches24h}${launched} · 겹침 자동 착지 ${rate} · 둘째 형제 착지 중앙값 ${median}${salvage}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
39
59
|
async function defaultSend(body: string, seat: string, pr: number, repo: string): Promise<void> {
|
|
40
60
|
const dir = mkdtempSync(join(tmpdir(), 'seat-report-'));
|
|
41
61
|
try {
|
|
@@ -58,8 +78,13 @@ export async function seatReport(seat: string, deps: SeatReportDeps = {}): Promi
|
|
|
58
78
|
// One line per item, its last state wins: an `attempting` row followed by `launched` is not «unconfirmed».
|
|
59
79
|
const latest = new Map<string, SeatEntry>();
|
|
60
80
|
const judgments = new Map<string, OpCandidate>();
|
|
81
|
+
const filtered = { auto: 0, route: 0 };
|
|
61
82
|
for (const entry of entries) {
|
|
62
|
-
if (
|
|
83
|
+
if (entry.candidate?.kind === 'decision-filter') {
|
|
84
|
+
filtered[entry.candidate.verdict] += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (seat === 'OP' && entry.candidate && 'verdict' in entry.candidate) {
|
|
63
88
|
if (entry.candidate.verdict === 'none') {
|
|
64
89
|
if (entry.candidate.id) {
|
|
65
90
|
const key = entry.candidate.kind === 'unassigned-cell'
|
|
@@ -89,8 +114,38 @@ export async function seatReport(seat: string, deps: SeatReportDeps = {}): Promi
|
|
|
89
114
|
return `건너뜀 ${entry.status} ${label}`;
|
|
90
115
|
});
|
|
91
116
|
const classified = [...judgments.values()].map(opJudgment).filter((row): row is NonNullable<typeof row> => row !== null);
|
|
92
|
-
const opDetail = classified.length ? ` · 결정 카드 후보: ${classified.filter((row) => row.kind === 'card').map((row) => row.text).join(' / ') || '없음'} · OP 가 할 일: ${classified.filter((row) => row.kind === 'todo').map((row) => row.text).join(' / ') || '없음'}` : ''
|
|
93
|
-
|
|
117
|
+
const opDetail = (classified.length ? ` · 결정 카드 후보: ${classified.filter((row) => row.kind === 'card').map((row) => row.text).join(' / ') || '없음'} · OP 가 할 일: ${classified.filter((row) => row.kind === 'todo').map((row) => row.text).join(' / ') || '없음'}` : '')
|
|
118
|
+
+ (filtered.auto + filtered.route ? ` · 카드 거르기: 자동 ${filtered.auto} · 넘김 ${filtered.route}` : '');
|
|
119
|
+
let draftDetail = '';
|
|
120
|
+
if (seat === 'OP') {
|
|
121
|
+
try {
|
|
122
|
+
const metrics = await (deps.draftMetrics ?? (async (clock: Date) => {
|
|
123
|
+
const [{ resolveRepositoryName }, { githubDraftSweepAdapters }] = await Promise.all([
|
|
124
|
+
import('../harness/repository-name.js'), import('../harness/harness-cli-command.js'),
|
|
125
|
+
]);
|
|
126
|
+
return collectDraftMetrics(resolveRepositoryName({}), githubDraftSweepAdapters(), clock);
|
|
127
|
+
}))(now);
|
|
128
|
+
draftDetail = ` · draft 재고 ${metrics.inventory} · 최장 나이 ${metrics.oldestAgeHours === null ? '해당 없음' : `${metrics.oldestAgeHours.toFixed(1)}h`} · needs-owner ${metrics.needsOwner} · 48h 전환율 ${metrics.conversion48h === null ? '표본 없음' : `${(metrics.conversion48h * 100).toFixed(1)}% (${metrics.converted48h}/${metrics.cohort48h})`}`;
|
|
129
|
+
} catch { draftDetail = ' · draft 지표 못 읽음'; }
|
|
130
|
+
try {
|
|
131
|
+
const overlap = await (deps.overlapMetrics ?? (async (clock: Date) => {
|
|
132
|
+
const [{ resolveRepositoryName }, { githubDraftSweepAdapters }, { readAskPreflightRowsSince, readSalvagedRowsSince }] = await Promise.all([
|
|
133
|
+
import('../harness/repository-name.js'), import('../harness/harness-cli-command.js'), import('../self-dev/ask-launch-io.js'),
|
|
134
|
+
]);
|
|
135
|
+
return collectOverlapMetrics(resolveRepositoryName({}), { ...githubDraftSweepAdapters(), listPreflightRows: readAskPreflightRowsSince, listSalvagedRows: readSalvagedRowsSince }, clock);
|
|
136
|
+
}))(now);
|
|
137
|
+
draftDetail += overlapLine(overlap);
|
|
138
|
+
} catch { draftDetail += ' · 겹침 지표 못 읽음'; }
|
|
139
|
+
let salvagedToday: number | null = null;
|
|
140
|
+
try {
|
|
141
|
+
salvagedToday = await (deps.salvagedToday ?? (async (dayStart: Date, clock: Date) => {
|
|
142
|
+
const { readSalvagedRowsSince } = await import('../self-dev/ask-launch-io.js');
|
|
143
|
+
return countSalvagedToday(await readSalvagedRowsSince(dayStart), dayStart, clock);
|
|
144
|
+
}))(new Date(`${date}T00:00:00+09:00`), now);
|
|
145
|
+
} catch { salvagedToday = null; }
|
|
146
|
+
draftDetail += ` · 수확 가지 오늘 ${salvagedToday === null ? '못 잼' : salvagedToday}`;
|
|
147
|
+
}
|
|
148
|
+
const body = `**[${seat}]** {{TS}} → 보고 ${date}: ${detail.join(' · ') || (classified.length ? 'OP 그림자 판단' : '원장 기록 없음')}${opDetail}${draftDetail}`;
|
|
94
149
|
const pr = (deps.config ?? getUserConfig().loops?.seat)?.reportPr;
|
|
95
150
|
const posted = deps.post === true && pr !== undefined;
|
|
96
151
|
if (posted) await (deps.send ?? ((text, id, number) => defaultSend(text, id, number, deps.repo ?? repoRoot)))(body, seat, pr);
|
|
@@ -852,7 +852,7 @@ export async function runAskLaunchFlow(
|
|
|
852
852
|
if (launchPreflight === false) return { kind: 'stopped-before-authoring' };
|
|
853
853
|
|
|
854
854
|
await deps.beforeAuthoring?.();
|
|
855
|
-
const authorAndPreflight = async (authorAskText: string = input.askText): Promise<{
|
|
855
|
+
const authorAndPreflight = async (authorAskText: string = input.askText, machineSuggestedTargetPaths: readonly string[] = []): Promise<{
|
|
856
856
|
readonly goalFile: string;
|
|
857
857
|
readonly decision: ReturnType<typeof decideAskPreflight>;
|
|
858
858
|
}> => {
|
|
@@ -950,6 +950,8 @@ export async function runAskLaunchFlow(
|
|
|
950
950
|
recentChangeWindowDays: input.recentChangeWindowDays,
|
|
951
951
|
openPrsLimit: OPEN_PR_LIMIT,
|
|
952
952
|
...(askOutsidePathHints.length > 0 ? { askOutsidePathHints } : {}),
|
|
953
|
+
// AUTO-TARGET: paths injected by the candidate search (not written in the ask) — a NOT-GROUNDED goal stops on them.
|
|
954
|
+
...(machineSuggestedTargetPaths.length > 0 ? { machineSuggestedTargetPaths } : {}),
|
|
953
955
|
declaredPathsRoot: deps.cwd(),
|
|
954
956
|
},
|
|
955
957
|
preflightDeps,
|
|
@@ -1026,12 +1028,13 @@ export async function runAskLaunchFlow(
|
|
|
1026
1028
|
...(candidates.error === undefined ? {} : { error: candidates.error }),
|
|
1027
1029
|
}, candidates.error === undefined ? 'info' : 'warn');
|
|
1028
1030
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
+
const selectedPaths = candidates.paths.slice(0, 1);
|
|
1032
|
+
if (selectedPaths.length > 0) {
|
|
1033
|
+
deps.print(`[ask] ⑴ 코드에서 후보 경로 ${selectedPaths.length}개를 찾아 넣고 다시 저작한다: ${selectedPaths.join(' · ')}`);
|
|
1031
1034
|
}
|
|
1032
|
-
authored = await authorAndPreflight(
|
|
1033
|
-
? `대상 경로: ${
|
|
1034
|
-
: input.askText);
|
|
1035
|
+
authored = await authorAndPreflight(selectedPaths.length > 0
|
|
1036
|
+
? `대상 경로: ${selectedPaths.join(' · ')}\n${input.askText}`
|
|
1037
|
+
: input.askText, selectedPaths);
|
|
1035
1038
|
deps.log('ask-auto-reauthor', {
|
|
1036
1039
|
candidatePathCount: candidates.paths.length,
|
|
1037
1040
|
firstGoalFile: first.goalFile,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// 72차 판이 복제를 금지했으므로 여기로 옮긴다. CLI 와 TUI 가 «같은 조회»를 쓴다.
|
|
6
6
|
// ⛔ 판정은 여기 없다 — 여기는 「무엇을 조회하는가」뿐이고, 「그래서 막나」는 launch-preflight 가 정한다.
|
|
7
7
|
import { execFileSync } from 'node:child_process';
|
|
8
|
-
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { readFileSync, realpathSync } from 'node:fs';
|
|
9
9
|
import {
|
|
10
10
|
parseAskTargetPathHints,
|
|
11
11
|
parseAskTargetPathHintsResult,
|
|
@@ -97,7 +97,7 @@ function inspectLaunchingTree(cwd: string): LaunchingTreeProbe {
|
|
|
97
97
|
|
|
98
98
|
/** 발사 전 검사가 쓰는 조회 구현 — ⛔ 이 «한 벌»을 모든 표면이 공유한다. */
|
|
99
99
|
export async function buildAskPreflightDeps(options: BuildAskPreflightDepsOptions = {}): Promise<AskPreflightDeps & { inspectLaunchingTree(cwd: string): LaunchingTreeProbe }> {
|
|
100
|
-
const [{ tracedPathReferences, verbatimOriginalAsk }, { loadRunLedger, queryFederatedCompletedRunLedgers, queryFederatedInterruptedRunLedgers, queryFederatedUnfinishedRunLedgers }] = await Promise.all([
|
|
100
|
+
const [{ tracedPathReferences, verbatimOriginalAsk, isNotGroundedWithoutPersistentEvidence }, { loadRunLedger, queryFederatedCompletedRunLedgers, queryFederatedInterruptedRunLedgers, queryFederatedUnfinishedRunLedgers }] = await Promise.all([
|
|
101
101
|
import('../self-implement/goal-author.js'),
|
|
102
102
|
import('../self-implement/run-ledger.js'),
|
|
103
103
|
]);
|
|
@@ -166,6 +166,8 @@ export async function buildAskPreflightDeps(options: BuildAskPreflightDepsOption
|
|
|
166
166
|
// ⛔ ask 표지가 없으면 빈 배열 — 그때는 표시가 «안 붙는다»(지어내지 않는다).
|
|
167
167
|
askTargetPaths: (document: string) => parseAskTargetPathHints(verbatimOriginalAsk(document) ?? ''),
|
|
168
168
|
askTargetPathRejections: (document: string) => parseAskTargetPathHintsResult(verbatimOriginalAsk(document) ?? '').rejected,
|
|
169
|
+
// AUTO-TARGET: a NOT-GROUNDED goal (no persistent evidence) is a scope card — machine-suggested paths do not launch it.
|
|
170
|
+
notGroundedWithoutPersistentEvidence: isNotGroundedWithoutPersistentEvidence,
|
|
169
171
|
// ⭐ 충돌 문면이 경로마다 「대상/근거」를 말하게 한다 — 판정은 «안» 바꾼다(문면만 는다).
|
|
170
172
|
// ⛔ TRACED PATHS 는 「바꿀 파일」과 「근거로 읽은 파일」을 섞는다(실측: TRACED 8 · 변경 3).
|
|
171
173
|
// ⇒ 사람이 막혔을 때 「그게 근거였네」를 «즉시» 알 수 있어야 한다.
|
|
@@ -300,6 +302,54 @@ export async function readAskPreflightLogRows(): Promise<AskLogRow[] | null> {
|
|
|
300
302
|
} catch { return null; }
|
|
301
303
|
}
|
|
302
304
|
|
|
305
|
+
/** Every `ask-preflight` row since `since`, all universes, paged past the 1000-row cap (OVERLAP-METRIC).
|
|
306
|
+
* ⛔ Unreadable ⇒ `null` — never an empty list that reads as «no overlap launches». */
|
|
307
|
+
export async function readAskPreflightRowsSince(since: Date): Promise<AskLogRow[] | null> {
|
|
308
|
+
return readLogRowsSince(since, 'dev-pipeline', 'ask-preflight');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** Every DRAFT-NOT-ARCHIVE `salvaged` row since `since`, all universes (OVERLAP-METRIC salvage siblings).
|
|
312
|
+
* ⛔ Unreadable ⇒ `null` — a salvage branch we could not see is «unmeasured», not «none». */
|
|
313
|
+
export async function readSalvagedRowsSince(since: Date): Promise<AskLogRow[] | null> {
|
|
314
|
+
return readLogRowsSince(since, 'self-implement.draft-not-archive', 'salvaged');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function readLogRowsSince(since: Date, category: string, event: string): Promise<AskLogRow[] | null> {
|
|
318
|
+
try {
|
|
319
|
+
const [{ resolveLogTargets }, { LogStore }] = await Promise.all([
|
|
320
|
+
import('../cli/logs-cli.js'),
|
|
321
|
+
import('../mss/logging/log-store.js'),
|
|
322
|
+
]);
|
|
323
|
+
const { targets } = resolveLogTargets({ all: true, includeTest: true });
|
|
324
|
+
const rows: AskLogRow[] = [];
|
|
325
|
+
// ⛔ One store can be registered under two names (`~/.monad` → `~/.elanous` symlink) — read each real file once,
|
|
326
|
+
// or every prod row is counted twice (OVERLAP-METRIC 실측: 169 행 중 69 가 같은 prod 파일의 겹침).
|
|
327
|
+
const seen = new Set<string>();
|
|
328
|
+
for (const target of targets) {
|
|
329
|
+
let real = target.dbPath;
|
|
330
|
+
try { real = realpathSync(target.dbPath); } catch { /* missing store: LogStore below decides */ }
|
|
331
|
+
if (seen.has(real)) continue;
|
|
332
|
+
seen.add(real);
|
|
333
|
+
const store = new LogStore(target.dbPath, { readonly: true });
|
|
334
|
+
try {
|
|
335
|
+
let beforeId: number | undefined;
|
|
336
|
+
for (let page = 0; page < 100; page++) {
|
|
337
|
+
const batch = store.query({ exactCategories: [category], events: [event], sinceMs: since.getTime(),
|
|
338
|
+
limit: 1_000, ...(beforeId === undefined ? {} : { beforeId }) });
|
|
339
|
+
for (const row of batch) {
|
|
340
|
+
const parsed = typeof row.data === 'string' ? JSON.parse(row.data) : row.data;
|
|
341
|
+
rows.push({ ts: row.ts, data: (parsed ?? null) as Record<string, unknown> | null });
|
|
342
|
+
}
|
|
343
|
+
if (batch.length < 1_000) break;
|
|
344
|
+
if (page === 99) return null;
|
|
345
|
+
beforeId = batch.at(-1)!.id;
|
|
346
|
+
}
|
|
347
|
+
} finally { store.close?.(); }
|
|
348
|
+
}
|
|
349
|
+
return rows;
|
|
350
|
+
} catch { return null; }
|
|
351
|
+
}
|
|
352
|
+
|
|
303
353
|
const stringList = (value: unknown): string[] =>
|
|
304
354
|
Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === 'string') : [];
|
|
305
355
|
|
|
@@ -14,6 +14,43 @@ export type AskPathCandidates =
|
|
|
14
14
|
const STOP_WORDS = new Set(['the', 'and', 'test', 'src', 'scripts', 'file', 'path', 'paths', 'code', 'with', 'from', 'this', 'that', 'into', 'for', 'then', 'when', 'have', 'does', 'should', 'will', 'please', 'target', 'change']);
|
|
15
15
|
const WORD = /[-/]?[A-Za-z][A-Za-z0-9_.-]*(?:\/[A-Za-z0-9_.-]+)*/g;
|
|
16
16
|
|
|
17
|
+
// ⛔ AUTO-TARGET (10-08 실측 · `ask-auto-target-candidates` Pod 로그): 한글 ask 에서 영문 낱말은 거의
|
|
18
|
+
// «포장»뿐이었다 — 디스패처 머리 `[UX · 0.2.20 칸 <ID> · TASK-AGENT(OP 디스패처)]` ⊕ Pod 샤드 꼬리
|
|
19
|
+
// `## Shard identity {"shardId","totalShards","position","summary","siblings"}` ⊕ `## Working-memory handoff`.
|
|
20
|
+
// 그 낱말들이 하니스 파일(orchestrate.ts · orchestrator.ts · self-implement-pod.ts · index.ts)을 끌어와
|
|
21
|
+
// 네 칸이 엉뚱한 골로 저작됐다. ⇒ 포장을 «증거»에서 걷고, 남는 것이 없으면 «후보 없음»(=근거 없음)을 낸다.
|
|
22
|
+
/** Machine-appended sections whose words describe the transport, not the request. */
|
|
23
|
+
const WRAPPER_SECTION_HEADINGS = new Set(['shard identity', 'working-memory handoff']);
|
|
24
|
+
/** Dispatcher wrapper lines that are identical for every card. */
|
|
25
|
+
const WRAPPER_LINE = /^\s*(?:보존 계약|판정)\s*:/;
|
|
26
|
+
/** Dispatcher header `[OWNER · <ver> 칸 <ID> · …]` — the title after it is kept. */
|
|
27
|
+
const WRAPPER_HEADER = /^\s*\[[^\]\n]*칸[^\]\n]*\]\s*/;
|
|
28
|
+
/** Dispatcher evidence label — the evidence itself is kept. */
|
|
29
|
+
const WRAPPER_LABEL = /^\s*칸 근거 끝\(남은 것\)\s*:\s*/;
|
|
30
|
+
/** Seat/role/surface words and similar labels that name the process, not the code. */
|
|
31
|
+
const GENERIC_TOKENS = new Set(['task-agent', 'op', 'mk', 'tc', 'ux', 'ceo', 'coo', 'cmo', 'cto', 'cxo', 'pr', 'prs', 'pod', 'tui', 'pwa', 'cli', 'hitl', 'p0', 'p1', 'p2']);
|
|
32
|
+
|
|
33
|
+
function isGenericToken(token: string): boolean {
|
|
34
|
+
const lower = token.toLowerCase().replace(/[.]+$/, '');
|
|
35
|
+
if (GENERIC_TOKENS.has(lower)) return true;
|
|
36
|
+
if (/^v?\d+(?:\.\d+)+(?:-[a-z0-9.]+)?$/i.test(lower)) return true; // version strings
|
|
37
|
+
if (/^[0-9a-f]{7,40}$/.test(lower) && /\d/.test(lower)) return true; // commit shas
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Remove dispatcher/Pod wrapper text so only the request body counts as lexical evidence. */
|
|
42
|
+
export function stripAskWrapper(askText: string): string {
|
|
43
|
+
const kept: string[] = [];
|
|
44
|
+
let skipping = false;
|
|
45
|
+
for (const line of askText.split(/\r?\n/)) {
|
|
46
|
+
const heading = /^##\s+(.+?)\s*$/.exec(line);
|
|
47
|
+
if (heading) skipping = WRAPPER_SECTION_HEADINGS.has(heading[1]!.toLowerCase());
|
|
48
|
+
if (skipping || WRAPPER_LINE.test(line)) continue;
|
|
49
|
+
kept.push(line.replace(WRAPPER_HEADER, '').replace(WRAPPER_LABEL, ''));
|
|
50
|
+
}
|
|
51
|
+
return kept.join('\n');
|
|
52
|
+
}
|
|
53
|
+
|
|
17
54
|
function existingFile(fragment: string, cwd: string): string | null {
|
|
18
55
|
const path = fragment.replace(/^\.\//, '');
|
|
19
56
|
if (!path.includes('/') && !/\.[A-Za-z][A-Za-z0-9]*$/.test(path)) return null;
|
|
@@ -29,7 +66,8 @@ export function findAskPathCandidates(askText: string, { cwd, run = execFileSync
|
|
|
29
66
|
const scores = new Map<string, Set<string>>();
|
|
30
67
|
const tokens: string[] = [];
|
|
31
68
|
const seen = new Set<string>();
|
|
32
|
-
const
|
|
69
|
+
const body = stripAskWrapper(askText);
|
|
70
|
+
const chunks = [...body.matchAll(/`([^`]+)`/g)].map((match) => match[1]!).concat([body]);
|
|
33
71
|
for (const chunk of chunks) {
|
|
34
72
|
for (const match of chunk.matchAll(WORD)) {
|
|
35
73
|
const raw = match[0];
|
|
@@ -40,7 +78,7 @@ export function findAskPathCandidates(askText: string, { cwd, run = execFileSync
|
|
|
40
78
|
hits.add(token);
|
|
41
79
|
scores.set(file, hits);
|
|
42
80
|
}
|
|
43
|
-
if (STOP_WORDS.has(token.toLowerCase()) || seen.has(token)) continue;
|
|
81
|
+
if (STOP_WORDS.has(token.toLowerCase()) || isGenericToken(token) || seen.has(token)) continue;
|
|
44
82
|
if (!file && !token.includes('/') && !token.includes('.') && !token.includes('-') && !token.includes('_')
|
|
45
83
|
&& !/[a-z][A-Z]/.test(token) && token.length < 4) continue;
|
|
46
84
|
seen.add(token);
|