elanous 0.2.24 → 0.2.27
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/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
- package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
- package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/release-loop.yaml +5 -5
- package/graphs/steward/recipes.yaml +4 -0
- package/graphs/steward/steward.yaml +10 -1
- package/package.json +1 -1
- package/scripts/bench-report.ts +46 -1
- package/scripts/ci-typecheck-changed.ts +88 -7
- package/scripts/coord-msg-bridge.ts +209 -0
- package/scripts/coord-post.sh +40 -7
- package/scripts/coord-requests-bridge.ts +10 -5
- package/scripts/expose-rubric-suggest.ts +1 -1
- package/scripts/measure-tsc-affected-roots.ts +10 -1
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- package/scripts/release-loop/export-check-node.ts +8 -5
- package/scripts/release-loop/gate-closure.ts +286 -0
- package/scripts/release-loop/gate-node.ts +73 -13
- package/scripts/release-loop/gate-partial.ts +34 -6
- package/scripts/release-loop/node-verdict.ts +7 -2
- package/scripts/release-loop/ops-upgrade-node.ts +63 -42
- package/scripts/release-loop/publish-node.ts +6 -0
- package/scripts/release-loop/resume-release.ts +37 -10
- package/scripts/release-loop/resume.ts +69 -4
- package/scripts/tsc-baseline-cache.ts +28 -3
- package/scripts/usage-rollup.ts +27 -13
- package/scripts/ux-sim.ts +30 -1
- package/skills/youtube-master/scripts/main.ts +4 -1
- package/skills/youtube-master/src/obsidian.ts +9 -0
- package/src/agent/task-notification.ts +30 -1
- package/src/agent-substrate/acp-implementer.ts +14 -7
- package/src/agent-substrate/pr-reviewer.ts +30 -10
- package/src/agent-substrate/review-observation.ts +9 -2
- package/src/agent-substrate/self-review-cli.ts +154 -16
- package/src/boot/daemon-tools/self-implement.ts +72 -4
- package/src/budget/cost-tier-advisor.ts +91 -0
- package/src/budget/llm-cost.ts +5 -1
- package/src/budget/shadow-arms.ts +77 -0
- package/src/budget/types.ts +5 -3
- package/src/budget/unified-usage.ts +172 -8
- package/src/cli/control-cli.ts +29 -0
- package/src/cli/doctor-cli.ts +106 -3
- package/src/cli/friendly-errors.ts +113 -0
- package/src/cli/intake-cli.ts +3 -1
- package/src/cli/memory-cli.ts +182 -0
- package/src/cli/model-watch-cli.ts +4 -1
- package/src/cli/msg-cli.ts +15 -5
- package/src/cli/pr-cli.ts +53 -0
- package/src/cli/pr-land-overlap-evidence.ts +18 -10
- package/src/cli/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +41 -12
- package/src/cli/release-run-if-ready.ts +11 -0
- package/src/cli/resource-cli.ts +48 -0
- package/src/cli/retro-cli.ts +12 -3
- package/src/cli/seat-cli.ts +121 -0
- package/src/cli/seat-requests-cli.ts +25 -0
- package/src/cli/self-utterances-cli.ts +140 -0
- package/src/cli/tasks-cli.ts +168 -14
- package/src/cli/usage-cli.ts +3 -1
- package/src/compact/verify-probe.ts +23 -3
- package/src/context-card/cell.ts +40 -0
- package/src/context-card/index.ts +50 -0
- package/src/control/control-status.ts +30 -1
- package/src/dashboard/boot-timing.ts +35 -0
- package/src/dashboard/index.ts +86 -24
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/debug/log-diet.ts +16 -4
- package/src/debug/log.ts +1 -1
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +29 -8
- package/src/domains/surface-events.ts +16 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +446 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/runner.ts +12 -6
- package/src/graph-wizard/archetypes.ts +14 -8
- package/src/graph-wizard/generate.ts +77 -1
- package/src/grok.ts +13 -7
- package/src/harness/harness-cli-command.ts +102 -51
- package/src/harness/harness-stop.ts +93 -19
- package/src/index.ts +52 -179
- package/src/instance/current.ts +2 -6
- package/src/instance/resolve.ts +5 -6
- package/src/intake-plane/collect-github.ts +7 -2
- package/src/intake-plane/lens.ts +46 -4
- package/src/intake-plane/requirement-funnel.ts +53 -1
- package/src/intelligence-map/catalog-feed.ts +119 -0
- package/src/intelligence-map/model-watch-intake.ts +40 -0
- package/src/intelligence-map/model-watch-mission.ts +14 -1
- package/src/llm/open-weight-discipline.ts +21 -0
- package/src/llm/openai-sampling-fields.ts +89 -0
- package/src/llm/runtime-model-family.ts +61 -0
- package/src/llm/zai-coding-plan.ts +27 -1
- package/src/llm.ts +17 -97
- package/src/machines/machine-ledger.ts +31 -3
- package/src/maturity/cli-maturity.ts +13 -3
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/msg/msg-store.ts +69 -7
- package/src/nexus/api/http-server.ts +22 -0
- package/src/oauth/codex-account-rotation.ts +4 -1
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-quota-policy.ts +33 -4
- package/src/ops/overview-collect.ts +3 -2
- package/src/ops/overview-owner.ts +29 -0
- package/src/plugin-hooks/shell-hook.ts +17 -2
- package/src/plugin-missions/evaluator-runner.ts +18 -2
- package/src/plugins/install/plugin-install.ts +11 -1
- package/src/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/prompt-enhance/enhance.ts +11 -0
- package/src/release-loop/auto-start.ts +7 -5
- package/src/release-loop/checklist.ts +52 -5
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/gate-shards.ts +4 -0
- package/src/release-loop/light-rc.ts +84 -13
- package/src/release-loop/merged-pr-checklist.ts +35 -5
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/seat-loop/duty-ledger.ts +64 -0
- package/src/seat-loop/seat-loop.ts +5 -1
- package/src/self-dev/decompose.ts +37 -3
- package/src/self-dev/dev-pipeline.ts +32 -7
- package/src/self-dev/draft-residue.ts +16 -6
- package/src/self-dev/draft-sweep.ts +75 -18
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/orchestrate.ts +6 -2
- package/src/self-dev/run-supervisor.ts +72 -8
- package/src/self-implement/gate-cli.ts +29 -10
- package/src/self-implement/gate-remote.ts +4 -1
- package/src/self-implement/goal-author.ts +15 -29
- package/src/self-implement/goal-command-execution.ts +26 -0
- package/src/self-implement/goal-new-paths.ts +42 -0
- package/src/self-implement/host-regate.ts +124 -30
- package/src/self-implement/importer-test-index.ts +3 -1
- package/src/self-implement/l8-merge-queue.ts +80 -2
- package/src/self-implement/merge-train.ts +19 -0
- package/src/self-implement/off-diff-evidence.ts +40 -1
- package/src/self-implement/orchestrator.ts +90 -20
- package/src/self-implement/premise-review.ts +159 -0
- package/src/self-implement/pwa-import-graph.ts +194 -7
- package/src/self-implement/regate-detail.ts +79 -0
- package/src/self-implement/review-deferred-to-host.ts +21 -0
- package/src/self-implement/rework-budget-judgment.ts +23 -3
- package/src/self-implement/running-runs.ts +2 -2
- package/src/self-implement/scope-adjacency.ts +23 -0
- package/src/self-implement/seams.ts +42 -7
- package/src/self-implement/self-implement-runtime.ts +126 -21
- package/src/session/index.ts +14 -4
- package/src/session-runtime/index.ts +55 -11
- package/src/skills/tools/agent.ts +16 -1
- package/src/skills/tools/persistent-grounding.ts +11 -1
- package/src/skills/tools/shell.ts +33 -1
- package/src/steward/rejudge-tick.ts +142 -0
- package/src/task-agent/board.ts +92 -3
- package/src/task-agent/card-evidence.ts +88 -1
- package/src/task-agent/cover.ts +85 -1
- package/src/task-agent/live-moves.ts +14 -6
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +370 -29
- package/src/task-agent/review-result-capture.ts +67 -2
- package/src/task-agent/shadow.ts +148 -21
- package/src/task-agent/task-hand.ts +22 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
- package/src/tool-runtime/tool-search-runtime.ts +25 -0
- package/src/tui.ts +20 -1
- package/src/user-config.ts +21 -63
- package/src/ux-sim/fault-cred-expiry.ts +100 -0
- package/src/ux-sim/fault-pod-death.ts +74 -0
- package/src/ux-sim/fault-pool-cap.ts +81 -0
- package/src/version/packed-revision.json +1 -1
- package/src/webclone/qa-table.ts +22 -0
- package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
- /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
|
@@ -62,11 +62,39 @@ export class TaskNotificationQueue {
|
|
|
62
62
|
* listens to both runner events and a separate `onTaskDone` hook.
|
|
63
63
|
* Keyed by taskId. */
|
|
64
64
|
private seen = new Set<string>();
|
|
65
|
+
/** Wake listeners — fired once per REAL enqueue (not on seen-dup).
|
|
66
|
+
* TUI-SEAT-READY ③ first shard: one completion event = one wake
|
|
67
|
+
* signal so an idle parent can open the next turn. Opening the turn
|
|
68
|
+
* itself is deliberately NOT wired here (next shard). */
|
|
69
|
+
private wakeListeners = new Set<(n: PendingTaskNotification) => void>();
|
|
70
|
+
|
|
71
|
+
/** Register a wake listener; returns an unsubscribe function.
|
|
72
|
+
* Listeners survive `clear()` — they belong to the wiring, not the
|
|
73
|
+
* queue contents. */
|
|
74
|
+
onEnqueue(listener: (n: PendingTaskNotification) => void): () => void {
|
|
75
|
+
this.wakeListeners.add(listener);
|
|
76
|
+
return () => { this.wakeListeners.delete(listener); };
|
|
77
|
+
}
|
|
65
78
|
|
|
66
79
|
enqueue(n: PendingTaskNotification): void {
|
|
67
80
|
if (this.seen.has(n.taskId)) return;
|
|
68
81
|
this.seen.add(n.taskId);
|
|
69
82
|
this.queue.push(n);
|
|
83
|
+
debug.log('agent.task-notification', 'wake', { taskId: n.taskId, size: this.queue.length });
|
|
84
|
+
for (const listener of this.wakeListeners) {
|
|
85
|
+
try {
|
|
86
|
+
listener(n);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
// fail-soft — a throwing wake listener must not lose the
|
|
89
|
+
// queued notification or break sibling listeners.
|
|
90
|
+
try {
|
|
91
|
+
debug.log('agent.task-notification', 'wake-listener-failed', {
|
|
92
|
+
taskId: n.taskId,
|
|
93
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
94
|
+
});
|
|
95
|
+
} catch { /* */ }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
70
98
|
}
|
|
71
99
|
|
|
72
100
|
/** Return all pending notifications AND clear the queue. Parents
|
|
@@ -85,7 +113,8 @@ export class TaskNotificationQueue {
|
|
|
85
113
|
return this.queue.length;
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
/** Forget everything — tests use this for isolation.
|
|
116
|
+
/** Forget everything — tests use this for isolation. Listeners are
|
|
117
|
+
* preserved: clear() empties queue + seen, not the wake wiring. */
|
|
89
118
|
clear(): void {
|
|
90
119
|
this.queue = [];
|
|
91
120
|
this.seen.clear();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// ── ACP Claude Code 를 «구현» 실행기로 (CLAUDE-IMPL-LANE · `--child-llm-provider claude-acp`) ──
|
|
2
2
|
//
|
|
3
3
|
// acp-reviewer.ts 의 짝이다. 리뷰어는 read-only 라 읽기 툴만 허가하지만, 구현 실행기는 런 워크트리 안에서
|
|
4
|
-
// 쓰기·실행을 허가해야 한다.
|
|
4
|
+
// 쓰기·실행을 허가해야 한다. 대표 대표 결정(10-12): ACP 세션 권한 모드는 호스트 설정(auto)을 그대로 두고
|
|
5
|
+
// 바꾸지 않으며, approver 가 불려도 «워크트리 밖 경로 쓰기»를 거부하지 않고 허가하되 insideWorktree 로 관측한다.
|
|
5
6
|
// 자식은 claude 구독 ACP 어댑터(`claude-agent-acp`)이며 env 는 subscriptionReviewerSpawn 의 과금 스크럽
|
|
6
7
|
// (ANTHROPIC_API_KEY 등 제거)을 그대로 쓴다 — 지우지 않으면 구독이 아니라 API 로 과금된다.
|
|
7
8
|
import { isAbsolute, relative, resolve } from 'node:path';
|
|
@@ -23,6 +24,8 @@ export interface ImplementerPermissionRequest {
|
|
|
23
24
|
export interface ImplementerPermissionDecision {
|
|
24
25
|
tool: string;
|
|
25
26
|
path: string | null;
|
|
27
|
+
/** 판정에 쓴 경로가 워크트리 안인가 — 경로가 없으면 null. 밖이어도 허가한다(대표 10-12); 이 칸이 그 관측이다. */
|
|
28
|
+
insideWorktree: boolean | null;
|
|
26
29
|
decision: 'allow' | 'deny';
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -37,18 +40,20 @@ function insideWorktree(worktree: string, target: string): boolean {
|
|
|
37
40
|
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
/** 허가 판정(순수 함수). 쓰기 계열(edit·delete·move)은
|
|
41
|
-
*
|
|
43
|
+
/** 허가 판정(순수 함수). 쓰기 계열(edit·delete·move)은 경로가 있으면 워크트리 안팎을 가리지 않고 허가한다
|
|
44
|
+
* (대표 10-12 — 밖 쓰기 거부를 걷었다 · insideWorktree 로 관측만 한다). 실행(execute)·읽기 계열은 허가,
|
|
45
|
+
* 그 외(모르는 kind)는 경로가 있을 때만 허가 — 경로 없는 쓰기·모르는 요청은 여전히 거부. */
|
|
42
46
|
export function decideImplementerPermission(req: ImplementerPermissionRequest, worktree: string): ImplementerPermissionDecision {
|
|
43
47
|
const paths = requestedPaths(req.rawInput);
|
|
44
48
|
const outside = paths.find((p) => !insideWorktree(worktree, p));
|
|
45
49
|
const tool = req.title.slice(0, 80);
|
|
46
50
|
const shown = outside ?? paths[0] ?? null;
|
|
47
|
-
const
|
|
48
|
-
|
|
51
|
+
const inside = paths.length === 0 ? null : outside === undefined;
|
|
52
|
+
const verdict = (allow: boolean): ImplementerPermissionDecision => ({ tool, path: shown, insideWorktree: inside, decision: allow ? 'allow' : 'deny' });
|
|
53
|
+
if (req.kind && WRITE_TOOL_KINDS.has(req.kind)) return verdict(paths.length > 0);
|
|
49
54
|
if (req.kind === 'execute') return verdict(true);
|
|
50
55
|
if (isReadOnlyReviewTool(req.kind, req.title)) return verdict(true);
|
|
51
|
-
return verdict(paths.length > 0
|
|
56
|
+
return verdict(paths.length > 0);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
export interface AcpImplementerOpts {
|
|
@@ -96,7 +101,9 @@ export function makeAcpImplementer(opts: AcpImplementerOpts): (prompt: string) =
|
|
|
96
101
|
permissionApprover: async (req) => {
|
|
97
102
|
const verdict = decideImplementerPermission(req, opts.worktree);
|
|
98
103
|
if (verdict.decision === 'allow') allowed++; else denied++;
|
|
99
|
-
debug.log(OBS, 'permission', {
|
|
104
|
+
debug.log(OBS, 'permission', {
|
|
105
|
+
tool: verdict.tool, path: verdict.path, insideWorktree: verdict.insideWorktree, allowed: verdict.decision === 'allow',
|
|
106
|
+
});
|
|
100
107
|
return verdict.decision === 'allow';
|
|
101
108
|
},
|
|
102
109
|
};
|
|
@@ -683,8 +683,9 @@ function isLongNoFindingBracket(text: string): boolean {
|
|
|
683
683
|
return NO_FINDING_HEAD.test(remark) && !LONG_REMARK_DISSENT.test(remark);
|
|
684
684
|
}
|
|
685
685
|
/** must-fix 항목이 «지적 없음» 표지인가 — must-fix 를 세는 자리는 전부 `parseReviewResult` 를 거친다
|
|
686
|
-
* (`self review --json` 의 `mustFix` → TA `parseReviewResultOutput` → `pr land --overlap-evidence` 의 `review-must-fix-N`).
|
|
687
|
-
|
|
686
|
+
* (`self review --json` 의 `mustFix` → TA `parseReviewResultOutput` → `pr land --overlap-evidence` 의 `review-must-fix-N`).
|
|
687
|
+
* ⭐ export — `parseReviewResultOutput` 가 «같은» 판정으로 저장된 결과의 표지 줄을 다시 접는다(PR-LAND-MUSTFIX-NONE · 복제 금지). */
|
|
688
|
+
export function isNoneSentinelFinding(finding: string): boolean {
|
|
688
689
|
const text = finding.trim();
|
|
689
690
|
if (BARE_SENTINEL.test(text)) return true;
|
|
690
691
|
const bracketed = BRACKETED_SENTINEL.exec(text);
|
|
@@ -765,6 +766,25 @@ function reviewedResultFromRaw(raw: string, runId: string | undefined, pass?: {
|
|
|
765
766
|
return { verdict: 'pass', mustFix: [], shouldFix: [], reviewed: false, failureReason: NO_VERDICT_LINE_REASON };
|
|
766
767
|
}
|
|
767
768
|
|
|
769
|
+
/** REVIEW-PROMPT-SIZE — llmReview 호출 하나(단일·청크 패스)마다 프롬프트·응답 크기를 남긴다.
|
|
770
|
+
* 관측이 리뷰를 막지 않는다(다른 review.* 관측과 같은 계약). */
|
|
771
|
+
function logReviewPromptSize(
|
|
772
|
+
prompt: string,
|
|
773
|
+
response: string,
|
|
774
|
+
pass: { pass: number; chunked: boolean },
|
|
775
|
+
runId: string | undefined,
|
|
776
|
+
): void {
|
|
777
|
+
try {
|
|
778
|
+
debug.log('review.prompt-size', 'call', {
|
|
779
|
+
pass: pass.pass,
|
|
780
|
+
promptChars: prompt.length,
|
|
781
|
+
responseChars: response.length,
|
|
782
|
+
chunked: pass.chunked,
|
|
783
|
+
...(runId !== undefined ? { runId } : {}),
|
|
784
|
+
});
|
|
785
|
+
} catch { /* Observation must not prevent the review. */ }
|
|
786
|
+
}
|
|
787
|
+
|
|
768
788
|
function failureReasonText(error: unknown): string {
|
|
769
789
|
if (error instanceof Error) return safeLogText(error.message, 400);
|
|
770
790
|
if (typeof error === 'string') return safeLogText(error, 400);
|
|
@@ -916,10 +936,11 @@ export async function reviewPullRequest(
|
|
|
916
936
|
+ ' 「여기 안 보인다」를 결함으로 판정하지 마십시오.',
|
|
917
937
|
].filter(Boolean).join('\n'),
|
|
918
938
|
};
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
939
|
+
const passPrompt = buildReviewPrompt(passInput, passBudget, '', passContext[index]?.budget);
|
|
940
|
+
const passImages = reviewImages.length > 0 && index === 0 ? reviewImages : undefined;
|
|
941
|
+
const passRaw = await llmReview(passPrompt, passImages);
|
|
942
|
+
logReviewPromptSize(passPrompt, passRaw, { pass: index + 1, chunked: true }, input.reviewContext?.runId);
|
|
943
|
+
passResults.push(reviewedResultFromRaw(passRaw, input.reviewContext?.runId, { index, of: plan.passes.length }));
|
|
923
944
|
}
|
|
924
945
|
return {
|
|
925
946
|
...foldReviewResults(passResults),
|
|
@@ -943,10 +964,9 @@ export async function reviewPullRequest(
|
|
|
943
964
|
} : {}),
|
|
944
965
|
};
|
|
945
966
|
}
|
|
946
|
-
const
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
);
|
|
967
|
+
const prompt = buildReviewPrompt(input, diffBudget, referencedContext.text, singleContextBudget);
|
|
968
|
+
const raw = await llmReview(prompt, reviewImages.length > 0 ? reviewImages : undefined);
|
|
969
|
+
logReviewPromptSize(prompt, raw, { pass: 1, chunked: false }, input.reviewContext?.runId);
|
|
950
970
|
return {
|
|
951
971
|
...reviewedResultFromRaw(raw, input.reviewContext?.runId),
|
|
952
972
|
diffBudget: {
|
|
@@ -60,8 +60,11 @@ interface ReviewObservationInput {
|
|
|
60
60
|
readonly fallbackAttempted?: boolean;
|
|
61
61
|
/** 폴백이 실제로 시도한 백엔드. */
|
|
62
62
|
readonly fallbackBackend?: string;
|
|
63
|
+
/** Explicitly requested primary model and the ACP backend that actually completed review. */
|
|
64
|
+
readonly requestedModel?: string;
|
|
65
|
+
readonly actualBackend?: string;
|
|
63
66
|
/** 폴백을 시도하지 않은 이유. */
|
|
64
|
-
readonly fallbackNotAttemptedReason?: 'explicit-acp' | 'primary-review-succeeded';
|
|
67
|
+
readonly fallbackNotAttemptedReason?: 'explicit-acp' | 'primary-review-succeeded' | 'explicit-model';
|
|
65
68
|
/** 1차가 왜 못 돌았나 — 폴백의 «사인». */
|
|
66
69
|
readonly fallbackTriggerReason?: string;
|
|
67
70
|
/** Each failed ACP fallback attempt, retained in order for diagnosis. */
|
|
@@ -80,7 +83,9 @@ interface ReviewObservation {
|
|
|
80
83
|
readonly reviewRoute?: 'api' | 'acp' | 'acp-fallback';
|
|
81
84
|
readonly fallbackAttempted?: boolean;
|
|
82
85
|
readonly fallbackBackend?: string;
|
|
83
|
-
readonly
|
|
86
|
+
readonly requestedModel?: string;
|
|
87
|
+
readonly actualBackend?: string;
|
|
88
|
+
readonly fallbackNotAttemptedReason?: 'explicit-acp' | 'primary-review-succeeded' | 'explicit-model';
|
|
84
89
|
readonly fallbackTriggerReason?: string;
|
|
85
90
|
readonly fallbackFailures?: readonly { backend: string; reason: string }[];
|
|
86
91
|
readonly skippedAcpFallbackBackends?: readonly { backend: string; reason: string }[];
|
|
@@ -168,6 +173,8 @@ export function buildReviewObservation(input: ReviewObservationInput): ReviewObs
|
|
|
168
173
|
...(input.reviewRoute ? { reviewRoute: input.reviewRoute } : {}),
|
|
169
174
|
...(input.fallbackAttempted !== undefined ? { fallbackAttempted: input.fallbackAttempted } : {}),
|
|
170
175
|
...(input.fallbackBackend ? { fallbackBackend: safeLogText(input.fallbackBackend) } : {}),
|
|
176
|
+
...(input.requestedModel ? { requestedModel: safeLogText(input.requestedModel) } : {}),
|
|
177
|
+
...(input.actualBackend ? { actualBackend: safeLogText(input.actualBackend) } : {}),
|
|
171
178
|
...(input.fallbackNotAttemptedReason ? { fallbackNotAttemptedReason: input.fallbackNotAttemptedReason } : {}),
|
|
172
179
|
...(input.fallbackTriggerReason ? { fallbackTriggerReason: safeLogText(input.fallbackTriggerReason) } : {}),
|
|
173
180
|
...(input.fallbackFailures?.length ? {
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
//
|
|
15
15
|
// index.ts 의 액션은 옵션 파싱과 실제 의존 배선만 남는다(얇은 껍데기).
|
|
16
16
|
|
|
17
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
17
20
|
import { tierModel } from '../llm/model-defaults.js';
|
|
18
21
|
import { buildReviewObservation, safeLogText } from './review-observation.js';
|
|
19
22
|
import { DEFAULT_REVIEW_BACKEND } from './acp-reviewer.js';
|
|
@@ -21,7 +24,7 @@ import { ACP_BACKENDS, canonicalizeBackendId } from '../acp/backend-registry.js'
|
|
|
21
24
|
import { buildManualReviewIntent, intentFromPr, prIntentSectionCoverage, reviewIntentTruncationFromPr, reviewIntentTruncationObservation } from './review-intent.js';
|
|
22
25
|
import { budgetReviewerContext, reviewDiffBudgetObservation, splitDiffByFile, type ReviewImage, type ReviewInput, type ReviewerContextItem, type ReviewResult } from './pr-reviewer.js';
|
|
23
26
|
import type { ReferencedFileReader } from '../self-implement/goal-file-reader.js';
|
|
24
|
-
import type
|
|
27
|
+
import { getUserConfig, type SubscriptionReviewerSpec } from '../user-config.js';
|
|
25
28
|
import { listRunLedgers, lookupPrGoalAcceptance, lookupRunLedger, type PrGoalAcceptanceLookup, type RunLedgerEntry, type RunLedgerLookup } from '../self-implement/run-ledger.js';
|
|
26
29
|
|
|
27
30
|
/** SUBSCRIPTION-EXHAUST-REROUTE — API reviewer when the configured `roleLlm.reviewer` lane is unavailable (off codex). */
|
|
@@ -34,6 +37,8 @@ export interface SelfReviewCliOpts {
|
|
|
34
37
|
acpModel?: string | undefined;
|
|
35
38
|
acpBackend?: string | undefined;
|
|
36
39
|
configuredAcpBackend?: string | undefined;
|
|
40
|
+
/** ACP review backends excluded from automatic fallback by `acp.reviewDenyBackends`. */
|
|
41
|
+
reviewDenyBackends?: string[] | undefined;
|
|
37
42
|
/** `roleLlm.reviewer` (same resolution as the harness). Used only when no explicit reviewer flag is given. */
|
|
38
43
|
roleReviewer?: SubscriptionReviewerSpec | undefined;
|
|
39
44
|
acpTimeout?: string | undefined;
|
|
@@ -75,13 +80,13 @@ export interface SelfReviewCliDeps {
|
|
|
75
80
|
*
|
|
76
81
|
* ⚠️ API 백엔드(`makeApiLlm`)는 이 인자를 안 받는다 — ACP 경로만 이미지를 나른다.
|
|
77
82
|
*/
|
|
78
|
-
makeAcpLlm(o: { backend: string; model?: string; timeoutMs: number }): (prompt: string, images?: readonly ReviewImage[]) => Promise<string>;
|
|
83
|
+
makeAcpLlm(o: { backend: string; model?: string; timeoutMs: number; cwd?: string }): (prompt: string, images?: readonly ReviewImage[]) => Promise<string>;
|
|
79
84
|
/**
|
|
80
85
|
* Reviewer ACP lane selected by `roleLlm.reviewer` (no explicit flag). Returns the LLM when the
|
|
81
86
|
* subscription is usable, or a reason code when it is not — the caller then reviews on the API
|
|
82
87
|
* exactly as before. Absent seam = the lane is unavailable (`role-reviewer-seam-missing`).
|
|
83
88
|
*/
|
|
84
|
-
makeRoleReviewerLlm?(spec: SubscriptionReviewerSpec, o: { timeoutMs: number }):
|
|
89
|
+
makeRoleReviewerLlm?(spec: SubscriptionReviewerSpec, o: { timeoutMs: number; cwd?: string }):
|
|
85
90
|
| { llm: (prompt: string, images?: readonly ReviewImage[]) => Promise<string>; backend: string }
|
|
86
91
|
| { reason: string };
|
|
87
92
|
/**
|
|
@@ -1117,10 +1122,11 @@ function roleAcpErrorReason(error: unknown): 'acp-handshake-timeout' | 'acp-erro
|
|
|
1117
1122
|
|
|
1118
1123
|
type AcpFallbackSkip = { backend: string; reason: string };
|
|
1119
1124
|
|
|
1120
|
-
function orderedAcpReviewFallbackBackends(configuredBackend: string | undefined): {
|
|
1125
|
+
function orderedAcpReviewFallbackBackends(configuredBackend: string | undefined, denyBackends: readonly string[] = []): {
|
|
1121
1126
|
backends: string[];
|
|
1122
1127
|
skipped: AcpFallbackSkip[];
|
|
1123
1128
|
} {
|
|
1129
|
+
const denied = new Set(denyBackends.map((backend) => backend.trim().toLowerCase()).filter(Boolean));
|
|
1124
1130
|
const candidates = [configuredBackend, ...Object.keys(ACP_BACKENDS)]
|
|
1125
1131
|
.map((backend) => backend?.trim())
|
|
1126
1132
|
.filter((backend): backend is string => Boolean(backend));
|
|
@@ -1132,6 +1138,10 @@ function orderedAcpReviewFallbackBackends(configuredBackend: string | undefined)
|
|
|
1132
1138
|
const spec = ACP_BACKENDS[backend];
|
|
1133
1139
|
if (!spec || seen.has(backend)) continue;
|
|
1134
1140
|
seen.add(backend);
|
|
1141
|
+
if (denied.has(backend)) {
|
|
1142
|
+
skipped.push({ backend, reason: 'denied-by-acp.reviewDenyBackends' });
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1135
1145
|
if (spec.unsupportedReason) {
|
|
1136
1146
|
skipped.push({ backend, reason: spec.unsupportedReason });
|
|
1137
1147
|
continue;
|
|
@@ -1164,6 +1174,65 @@ export function renderReviewerContextStatus(loaded: LoadedReviewerContext, decom
|
|
|
1164
1174
|
return `Reviewer context: ${loaded.items.length} loaded, ${loaded.failed.length} not loaded.${source}${truncation}${decompositionStatus}${labels ? `\n${labels}` : ''}${failures ? `\n${failures}` : ''}`;
|
|
1165
1175
|
}
|
|
1166
1176
|
|
|
1177
|
+
/**
|
|
1178
|
+
* 머지된 PR 의 사후 리뷰 격리 — 리뷰어 cwd 가 main 최신이면 그 뒤 수리를 인용한다.
|
|
1179
|
+
* `merged` 는 그 PR 의 머지 커밋, `open` 은 종전(cwd 불변), `unpinnable` 은 MERGED 인데 머지 커밋을 못 구한 경우다.
|
|
1180
|
+
*/
|
|
1181
|
+
type PrMergeState =
|
|
1182
|
+
| { kind: 'open' }
|
|
1183
|
+
| { kind: 'merged'; commit: string }
|
|
1184
|
+
| { kind: 'unpinnable'; reason: 'merge-commit-unknown' };
|
|
1185
|
+
|
|
1186
|
+
function readPrMergeState(pr: string, deps: SelfReviewCliDeps): PrMergeState {
|
|
1187
|
+
const view = deps.gh(['pr', 'view', pr, '--json', 'state,mergeCommit'], 15_000);
|
|
1188
|
+
if (view.status !== 0) return { kind: 'open' };
|
|
1189
|
+
try {
|
|
1190
|
+
const parsed = JSON.parse(view.stdout) as { state?: unknown; mergeCommit?: { oid?: unknown } | null };
|
|
1191
|
+
if (parsed?.state !== 'MERGED') return { kind: 'open' };
|
|
1192
|
+
const oid = parsed.mergeCommit?.oid;
|
|
1193
|
+
return typeof oid === 'string' && COMMIT_OID.test(oid)
|
|
1194
|
+
? { kind: 'merged', commit: oid }
|
|
1195
|
+
: { kind: 'unpinnable', reason: 'merge-commit-unknown' };
|
|
1196
|
+
} catch {
|
|
1197
|
+
return { kind: 'open' };
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
interface ReviewWorktree {
|
|
1202
|
+
cwd: string;
|
|
1203
|
+
commit: string;
|
|
1204
|
+
/** 멱등 — 두 번 불러도 안전하다. */
|
|
1205
|
+
remove(): void;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
type ReviewWorktreeResult = ReviewWorktree | { reason: 'no-git-seam' | 'worktree-add-failed' };
|
|
1209
|
+
|
|
1210
|
+
function createDetachedReviewWorktree(commit: string, deps: SelfReviewCliDeps): ReviewWorktreeResult {
|
|
1211
|
+
const git = deps.git;
|
|
1212
|
+
if (!git) return { reason: 'no-git-seam' };
|
|
1213
|
+
const parent = mkdtempSync(join(tmpdir(), 'elanous-review-pin-'));
|
|
1214
|
+
const cwd = join(parent, 'wt');
|
|
1215
|
+
const add = () => git(['worktree', 'add', '--detach', cwd, commit], 120_000);
|
|
1216
|
+
let added = add();
|
|
1217
|
+
if (added.status !== 0) {
|
|
1218
|
+
git(['fetch', 'origin', commit], 120_000);
|
|
1219
|
+
added = add();
|
|
1220
|
+
}
|
|
1221
|
+
let removed = false;
|
|
1222
|
+
const remove = (): void => {
|
|
1223
|
+
if (removed) return;
|
|
1224
|
+
removed = true;
|
|
1225
|
+
git(['worktree', 'remove', '--force', cwd], 60_000);
|
|
1226
|
+
rmSync(parent, { recursive: true, force: true });
|
|
1227
|
+
// ⛔ `git worktree prune` 은 부르지 않는다 — 저장소 «전체»의 stale 메타데이터를 지워 남의 worktree 까지 건드린다.
|
|
1228
|
+
};
|
|
1229
|
+
if (added.status !== 0) {
|
|
1230
|
+
remove();
|
|
1231
|
+
return { reason: 'worktree-add-failed' };
|
|
1232
|
+
}
|
|
1233
|
+
return { cwd, commit, remove };
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1167
1236
|
/** `elanous self review <pr...>` 본문. read-only — 머지하지 않는다. */
|
|
1168
1237
|
/**
|
|
1169
1238
|
* `self review --json` stdout 한 줄 — 결과가 하나면 객체, 여럿이면 배열. index.ts 액션이 이것을 그대로 쓴다.
|
|
@@ -1177,6 +1246,20 @@ export async function runSelfReviewCliCommand(
|
|
|
1177
1246
|
prArgs: string[],
|
|
1178
1247
|
opts: SelfReviewCliOpts,
|
|
1179
1248
|
deps: SelfReviewCliDeps,
|
|
1249
|
+
): Promise<SelfReviewCliOutcome> {
|
|
1250
|
+
const pins: ReviewWorktree[] = [];
|
|
1251
|
+
try {
|
|
1252
|
+
return await runSelfReviewCliCommandPinned(prArgs, opts, deps, pins);
|
|
1253
|
+
} finally {
|
|
1254
|
+
for (const pin of pins) pin.remove();
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
async function runSelfReviewCliCommandPinned(
|
|
1259
|
+
prArgs: string[],
|
|
1260
|
+
opts: SelfReviewCliOpts,
|
|
1261
|
+
deps: SelfReviewCliDeps,
|
|
1262
|
+
pins: ReviewWorktree[],
|
|
1180
1263
|
): Promise<SelfReviewCliOutcome> {
|
|
1181
1264
|
// 관측 sink는 모든 종료 경로보다 먼저 등록해 거부도 운영 로그에 남긴다.
|
|
1182
1265
|
await deps.registerSink('self-review');
|
|
@@ -1201,7 +1284,12 @@ export async function runSelfReviewCliCommand(
|
|
|
1201
1284
|
? { backend: opts.configuredAcpBackend, source: 'config' as const }
|
|
1202
1285
|
: { backend: DEFAULT_REVIEW_BACKEND, source: 'default' as const };
|
|
1203
1286
|
const acpBackend = acpBackendResolution.backend;
|
|
1204
|
-
const
|
|
1287
|
+
const requestedModel = opts.model?.trim() || undefined;
|
|
1288
|
+
const rawReviewDenyBackends = (getUserConfig().raw?.acp as { reviewDenyBackends?: unknown } | undefined)?.reviewDenyBackends;
|
|
1289
|
+
const configuredReviewDenyBackends = Array.isArray(rawReviewDenyBackends)
|
|
1290
|
+
? rawReviewDenyBackends.filter((backend): backend is string => typeof backend === 'string')
|
|
1291
|
+
: [];
|
|
1292
|
+
const automaticFallbacks = orderedAcpReviewFallbackBackends(opts.configuredAcpBackend, opts.reviewDenyBackends ?? configuredReviewDenyBackends);
|
|
1205
1293
|
const fallbackAcpBackends = opts.acpBackend
|
|
1206
1294
|
? [canonicalizeBackendId(opts.acpBackend)]
|
|
1207
1295
|
: automaticFallbacks.backends;
|
|
@@ -1224,6 +1312,14 @@ export async function runSelfReviewCliCommand(
|
|
|
1224
1312
|
const envModel = deps.envModel();
|
|
1225
1313
|
const roleFallbackModel = !useAcp && !opts.model && !envModel && reviewerSource === 'role-config'
|
|
1226
1314
|
? deps.roleFallbackModel?.()?.trim() || undefined : undefined;
|
|
1315
|
+
if (requestedModel && /^glm-\d+(?:\.\d+)?$/i.test(requestedModel)) {
|
|
1316
|
+
const canonical = requestedModel.toLowerCase() === 'glm-5.3' ? 'openrouter/z-ai/glm-5.3' : undefined;
|
|
1317
|
+
const suggestion = canonical ? ` 정본 모델 ID 후보: ${canonical}` : ' `local:<model>` 또는 공급자 정본 ID를 지정하세요.';
|
|
1318
|
+
const message = `모델 ID가 모호합니다: ${requestedModel}.${suggestion} 짧은 별칭을 공급자 정본 ID로 바꿔 다시 시도하세요.`;
|
|
1319
|
+
deps.log('model-rejected', { requestedModel: safeLogText(requestedModel), reason: 'ambiguous-model-id', ...(canonical ? { canonicalModelCandidate: canonical } : {}) }, { level: 'warn' });
|
|
1320
|
+
deps.error(message);
|
|
1321
|
+
return { results: opts.json ? [{ error: message, requestedModel }] : [], failed: 1 };
|
|
1322
|
+
}
|
|
1227
1323
|
const model = useAcp ? `acp:${acpBackend}${acpModel ? `/${acpModel}` : ''}` : (opts.model || envModel || roleFallbackModel || tierModel('better'));
|
|
1228
1324
|
let roleReviewer: { llm: (prompt: string, images?: readonly ReviewImage[]) => Promise<string>; model: string } | undefined;
|
|
1229
1325
|
let roleReviewerUnavailableReason: string | undefined;
|
|
@@ -1272,6 +1368,7 @@ export async function runSelfReviewCliCommand(
|
|
|
1272
1368
|
// ⛔ `relation-unknown` 도 경고한다(위 주석 · 리뷰가 두 라운드 반복 지적) — 그 밖 unavailable 은 조용하다.
|
|
1273
1369
|
// ⭐ 경고 여부 판정은 `localHeadWarningDetails` 한 곳에 있다(호출부에서 같은 함수를 두 번 부르지 않는다).
|
|
1274
1370
|
const mismatchWarning = localHeadWarningDetails(localHeadComparison);
|
|
1371
|
+
const mergeState = readPrMergeState(pr, deps);
|
|
1275
1372
|
const view = deps.gh(['pr', 'view', pr, '--json', 'title,body'], 15_000);
|
|
1276
1373
|
let prView: { title?: string; body?: string } | undefined;
|
|
1277
1374
|
if (view.status === 0) {
|
|
@@ -1399,6 +1496,36 @@ export async function runSelfReviewCliCommand(
|
|
|
1399
1496
|
else deps.print(`\n━━ PR ${pr} (${primaryModel}) ━━\n${renderStaleRefusal(diffRead)}\n${reviewerContextStatus}`);
|
|
1400
1497
|
continue;
|
|
1401
1498
|
}
|
|
1499
|
+
// ⭐ 머지된 PR 만 머지 커밋 detached worktree 에서 리뷰한다 — main 최신이 아니라 그 PR 이 머지된 시점의 코드를 본다.
|
|
1500
|
+
// 열린 PR 은 종전 그대로(cwd = process.cwd() · 리뷰어 심이 cwd 를 받지 않는다).
|
|
1501
|
+
let reviewPin: ReviewWorktree | undefined;
|
|
1502
|
+
let reviewCwdPinFallbackReason: string | undefined;
|
|
1503
|
+
// cwd 를 받는 레인(ACP · role 리뷰어)일 때만 worktree 를 뜬다 — API 리뷰어는 cwd 를 안 받으므로 떠도 그 위에서 돌지 않는다.
|
|
1504
|
+
const pinLane = useAcp || Boolean(roleReviewer && opts.roleReviewer && deps.makeRoleReviewerLlm);
|
|
1505
|
+
let rolePinned = false;
|
|
1506
|
+
if (!pinLane) {
|
|
1507
|
+
// 비-ACP 레인 — 격리하지 않는다(종전 그대로 · reviewCwdCommit 없음).
|
|
1508
|
+
} else if (mergeState.kind === 'merged') {
|
|
1509
|
+
const made = createDetachedReviewWorktree(mergeState.commit, deps);
|
|
1510
|
+
if ('cwd' in made) {
|
|
1511
|
+
reviewPin = made;
|
|
1512
|
+
pins.push(made);
|
|
1513
|
+
} else reviewCwdPinFallbackReason = made.reason;
|
|
1514
|
+
} else if (mergeState.kind === 'unpinnable') reviewCwdPinFallbackReason = mergeState.reason;
|
|
1515
|
+
const reviewCwd = reviewPin?.cwd;
|
|
1516
|
+
const prAcpReviewLLM = reviewCwd && useAcp
|
|
1517
|
+
? deps.makeAcpLlm({ backend: acpBackend, ...(acpModel ? { model: acpModel } : {}), timeoutMs: acpTimeoutSec * 1000, cwd: reviewCwd })
|
|
1518
|
+
: acpReviewLLM;
|
|
1519
|
+
let prRoleReviewer = roleReviewer;
|
|
1520
|
+
if (reviewCwd && roleReviewer && opts.roleReviewer && deps.makeRoleReviewerLlm) {
|
|
1521
|
+
try {
|
|
1522
|
+
const pinned = deps.makeRoleReviewerLlm(opts.roleReviewer, { timeoutMs: acpTimeoutSec * 1000, cwd: reviewCwd });
|
|
1523
|
+
if ('llm' in pinned) { prRoleReviewer = { llm: pinned.llm, model: `acp:${pinned.backend}` }; rolePinned = true; }
|
|
1524
|
+
else reviewCwdPinFallbackReason = 'role-reviewer-cwd-unavailable';
|
|
1525
|
+
} catch {
|
|
1526
|
+
reviewCwdPinFallbackReason = 'role-reviewer-cwd-unavailable';
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1402
1529
|
const startedAt = deps.now();
|
|
1403
1530
|
// Role-config lane builds the API reviewer only when it falls back (`made().api` stays 0 on ACP success).
|
|
1404
1531
|
const responded: { provider?: string; model?: string } = {};
|
|
@@ -1406,7 +1533,7 @@ export async function runSelfReviewCliCommand(
|
|
|
1406
1533
|
pinProvider: Boolean(opts.model?.trim()),
|
|
1407
1534
|
onResolved: (provider, respondedModel) => { responded.provider = provider; responded.model = respondedModel; },
|
|
1408
1535
|
});
|
|
1409
|
-
const llmReview =
|
|
1536
|
+
const llmReview = prRoleReviewer ? undefined : (prAcpReviewLLM ?? makeApi());
|
|
1410
1537
|
// ⛔ evidenceNote 는 **별도 채널**이다 — phaseIntent 에 섞으면 의도 채널이 오염된다(실측: 그렇게
|
|
1411
1538
|
// 했다가 intent 배선 테스트 3개가 즉시 깨졌다).
|
|
1412
1539
|
// ⛔ 사람 `--intent`(phaseIntent) 와 골 acceptance 는 다른 인자 — 충돌하지 않고, 충돌해도 intent 가 이긴다.
|
|
@@ -1426,10 +1553,10 @@ export async function runSelfReviewCliCommand(
|
|
|
1426
1553
|
let roleReview: ReviewResult | undefined;
|
|
1427
1554
|
let roleReviewerFallbackReason = roleReviewerUnavailableReason;
|
|
1428
1555
|
let roleReviewMs: number | undefined;
|
|
1429
|
-
if (
|
|
1556
|
+
if (prRoleReviewer) {
|
|
1430
1557
|
const roleStartedAt = deps.now();
|
|
1431
1558
|
try {
|
|
1432
|
-
const attempt = await deps.reviewPullRequest(reviewInput,
|
|
1559
|
+
const attempt = await deps.reviewPullRequest(reviewInput, prRoleReviewer.llm);
|
|
1433
1560
|
if (attempt.reviewed === true) roleReview = attempt;
|
|
1434
1561
|
// Code, not the reviewer's raw failure text (same rule as the throw path above).
|
|
1435
1562
|
else roleReviewerFallbackReason = 'acp-review-not-completed';
|
|
@@ -1445,15 +1572,15 @@ export async function runSelfReviewCliCommand(
|
|
|
1445
1572
|
}, { level: 'warn' });
|
|
1446
1573
|
}
|
|
1447
1574
|
}
|
|
1448
|
-
let review = roleReview ?? await deps.reviewPullRequest(reviewInput, llmReview ??
|
|
1449
|
-
let selectedModel = roleReview &&
|
|
1575
|
+
let review = roleReview ?? await deps.reviewPullRequest(reviewInput, llmReview ?? prAcpReviewLLM ?? makeApi());
|
|
1576
|
+
let selectedModel = roleReview && prRoleReviewer ? prRoleReviewer.model : model;
|
|
1450
1577
|
let reviewRoute: 'api' | 'acp' | 'acp-fallback' = useAcp || roleReview ? 'acp' : 'api';
|
|
1451
1578
|
let fallbackAttempted = false;
|
|
1452
1579
|
let fallbackBackend: string | undefined;
|
|
1453
1580
|
let fallbackTriggerReason: string | undefined;
|
|
1454
|
-
let fallbackNotAttemptedReason: 'explicit-acp' | 'primary-review-succeeded' | undefined;
|
|
1581
|
+
let fallbackNotAttemptedReason: 'explicit-acp' | 'primary-review-succeeded' | 'explicit-model' | undefined;
|
|
1455
1582
|
const fallbackFailures: Array<{ backend: string; reason: string }> = [];
|
|
1456
|
-
if (!useAcp && !roleReview && review.reviewed !== true) {
|
|
1583
|
+
if (!useAcp && !roleReview && !opts.acpModel?.trim() && (!requestedModel || Boolean(opts.acpBackend)) && review.reviewed !== true) {
|
|
1457
1584
|
fallbackAttempted = true;
|
|
1458
1585
|
fallbackTriggerReason = safeLogText(review.failureReason || 'reviewed=false', 400);
|
|
1459
1586
|
for (const backend of fallbackAcpBackends) {
|
|
@@ -1462,11 +1589,12 @@ export async function runSelfReviewCliCommand(
|
|
|
1462
1589
|
pr: safeLogText(pr),
|
|
1463
1590
|
failureReason: fallbackTriggerReason,
|
|
1464
1591
|
fallbackBackend: safeLogText(backend),
|
|
1592
|
+
requestedModel: safeLogText(primaryModel),
|
|
1465
1593
|
}, { level: 'warn' });
|
|
1466
1594
|
try {
|
|
1467
1595
|
const fallbackReview = await deps.reviewPullRequest(
|
|
1468
1596
|
reviewInput,
|
|
1469
|
-
deps.makeAcpLlm({ backend, timeoutMs: acpTimeoutSec * 1000 }),
|
|
1597
|
+
deps.makeAcpLlm({ backend, timeoutMs: acpTimeoutSec * 1000, ...(reviewCwd ? { cwd: reviewCwd } : {}) }),
|
|
1470
1598
|
);
|
|
1471
1599
|
if (fallbackReview.reviewed === true) {
|
|
1472
1600
|
review = fallbackReview;
|
|
@@ -1482,13 +1610,22 @@ export async function runSelfReviewCliCommand(
|
|
|
1482
1610
|
}
|
|
1483
1611
|
}
|
|
1484
1612
|
}
|
|
1613
|
+
reviewPin?.remove();
|
|
1614
|
+
// reviewCwdCommit 은 «최종 판정을 낸 LLM 이 실제로 그 cwd 를 받았을 때만» 싣는다(role 실패 → API 폴백이면 안 싣는다).
|
|
1615
|
+
const reviewedOnPin = Boolean(reviewPin) && (roleReview ? rolePinned : reviewRoute === 'acp-fallback' ? true : reviewRoute === 'acp' && useAcp);
|
|
1616
|
+
if (reviewPin && !reviewedOnPin) reviewCwdPinFallbackReason ??= 'final-reviewer-not-pinned';
|
|
1617
|
+
const reviewCwdOutput = {
|
|
1618
|
+
...(reviewPin && reviewedOnPin ? { reviewCwdCommit: reviewPin.commit } : {}),
|
|
1619
|
+
...(reviewCwdPinFallbackReason ? { reviewCwdPinFallbackReason } : {}),
|
|
1620
|
+
};
|
|
1485
1621
|
if (!fallbackAttempted) {
|
|
1486
|
-
fallbackNotAttemptedReason = useAcp ? 'explicit-acp' : 'primary-review-succeeded';
|
|
1622
|
+
fallbackNotAttemptedReason = useAcp ? 'explicit-acp' : requestedModel && review.reviewed !== true ? 'explicit-model' : 'primary-review-succeeded';
|
|
1487
1623
|
}
|
|
1488
1624
|
const reviewProvenance = {
|
|
1489
1625
|
reviewRoute,
|
|
1490
1626
|
fallbackAttempted,
|
|
1491
1627
|
...(fallbackBackend ? { fallbackBackend } : {}),
|
|
1628
|
+
...(fallbackBackend ? { requestedModel: primaryModel, actualBackend: `acp:${fallbackBackend}` } : {}),
|
|
1492
1629
|
...(fallbackNotAttemptedReason ? { fallbackNotAttemptedReason } : {}),
|
|
1493
1630
|
...(fallbackTriggerReason ? { fallbackTriggerReason } : {}),
|
|
1494
1631
|
...(fallbackFailures.length ? { fallbackFailures } : {}),
|
|
@@ -1522,20 +1659,21 @@ export async function runSelfReviewCliCommand(
|
|
|
1522
1659
|
goalLoaded: goalAcceptance.goalLoaded,
|
|
1523
1660
|
acceptanceChars: goalAcceptance.acceptanceChars,
|
|
1524
1661
|
...reviewerSelection,
|
|
1662
|
+
...reviewCwdOutput,
|
|
1525
1663
|
},
|
|
1526
1664
|
{ level: review.reviewed === false ? 'warn' : 'info' });
|
|
1527
1665
|
// --acp 는 대표가 명시 요청한 리뷰 — fail-soft(reviewed=false)면 조용히 pass 하지 말고 표면화(관측=acp-review).
|
|
1528
1666
|
if (useAcp && review.reviewed === false) {
|
|
1529
1667
|
const err = 'ACP 리뷰 실행 실패(reviewed=false) — 관측: elanous logs --category acp-review';
|
|
1530
1668
|
const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
|
|
1531
|
-
if (opts.json) results.push({ pr, error: err, ...review, verdict: null, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...provenance, ...contextOutput });
|
|
1669
|
+
if (opts.json) results.push({ pr, error: err, ...review, verdict: null, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput });
|
|
1532
1670
|
else deps.error(`PR ${pr}: ${err}\n${renderProvenance(diffRead)}\n${reviewerContextStatus}`);
|
|
1533
1671
|
failed += 1;
|
|
1534
1672
|
continue;
|
|
1535
1673
|
}
|
|
1536
1674
|
const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
|
|
1537
1675
|
const jsonReview = review.reviewed === true ? review : { ...review, verdict: null };
|
|
1538
|
-
if (opts.json) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...provenance, ...contextOutput, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
|
|
1676
|
+
if (opts.json) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
|
|
1539
1677
|
else deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n${evidenceLine}\n${reviewerContextStatus}\n${deps.renderReview(review)}`);
|
|
1540
1678
|
// REVIEW-ERROR-RC — 기본(API)·role 경로가 1차·폴백 모두 실패해 reviewed≠true 로 끝나도 «못 리뷰한 PR» 이다(verdict:null).
|
|
1541
1679
|
if (review.reviewed !== true) failed += 1;
|
|
@@ -75,6 +75,66 @@ export function _setCreateGoalAuthorDecomposeStepsForTesting(fn?: CreateGoalAuth
|
|
|
75
75
|
/** 진행 종료 스테이지(phase='end') — 그 외는 delta(start 제외). */
|
|
76
76
|
const END_STAGES: readonly SelfImplementProgressStage[] = ['pr-opened', 'aborted', 'gate-failed', 'pr-declined'];
|
|
77
77
|
|
|
78
|
+
// ⭐ 결과 네 꼴(HARNESS-RESULT-CONTRACT · RFC-tui-tool-surface-on-graph-harness §4 · 0.2.26) —
|
|
79
|
+
// 종전 `{observed:true}` 한 비트는 모델이 «안 됐다 → 직접 편집»으로 읽었다(UX S1-02 · 47 도구).
|
|
80
|
+
// ⇒ launched / pending / observed-only / failed 네 꼴로 구조화해 «다음 행동»을 문면으로 고정한다.
|
|
81
|
+
// ⚠️ launched 꼴은 SelfImplementResult 필드를 **그대로 보존**한다 — runId 조인·원장 소비자 무손상.
|
|
82
|
+
export type SelfImplementLaunchedToolResult = SelfImplementResult & { runId: string; kind: 'launched'; message: string; next: string; missing: string[] };
|
|
83
|
+
export type SelfImplementPendingToolResult = Partial<SelfImplementResult> & { kind: 'pending'; message: string; next: string; missing: string[] };
|
|
84
|
+
export type SelfImplementObservedOnlyToolResult = { kind: 'observed-only'; observed: true; message: string; next: string; missing: ['runId', 'node'] };
|
|
85
|
+
export type SelfImplementFailedToolResult = Partial<SelfImplementResult> & { kind: 'failed'; reason: string; message: string; next: string; missing: string[] };
|
|
86
|
+
export type SelfImplementToolResult = SelfImplementLaunchedToolResult | SelfImplementPendingToolResult | SelfImplementObservedOnlyToolResult | SelfImplementFailedToolResult;
|
|
87
|
+
|
|
88
|
+
/** 하니스가 런을 맡았다 — 파일 편집은 하니스 몫이므로 모델의 직접 Write/Edit 을 문면으로 막는다. */
|
|
89
|
+
export function buildLaunchedToolResult(result: SelfImplementResult): SelfImplementLaunchedToolResult | SelfImplementPendingToolResult {
|
|
90
|
+
if (!result.runId) return buildPendingToolResult(result);
|
|
91
|
+
const runId = result.runId;
|
|
92
|
+
const node = result.node || null;
|
|
93
|
+
const missing = node ? [] : ['node'];
|
|
94
|
+
const query = `eln self run ${runId}`;
|
|
95
|
+
return {
|
|
96
|
+
...result,
|
|
97
|
+
runId,
|
|
98
|
+
kind: 'launched',
|
|
99
|
+
next: query,
|
|
100
|
+
missing,
|
|
101
|
+
message: `하니스가 맡았습니다 · 런 ${runId} · 노드 ${node ?? '미관측'} · 다음 조회: ${query} · 이 턴에서 파일을 직접 편집하지 마세요`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** 완료 또는 접수는 관측했지만 실제 런 ID가 없어 발사를 단언할 수 없다. */
|
|
106
|
+
export function buildPendingToolResult(result: SelfImplementResult): SelfImplementPendingToolResult {
|
|
107
|
+
const { runId: _unconfirmedRunId, ...observed } = result;
|
|
108
|
+
return {
|
|
109
|
+
...observed,
|
|
110
|
+
kind: 'pending',
|
|
111
|
+
next: 'eln self running-runs',
|
|
112
|
+
missing: ['runId', ...(result.node ? [] : ['node'])],
|
|
113
|
+
message: '하니스 응답을 받았지만 런 식별자는 아직 미관측입니다 · 진행 중 런 조회: eln self running-runs · 일치하는 런이 없으면 요청을 다시 보내세요 · 이 턴에서 파일을 직접 편집하지 마세요',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** 관측 전용 — 런이 발사되지 «않았다»는 사실과 «구현 실패가 아니다»를 함께 말한다. */
|
|
118
|
+
export function buildObservedOnlyToolResult(): SelfImplementObservedOnlyToolResult {
|
|
119
|
+
return {
|
|
120
|
+
kind: 'observed-only',
|
|
121
|
+
observed: true,
|
|
122
|
+
missing: ['runId', 'node'],
|
|
123
|
+
next: '실제 발사를 원하면 관측 전용 모드를 끈 뒤 다시 요청하세요',
|
|
124
|
+
message: '관측 전용이라 런을 발사하지 않았습니다 · 코드도 안 바꿨습니다 · 이 결과를 구현 실패로 읽고 직접 Write/Edit 하지 마세요 · 실제 발사를 원하면 관측 전용 모드를 끈 뒤 다시 요청하세요',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** 거부·실패 — 이유와 다음 행동을 구조화해 모델이 재시도·포기·인계를 판단하게 한다. */
|
|
129
|
+
export function buildFailedToolResult(reason: string, result?: SelfImplementResult): SelfImplementFailedToolResult {
|
|
130
|
+
const next = result?.runId ? `eln self run ${result.runId}` : '요청과 실패 이유를 확인한 뒤 다시 요청하세요';
|
|
131
|
+
return {
|
|
132
|
+
...(result ?? {}), kind: 'failed', reason, next,
|
|
133
|
+
missing: [...(result?.runId ? [] : ['runId']), ...(result?.node ? [] : ['node'])],
|
|
134
|
+
message: `하니스가 발사되지 않았거나 실패했습니다: ${reason} · 다음: ${next} · 이 턴에서 파일을 직접 편집하지 마세요`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
78
138
|
/**
|
|
79
139
|
* ★ base seam 에 막(SurfaceUx) 배선을 얹는다(P0·테스트 가능). approvePr=ux.confirm(fail-closed)·
|
|
80
140
|
* onProgress=ux.progress. 코어(runSelfImplement)·다른 seam(worktree/implement/gate/openPr)은 무손상.
|
|
@@ -180,9 +240,10 @@ export async function dispatchSelfImplement(
|
|
|
180
240
|
authorGoal: SelfImplementGoalAuthor = writeAuthoredGoal,
|
|
181
241
|
runCli: RunSelfImplementCliFn = runSelfImplementCliCommand,
|
|
182
242
|
seamsFactory?: SelfImplementSeamsFactory,
|
|
183
|
-
): Promise<
|
|
243
|
+
): Promise<SelfImplementToolResult> {
|
|
184
244
|
const feature = typeof args.feature === 'string' ? args.feature.trim() : '';
|
|
185
|
-
if (!feature) return
|
|
245
|
+
if (!feature) return buildFailedToolResult('SelfImplement: `feature` is required');
|
|
246
|
+
try {
|
|
186
247
|
const base = typeof args.base === 'string' && args.base.trim() ? args.base.trim() : undefined;
|
|
187
248
|
const draft = typeof args.draft === 'boolean' ? args.draft : true;
|
|
188
249
|
const entry = resolveDispatchEntry(ctx);
|
|
@@ -216,7 +277,7 @@ export async function dispatchSelfImplement(
|
|
|
216
277
|
debug.log('daemon-tools.self-implement', 'runtime.observe-only-decision', { surface: ux.surface, observeOnly: observeOnly.enabled, observeOnlySource: observeOnly.source });
|
|
217
278
|
if (observeOnly.enabled) {
|
|
218
279
|
debug.log('daemon-tools.self-implement', 'runtime.observed', { surface: ux.surface, observeOnly: observeOnly.enabled, observeOnlySource: observeOnly.source });
|
|
219
|
-
return
|
|
280
|
+
return buildObservedOnlyToolResult();
|
|
220
281
|
}
|
|
221
282
|
|
|
222
283
|
let goalFile: string | undefined;
|
|
@@ -298,5 +359,12 @@ export async function dispatchSelfImplement(
|
|
|
298
359
|
// ⭐ runId 를 반드시 싣는다 — 관측이 전부 runId 로 키잉되므로(`self run <runId>`·`logs --grep`)
|
|
299
360
|
// 이게 없으면 **이 경계에서 조인이 끊긴다**(N3 재측정 2026-07-28: 계약은 섰는데 로그가 못 따라갔다).
|
|
300
361
|
debug.log('daemon-tools.self-implement', 'done', { runId: result.runId, stage: result.stage, ok: result.ok, pr: result.prUrl ?? null });
|
|
301
|
-
return result
|
|
362
|
+
return !result.ok
|
|
363
|
+
? buildFailedToolResult(result.detail ?? result.stage, result)
|
|
364
|
+
: result.runId ? buildLaunchedToolResult(result) : buildPendingToolResult(result);
|
|
365
|
+
} catch (error) {
|
|
366
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
367
|
+
debug.log('daemon-tools.self-implement', 'failed', { reason, stage: 'dispatch' });
|
|
368
|
+
return buildFailedToolResult(reason);
|
|
369
|
+
}
|
|
302
370
|
}
|