elanous 0.2.24 → 0.2.25
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/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-37fd16f479f5554a.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-9360b1285b2a346e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f08f6529d09ffae1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-f000d54d258f9ef6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-24282bf9f90031a5.js → page-b12149c51f7d04b1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-22f674e7e4c2c9d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8888733e40cea6d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9717ec6964b92276.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-44eaad486bc98a45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-97fa6cf3d34c7eb9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-305cd294e754906e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-dea4b795741126fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-35e05d7450461a67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-45889e7070d11126.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-16a2e893f83ae4d0.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-b2638013c0bf7dfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-56888bc744e08dac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-c44f93a41167536f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-952c6ceec6d9de38.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-6d0202af568f4c63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-1b810474507f3702.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-74366ae2693a7d95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4fb6fc34e20c07b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-e9502921f4f01b1f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-b6169ea2f09cf287.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6a14333d1b1b3967.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8c91a9a66c9ec90a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-1d809a87139dd024.js → page-4e634c5b98fd4e93.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ed3070d637850548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-b9cc8a10bc6078b4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-3d3fc73dd187ed52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-128458c8d86fbb5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9c04dac0831c2bbb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-cf0c2b0183991d09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-04de9ca6d52a3893.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-62527677bbc2fdc4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9a2e09c4a311764c.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-bfeb35d69e8b24bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-89cb33bced824e4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-b008aff96be56654.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-814394dcbae789b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-6a87325c87f09dd2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-6445ac4cbb8dd869.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-852170303c6cd755.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-087ceeb975ef272b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-97c7361cc2a19319.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-20162174b77f96cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-8c6901833f897496.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-05a4b2c9b91034aa.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/_next/static/{Q-7iofoxOEv1WX18S35of → dRS6lEhSRRBr1abbzp7fJ}/_buildManifest.js +1 -1
- 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 +7 -5
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- 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/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-substrate/acp-implementer.ts +14 -7
- package/src/agent-substrate/pr-reviewer.ts +30 -10
- package/src/agent-substrate/self-review-cli.ts +126 -10
- package/src/budget/cost-tier-advisor.ts +91 -0
- 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/doctor-cli.ts +21 -0
- 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/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +9 -7
- 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-requests-cli.ts +25 -0
- package/src/cli/tasks-cli.ts +31 -7
- package/src/cli/usage-cli.ts +3 -1
- package/src/compact/verify-probe.ts +23 -3
- package/src/context-card/index.ts +50 -0
- package/src/control/control-status.ts +30 -1
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +4 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/debug/log-diet.ts +16 -4
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +4 -0
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +375 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/runner.ts +9 -5
- 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 +56 -47
- package/src/harness/harness-stop.ts +82 -12
- package/src/index.ts +17 -175
- 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.ts +4 -8
- package/src/maturity/feature-maturity.ts +1 -1
- 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/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/release-loop/auto-start.ts +7 -5
- package/src/release-loop/checklist.ts +11 -1
- 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/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 +52 -4
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/run-supervisor.ts +37 -7
- 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 +12 -2
- 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 +88 -19
- package/src/self-implement/premise-review.ts +159 -0
- 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/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 +65 -0
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +151 -7
- package/src/task-agent/review-result-capture.ts +3 -1
- package/src/task-agent/shadow.ts +12 -0
- package/src/task-agent/task-hand.ts +4 -1
- 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 +235 -28
- package/src/user-config.ts +18 -4
- 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/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/design-check/page-26345242e4049f55.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/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 → dRS6lEhSRRBr1abbzp7fJ}/_ssgManifest.js +0 -0
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import { judgePredictionAccuracy, mustFixTrendFromHistory, renderJudgeOwnSignals, renderJudgePredictionAccuracy } from './judge-prediction-accuracy.js';
|
|
17
17
|
import { isElanousRuntimeArtifactPath } from './gate-scope.js';
|
|
18
|
+
import { buildPrConclusionCard, firstParagraphOf, prConclusionCardHeader } from '../context-card/index.js';
|
|
18
19
|
import { spawn, spawnSync, execFile } from 'node:child_process';
|
|
19
20
|
import { randomUUID, timingSafeEqual } from 'node:crypto';
|
|
20
21
|
import { existsSync, lstatSync, mkdtempSync, readFileSync, realpathSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
@@ -71,6 +72,7 @@ import { ghAutomationEnv, makePrManager, type PrManager } from '../autopilot/pr-
|
|
|
71
72
|
import { defaultSpawnGh, lookupOpenDraftPrs } from '../cli/logs-abandoned-draft-prs.js';
|
|
72
73
|
import { loadRunLedger, runLedgerDir } from './run-ledger.js';
|
|
73
74
|
import { readdirSync } from 'node:fs';
|
|
75
|
+
import { REVIEW_DEFERRED_TO_HOST_FAILURE } from './review-deferred-to-host.js';
|
|
74
76
|
import { budgetReviewerContext, reviewDiffBudgetObservation, reviewPullRequest, renderReview, type ReviewerContextItem } from '../agent-substrate/pr-reviewer.js';
|
|
75
77
|
import { buildReviewIntent, type ReviewIntentInput } from '../agent-substrate/review-intent.js';
|
|
76
78
|
import { OFF_DIFF_EVIDENCE_PROMPT, requiredEvidenceFromGoal, renderRequiredEvidencePrompt, tailWithOmissionMarker } from './off-diff-evidence.js';
|
|
@@ -849,16 +851,34 @@ export function changedFileTypecheck(
|
|
|
849
851
|
}
|
|
850
852
|
}
|
|
851
853
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
854
|
+
export interface PrBodyConclusionInput {
|
|
855
|
+
/** 결론줄 «포인터:» 에 붙일 원본 위치(원문 전문을 가리키는 참조). */
|
|
856
|
+
readonly pointers?: readonly string[];
|
|
857
|
+
/** 원문 본문을 읽지 못한 경우 — «결론: 확인 불가» 로 떨어진다. */
|
|
858
|
+
readonly unreadable?: boolean;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/** RFC context-diet §3a — PR 본문 첫 단락을 «결론: <한 줄> · 포인터: <원본>» 결론줄로 앞세우고
|
|
862
|
+
* 원문 본문은 결론줄 아래 그대로 둔다(지우지 않는다). 결론이 없으면 «결론: 없음(원문에 결론 없음)». */
|
|
863
|
+
export function buildPrBody(cwd: string, body: string, conclusion?: PrBodyConclusionInput): string {
|
|
864
|
+
const card = buildPrConclusionCard({
|
|
865
|
+
id: 'pr-body-conclusion',
|
|
866
|
+
firstParagraph: firstParagraphOf(body),
|
|
867
|
+
...(conclusion?.unreadable ? { unreadable: true } : {}),
|
|
868
|
+
pointers: [...(conclusion?.pointers ?? [])],
|
|
869
|
+
source: 'pr-body',
|
|
870
|
+
updatedAt: new Date().toISOString(),
|
|
871
|
+
});
|
|
872
|
+
const header = prConclusionCardHeader(card);
|
|
856
873
|
const templatePath = join(cwd, '.github', 'pull_request_template.md');
|
|
857
|
-
|
|
858
|
-
const
|
|
859
|
-
return template ? `${template}\n\n${
|
|
874
|
+
const template = existsSync(templatePath) ? readFileSync(templatePath, 'utf8').trim() : '';
|
|
875
|
+
const withConclusion = `${header}\n\n${body}`;
|
|
876
|
+
return template ? `${template}\n\n${withConclusion}` : withConclusion;
|
|
860
877
|
}
|
|
861
878
|
|
|
879
|
+
/** 헤드리스 elanous 가 이 feature 를 구현하도록 주입하는 프롬프트. goal-loop 계약 + 검증된 클린-빌드
|
|
880
|
+
* 앵커(측정→운영·[[REPORT-gemma-goalloop-lever-2026-07-20]])를 명시. 앵커가 gemma 를 99 로 끌어올렸고
|
|
881
|
+
* 강한 모델엔 무해 — self-run 어느 provider 든 동일 규율. */
|
|
862
882
|
export function featurePrompt(feature: string, cwd?: string, reviewerContext?: readonly ReviewerContextItem[]): string {
|
|
863
883
|
const worktreeNotice = cwd?.trim()
|
|
864
884
|
? `작업 디렉토리는 \`${cwd}\`다. 이 트리 안에서만 편집하고, 경로가 필요하면 추측하지 말고 이 경로를 기준으로 삼아라.`
|
|
@@ -1063,6 +1083,9 @@ export interface DefaultSeamsOptions {
|
|
|
1063
1083
|
* ⛔ llmReview 시그니처는 그대로(prompt-in/text-out · 도구 채널 없음).
|
|
1064
1084
|
*/
|
|
1065
1085
|
reviewerCanSelfRead?: boolean;
|
|
1086
|
+
/** REVIEW-ACP-POD ②-b — 참이면 reviewDiff 가 리뷰어를 부르지 않고 `reviewed=false` ⊕ `failureReason=deferred-to-host` 를 낸다
|
|
1087
|
+
* (발사 호스트가 Claude ACP 로 리뷰한다). 기본 거짓 = 종전. */
|
|
1088
|
+
reviewDeferredToHost?: boolean;
|
|
1066
1089
|
/** CLI가 적재한 리뷰어 컨텍스트. 비어 있으면 기존 ReviewInput 형태를 유지한다. */
|
|
1067
1090
|
reviewerContext?: ReviewerContextItem[];
|
|
1068
1091
|
/** 기존 LLM HITL relay builder의 테스트 seam. 생성 실패 시 기본 dispatch를 그대로 유지한다. */
|
|
@@ -2587,6 +2610,18 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2587
2610
|
...(o.reviewerCanSelfRead !== undefined ? { canSelfRead: o.reviewerCanSelfRead } : {}),
|
|
2588
2611
|
};
|
|
2589
2612
|
}
|
|
2613
|
+
if (o.reviewDeferredToHost) {
|
|
2614
|
+
// REVIEW-ACP-POD ②-b — 리뷰어 호출 0. ⛔ 통과로 꾸미지 않는다(reviewed=false) — 판정은 호스트 ACP 리뷰가 맡는다.
|
|
2615
|
+
debug.log('self-implement', 'review.done', {
|
|
2616
|
+
verdict: 'warn', reviewed: false, reason: REVIEW_DEFERRED_TO_HOST_FAILURE,
|
|
2617
|
+
...(ctx?.round !== undefined ? { round: ctx.round } : {}),
|
|
2618
|
+
});
|
|
2619
|
+
try { emitDecision(reviewDecision({ runId: ctx?.runId, verdict: 'warn', reviewed: false, reason: REVIEW_DEFERRED_TO_HOST_FAILURE })); } catch { /* observation must not change the review result */ }
|
|
2620
|
+
return {
|
|
2621
|
+
verdict: 'warn' as const, mustFix: [], shouldFix: [], summary: '(리뷰를 호스트 Claude ACP 리뷰로 미뤘다)', reviewed: false,
|
|
2622
|
+
failureReason: REVIEW_DEFERRED_TO_HOST_FAILURE, deferredToHost: true as const,
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2590
2625
|
const intentInput = toReviewIntentInput(ctx);
|
|
2591
2626
|
const phaseIntent = intentInput ? buildReviewIntent(intentInput) : 'self-implement 변경 리뷰';
|
|
2592
2627
|
const evidenceNote = [
|
|
@@ -44,7 +44,7 @@ import { enhanceAgentResultWithSeed } from '../../agent/seed.js';
|
|
|
44
44
|
import { resolveAgent } from '../../agent/loader.js';
|
|
45
45
|
import { resolveAgentLayered } from '../../agent/definition-registry.js';
|
|
46
46
|
import type { AgentDefinition } from '../../agent/types.js';
|
|
47
|
-
import { getSessionCwd } from '../../session/working-dir.js';
|
|
47
|
+
import { getSessionCwd, setSessionCwd } from '../../session/working-dir.js';
|
|
48
48
|
import {
|
|
49
49
|
agentCacheKey, dedupeStub, logDedupHit, type SessionCache,
|
|
50
50
|
DEDUP_CASCADE_HALT_THRESHOLD, CONSECUTIVE_DEDUP_BLOCK_THRESHOLD,
|
|
@@ -485,6 +485,11 @@ export async function dispatchAgent(
|
|
|
485
485
|
} else if (isolation === 'worktree') {
|
|
486
486
|
const { enterWorktreeRuntime } = await import('../../tool-runtime/git-worktree-runtimes.js');
|
|
487
487
|
const wtName = `${spawnName ?? definition.name}-${debugCorrelationId}`.replace(/[^a-zA-Z0-9._/-]/g, '-');
|
|
488
|
+
// enterWorktreeRuntime.run mutates the parent session cwd via
|
|
489
|
+
// setSessionCwd(path, 'tool'). Capture and restore so Agent(isolation:
|
|
490
|
+
// 'worktree') never leaks the child's worktree into the parent status
|
|
491
|
+
// line — enter_worktree (human-invoked) still moves cwd intentionally.
|
|
492
|
+
const parentCwd = getSessionCwd();
|
|
488
493
|
try {
|
|
489
494
|
const wt = await enterWorktreeRuntime.run({ name: wtName }, { surface: 'skill' as any });
|
|
490
495
|
childCwd = wt.path;
|
|
@@ -506,6 +511,16 @@ export async function dispatchAgent(
|
|
|
506
511
|
requestedIsolation: 'worktree',
|
|
507
512
|
reason: message,
|
|
508
513
|
}, { level: 'warn' });
|
|
514
|
+
} finally {
|
|
515
|
+
const afterCwd = getSessionCwd();
|
|
516
|
+
if (afterCwd !== parentCwd) {
|
|
517
|
+
setSessionCwd(parentCwd, 'tool');
|
|
518
|
+
debug.log('agent.spawn', 'worktree-parent-cwd-restored', {
|
|
519
|
+
agent: definition.name,
|
|
520
|
+
from: afterCwd,
|
|
521
|
+
to: parentCwd,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
509
524
|
}
|
|
510
525
|
} else {
|
|
511
526
|
childCwd = opts.cwd ?? getSessionCwd();
|
|
@@ -153,6 +153,16 @@ function rejectionSample(value: string): string {
|
|
|
153
153
|
return value.slice(0, EVIDENCE_REJECTION_SAMPLE_PREFIX_LENGTH);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
function stripLeadingListMarkers(line: string): string {
|
|
157
|
+
let stripped = line;
|
|
158
|
+
let previous: string;
|
|
159
|
+
do {
|
|
160
|
+
previous = stripped;
|
|
161
|
+
stripped = stripped.replace(/^\s*(?:[-*+•]|\d+[.)])\s+/, '');
|
|
162
|
+
} while (stripped !== previous);
|
|
163
|
+
return stripped;
|
|
164
|
+
}
|
|
165
|
+
|
|
156
166
|
function verifiedEvidenceFromCompletion(evidence: string, readFiles: Set<string>): { files: string[]; evidence: string[]; rejection: EvidenceRejection } {
|
|
157
167
|
const lines = evidence.split(/\r?\n/).filter((line) => line.trim());
|
|
158
168
|
const rejection: {
|
|
@@ -185,7 +195,7 @@ function verifiedEvidenceFromCompletion(evidence: string, readFiles: Set<string>
|
|
|
185
195
|
return hasPath && insideRoot && unreadPaths.length === 0 && hasMeaningfulText;
|
|
186
196
|
});
|
|
187
197
|
const files = Array.from(new Set(verifiedLines.flatMap(repositoryRelativeCodePaths)));
|
|
188
|
-
return { files, evidence: verifiedLines, rejection };
|
|
198
|
+
return { files, evidence: verifiedLines.map(stripLeadingListMarkers), rejection };
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
function groundingMessages(goal: string, terms: readonly string[]): LLMMessage[] {
|
|
@@ -113,7 +113,7 @@ export interface RunShellDispatchResult extends Record<string, unknown> {
|
|
|
113
113
|
* follow in the structured fields below. */
|
|
114
114
|
output: string;
|
|
115
115
|
exitCode: number | null;
|
|
116
|
-
outcome: ShellResult['outcome'];
|
|
116
|
+
outcome: ShellResult['outcome'] | 'started';
|
|
117
117
|
elapsedMs: number;
|
|
118
118
|
stdout: string;
|
|
119
119
|
stderr: string;
|
|
@@ -260,6 +260,38 @@ async function dispatchViaRunner(args: {
|
|
|
260
260
|
...(args.signal !== undefined ? { signal: args.signal } : {}),
|
|
261
261
|
};
|
|
262
262
|
const handle = runnerDispatch(req, args.deps);
|
|
263
|
+
if (args.mode === 'bg') {
|
|
264
|
+
const bgStartedAt = Date.now();
|
|
265
|
+
void handle.result.then(
|
|
266
|
+
(result) => {
|
|
267
|
+
debug.log('skill-tool.shell', 'bg-finished', {
|
|
268
|
+
handle: handle.id,
|
|
269
|
+
exitCode: result.exitCode ?? null,
|
|
270
|
+
durationMs: result.durationMs,
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
(err: unknown) => {
|
|
274
|
+
debug.log('skill-tool.shell', 'bg-finished', {
|
|
275
|
+
handle: handle.id,
|
|
276
|
+
exitCode: null,
|
|
277
|
+
durationMs: Date.now() - bgStartedAt,
|
|
278
|
+
error: err instanceof Error ? err.message : String(err),
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
return {
|
|
283
|
+
output: `RunShell outcome=started handle=${handle.id} bg=${handle.id}`,
|
|
284
|
+
exitCode: null,
|
|
285
|
+
outcome: 'started',
|
|
286
|
+
elapsedMs: 0,
|
|
287
|
+
stdout: '',
|
|
288
|
+
stderr: '',
|
|
289
|
+
truncated: false,
|
|
290
|
+
approvalKey: `runner:${handle.id}`,
|
|
291
|
+
sandboxed: false,
|
|
292
|
+
sandboxTool: 'none',
|
|
293
|
+
};
|
|
294
|
+
}
|
|
263
295
|
const result = await handle.result;
|
|
264
296
|
return runnerToLegacyResult(handle.id, result);
|
|
265
297
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TA-REJUDGE-PERIODIC — the steward (coordinator) tick re-runs `tasks rejudge --all` on a cadence.
|
|
3
|
+
*
|
|
4
|
+
* `tasks rejudge` only ran when someone typed it (OP bridged the gap with a 30-minute shell loop). This node is the
|
|
5
|
+
* product form: the steward graph already ticks every 15 minutes, so the rejudge rides that tick — no new resident loop.
|
|
6
|
+
*
|
|
7
|
+
* - Off by default: `taskAgent.rejudgeEveryMinutes` absent/0 → one `disabled` line per tick and nothing else.
|
|
8
|
+
* Rejudge can land PRs (per `taskAgent.liveMoves`), so it is switched on by an operator, not by an upgrade.
|
|
9
|
+
* - Cadence: due when the last started run is ≥ interval − 2 min ago (tick start jitter must not skip a whole tick).
|
|
10
|
+
* - Load guard: 1-minute load average above `taskAgent.rejudgeMaxLoad` (default 60) skips this tick without stamping,
|
|
11
|
+
* so the next tick retries.
|
|
12
|
+
* - Fail-soft: every outcome exits 0 — a rejudge problem never stops the steward's own stages.
|
|
13
|
+
* - Observation: one `debug.log('loop.steward', 'rejudge-tick', …)` per tick.
|
|
14
|
+
*/
|
|
15
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
+
import { loadavg } from 'node:os';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
import { debug } from '../debug/log.js';
|
|
19
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
20
|
+
import { spawnElanous } from '../instance/spawn-elanous.js';
|
|
21
|
+
import { getUserConfig } from '../user-config.js';
|
|
22
|
+
|
|
23
|
+
export const REJUDGE_TICK_EVENT = 'rejudge-tick';
|
|
24
|
+
export const REJUDGE_DEFAULT_MAX_LOAD = 60;
|
|
25
|
+
export const REJUDGE_JITTER_MS = 2 * 60_000;
|
|
26
|
+
export const REJUDGE_TIMEOUT_MS = 600_000;
|
|
27
|
+
|
|
28
|
+
export type RejudgeTickDecision = 'disabled' | 'not-due' | 'load-skip' | 'ran' | 'failed';
|
|
29
|
+
|
|
30
|
+
export interface RejudgeTickResult {
|
|
31
|
+
decision: RejudgeTickDecision;
|
|
32
|
+
everyMinutes: number | null;
|
|
33
|
+
load?: number;
|
|
34
|
+
maxLoad?: number;
|
|
35
|
+
lastStartedAt?: string | null;
|
|
36
|
+
rc?: number | null;
|
|
37
|
+
timedOut?: boolean;
|
|
38
|
+
cards?: number;
|
|
39
|
+
decisions?: Record<string, number>;
|
|
40
|
+
ms?: number;
|
|
41
|
+
reason?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RejudgeRun { code: number | null; stdout: string; stderr: string; timedOut: boolean }
|
|
45
|
+
|
|
46
|
+
export interface RejudgeTickDeps {
|
|
47
|
+
now?: () => Date;
|
|
48
|
+
/** `taskAgent.rejudgeEveryMinutes` / `taskAgent.rejudgeMaxLoad` — default reads the user config. */
|
|
49
|
+
config?: () => { rejudgeEveryMinutes?: number; rejudgeMaxLoad?: number } | undefined;
|
|
50
|
+
load?: () => number;
|
|
51
|
+
stampPath?: string;
|
|
52
|
+
run?: () => Promise<RejudgeRun>;
|
|
53
|
+
log?: (event: string, data: Record<string, unknown>) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function defaultStampPath(): string {
|
|
57
|
+
// Resolved at call time, in the node process's own universe (prod cron vs --test graph run).
|
|
58
|
+
return join(effectiveInstanceRoot(), 'steward', 'rejudge-tick.json');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function readStamp(path: string): string | null {
|
|
62
|
+
try {
|
|
63
|
+
const value = (JSON.parse(readFileSync(path, 'utf8')) as { startedAt?: unknown }).startedAt;
|
|
64
|
+
return typeof value === 'string' && Number.isFinite(Date.parse(value)) ? value : null;
|
|
65
|
+
} catch { return null; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Same universe as this process (env inherited) · same installed version (entry next to this module). */
|
|
69
|
+
export function defaultRejudgeRun(timeoutMs = REJUDGE_TIMEOUT_MS): Promise<RejudgeRun> {
|
|
70
|
+
return new Promise(done => {
|
|
71
|
+
const child = spawnElanous(['tasks', 'rejudge', '--all', '--json'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
72
|
+
let stdout = '';
|
|
73
|
+
let stderr = '';
|
|
74
|
+
let timedOut = false;
|
|
75
|
+
const timer = setTimeout(() => { timedOut = true; child.kill('SIGTERM'); }, timeoutMs);
|
|
76
|
+
child.stdout?.on('data', chunk => { stdout += String(chunk); });
|
|
77
|
+
child.stderr?.on('data', chunk => { stderr += String(chunk); });
|
|
78
|
+
child.on('error', error => { clearTimeout(timer); done({ code: null, stdout, stderr: `${stderr}${error.message}`, timedOut }); });
|
|
79
|
+
child.on('close', code => { clearTimeout(timer); done({ code, stdout, stderr, timedOut }); });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The last `[...]` line of `tasks rejudge --all --json` → card count and a decision histogram. */
|
|
84
|
+
function summarize(stdout: string): { cards: number; decisions: Record<string, number> } | null {
|
|
85
|
+
const line = stdout.split('\n').map(text => text.trim()).filter(text => text.startsWith('[')).at(-1);
|
|
86
|
+
if (!line) return null;
|
|
87
|
+
try {
|
|
88
|
+
const rows = JSON.parse(line) as Array<{ card?: unknown; decision?: unknown }>;
|
|
89
|
+
if (!Array.isArray(rows)) return null;
|
|
90
|
+
const decisions: Record<string, number> = {};
|
|
91
|
+
for (const row of rows) { const key = String(row?.decision ?? 'unknown'); decisions[key] = (decisions[key] ?? 0) + 1; }
|
|
92
|
+
return { cards: new Set(rows.map(row => String(row?.card))).size, decisions };
|
|
93
|
+
} catch { return null; }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function positive(value: unknown): number | null {
|
|
97
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function rejudgeTick(deps: RejudgeTickDeps = {}): Promise<RejudgeTickResult> {
|
|
101
|
+
const log = deps.log ?? ((event, data) => debug.log('loop.steward', event, data));
|
|
102
|
+
const emit = (result: RejudgeTickResult): RejudgeTickResult => {
|
|
103
|
+
try { log(REJUDGE_TICK_EVENT, { ...result }); } catch { /* fail-soft */ }
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
try {
|
|
107
|
+
const cfg = (deps.config ?? (() => getUserConfig().taskAgent))();
|
|
108
|
+
const everyMinutes = positive(cfg?.rejudgeEveryMinutes);
|
|
109
|
+
if (everyMinutes === null) return emit({ decision: 'disabled', everyMinutes: null, reason: 'taskAgent.rejudgeEveryMinutes unset' });
|
|
110
|
+
const now = (deps.now ?? (() => new Date()))();
|
|
111
|
+
const stampPath = deps.stampPath ?? defaultStampPath();
|
|
112
|
+
const lastStartedAt = readStamp(stampPath);
|
|
113
|
+
if (lastStartedAt && now.getTime() - Date.parse(lastStartedAt) < everyMinutes * 60_000 - REJUDGE_JITTER_MS) {
|
|
114
|
+
return emit({ decision: 'not-due', everyMinutes, lastStartedAt });
|
|
115
|
+
}
|
|
116
|
+
const maxLoad = positive(cfg?.rejudgeMaxLoad) ?? REJUDGE_DEFAULT_MAX_LOAD;
|
|
117
|
+
const load = (deps.load ?? (() => loadavg()[0] ?? 0))();
|
|
118
|
+
if (load > maxLoad) return emit({ decision: 'load-skip', everyMinutes, load, maxLoad, lastStartedAt });
|
|
119
|
+
// Claim before running so an overlapping steward tick does not start a second rejudge.
|
|
120
|
+
mkdirSync(dirname(stampPath), { recursive: true });
|
|
121
|
+
writeFileSync(stampPath, JSON.stringify({ startedAt: now.toISOString() }));
|
|
122
|
+
const started = Date.now();
|
|
123
|
+
const run = await (deps.run ?? (() => defaultRejudgeRun()))();
|
|
124
|
+
const summary = summarize(run.stdout);
|
|
125
|
+
const ok = run.code === 0 && !run.timedOut && summary !== null;
|
|
126
|
+
return emit({
|
|
127
|
+
decision: ok ? 'ran' : 'failed', everyMinutes, load, maxLoad, lastStartedAt, rc: run.code, timedOut: run.timedOut,
|
|
128
|
+
cards: summary?.cards ?? 0, decisions: summary?.decisions ?? {}, ms: Date.now() - started,
|
|
129
|
+
...(ok ? {} : { reason: (run.stderr || run.stdout).trim().slice(-300) || (summary === null ? 'no JSON result line' : 'nonzero exit') }),
|
|
130
|
+
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
return emit({ decision: 'failed', everyMinutes: null, reason: (error instanceof Error ? error.message : String(error)).slice(-300) });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (import.meta.main) {
|
|
137
|
+
try { await (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink('steward'); }
|
|
138
|
+
catch (error) { console.error(`steward rejudge: log sink registration failed — ${error instanceof Error ? error.message : String(error)}`); }
|
|
139
|
+
const result = await rejudgeTick();
|
|
140
|
+
console.log(`steward rejudge: ${result.decision}${result.reason ? ` — ${result.reason}` : ''}`);
|
|
141
|
+
process.exitCode = 0;
|
|
142
|
+
}
|
package/src/task-agent/board.ts
CHANGED
|
@@ -7,13 +7,42 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
+
import { debug } from '../debug/log.js';
|
|
10
11
|
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
11
12
|
import { listChecklist, type ChecklistStatus } from '../release-loop/checklist.js';
|
|
12
|
-
import {
|
|
13
|
+
import { buildRunProgressRows, queryRunningRuns, type RunningRunsResult, type RunProgressRow } from '../self-implement/running-runs.js';
|
|
14
|
+
import {
|
|
15
|
+
cardPrNumber, CLOSED_BY_HAND_EVENT, HAND_MOVE_HISTORY_EVENT, LIVE_MOVE_HISTORY_EVENT, LIVE_MOVE_RESULT_EVENT, readTaskAgentState,
|
|
16
|
+
type CompletionKind, type TaskCard,
|
|
17
|
+
} from './task-hand.js';
|
|
13
18
|
|
|
14
19
|
export type BoardLevel = 'project' | 'goal' | 'milestone' | 'task';
|
|
15
20
|
export type BoardStatus = 'open' | 'done' | 'blocked';
|
|
16
21
|
|
|
22
|
+
/** 카드 원장(task-agent-actions.json)에 적힌 사실만 — 없는 칸은 null(지어내지 않는다). */
|
|
23
|
+
export interface BoardTaskLedger {
|
|
24
|
+
runId: string | null;
|
|
25
|
+
pr: number | null;
|
|
26
|
+
/** 카드 상태(handed · launched · launch-failed · failed). */
|
|
27
|
+
lastStatus: TaskCard['status'];
|
|
28
|
+
/** 관측 기록(live-move · hand-move)을 뺀 history 의 마지막 줄. */
|
|
29
|
+
lastEvent: { at: string; event: string; detail: string | null } | null;
|
|
30
|
+
/** 카드가 failed · launch-failed 일 때 마지막 줄의 사유(예: `failed/needs-owner — exit 1 · pod-failure`). 그 밖에는 null. */
|
|
31
|
+
exitReason: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** `GET /api/task-agent/board` 응답 — progress 는 진전 관측(`queryRunningRuns`)을 싣는다; 관측을 못 얻으면 null(0을 «없다»로 쓰지 않는다). */
|
|
35
|
+
export interface TaskAgentBoardResponse { board: BoardNode[]; progress: TaskAgentBoardProgress | null }
|
|
36
|
+
|
|
37
|
+
/** 진전 관측 칸 — 행은 기존 `RunProgressRow` 형식 그대로(새 행 형식을 만들지 않는다). 과제 노드와는 `ledger.runId` ↔ `rows[].runId` 로만 짝짓는다(ledger 에 새 칸은 없다). */
|
|
38
|
+
export interface TaskAgentBoardProgress {
|
|
39
|
+
readonly rows: readonly RunProgressRow[];
|
|
40
|
+
/** 관측이 부분(running 수가 `{ count: null, lowerBound }` 꼴이거나 읽지 못한 원장 unreadable 이 있으면)이면 true · 아니면 false. */
|
|
41
|
+
readonly partial: boolean;
|
|
42
|
+
/** 부분 관측일 때의 최소 running 수 · 완전 관측이면 null. */
|
|
43
|
+
readonly lowerBound: number | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
17
46
|
export interface BoardNode {
|
|
18
47
|
level: BoardLevel;
|
|
19
48
|
id: string;
|
|
@@ -21,6 +50,8 @@ export interface BoardNode {
|
|
|
21
50
|
status: BoardStatus;
|
|
22
51
|
/** 과제 노드만 — 카드의 종결 종류(비면 code-pr 로 읽는다 · 칸은 싣지 않는다). */
|
|
23
52
|
completion?: CompletionKind;
|
|
53
|
+
/** 과제 노드만 · `cardsBoard(…, { ledger: true })` 일 때만 — 카드 원장에서 읽은 런·PR·마지막 상태·종료 이유. */
|
|
54
|
+
ledger?: BoardTaskLedger;
|
|
24
55
|
/** 부모 노드 id(프로젝트는 없다). */
|
|
25
56
|
parent?: string;
|
|
26
57
|
/** 프로젝트 노드만 — 프로젝트 없는 카드의 자리(id 는 빈 문자열이라 실제 프로젝트 id 와 겹치지 않는다). */
|
|
@@ -60,8 +91,28 @@ function cardStatus(card: TaskCard): BoardStatus {
|
|
|
60
91
|
return card.greenProposal ? 'done' : 'open';
|
|
61
92
|
}
|
|
62
93
|
|
|
63
|
-
|
|
64
|
-
|
|
94
|
+
function cardLedger(card: TaskCard): BoardTaskLedger {
|
|
95
|
+
const last = (card.history ?? [])
|
|
96
|
+
.filter((item) => item.event !== LIVE_MOVE_HISTORY_EVENT && item.event !== LIVE_MOVE_RESULT_EVENT && item.event !== HAND_MOVE_HISTORY_EVENT)
|
|
97
|
+
.at(-1);
|
|
98
|
+
const ended = card.status === 'failed' || card.status === 'launch-failed';
|
|
99
|
+
// ⚠️ 종료 이유 = «관측 줄을 뺀 마지막 줄»의 detail 만 본다 — 그 줄이 detail 없는 run-bound·pr-bound 면 null(지어내지 않음 · 앞줄을 거슬러 찾지 않는다).
|
|
100
|
+
// 관측 줄 거르기는 task-hand.ts(wait 사유)와 같은 셋이다 — 공용 헬퍼로 묶는 것은 다음 조각(UX 수확 리뷰 should-fix).
|
|
101
|
+
const reason = last ? (last.event === CLOSED_BY_HAND_EVENT ? last.reason ?? last.detail : last.detail) : undefined;
|
|
102
|
+
return {
|
|
103
|
+
runId: card.runId ?? null,
|
|
104
|
+
pr: cardPrNumber(card) ?? null,
|
|
105
|
+
lastStatus: card.status,
|
|
106
|
+
lastEvent: last ? { at: last.at, event: last.event, detail: last.detail ?? null } : null,
|
|
107
|
+
exitReason: ended ? reason ?? null : null,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 과제 카드 → 프로젝트 트리. 프로젝트 없는 카드는 «무소속»(`unassigned: true` · id '') 아래 — 어떤 프로젝트 id 로도 걸러지지 않는다.
|
|
113
|
+
* `ledger: true` 면 과제 노드마다 카드 원장 사실(`ledger`)을 붙인다 — 기본(CLI)은 그대로다.
|
|
114
|
+
*/
|
|
115
|
+
export function cardsBoard(statePath: string, options: { ledger?: boolean } = {}): BoardNode[] {
|
|
65
116
|
const projects: BoardNode[] = [];
|
|
66
117
|
const cards = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {};
|
|
67
118
|
for (const card of Object.values(cards)) {
|
|
@@ -77,6 +128,7 @@ export function cardsBoard(statePath: string): BoardNode[] {
|
|
|
77
128
|
milestone.children!.push({
|
|
78
129
|
level: 'task', id: card.id, title: card.text, status: cardStatus(card),
|
|
79
130
|
...(card.completion ? { completion: card.completion } : {}),
|
|
131
|
+
...(options.ledger ? { ledger: cardLedger(card) } : {}),
|
|
80
132
|
parent: milestone.id,
|
|
81
133
|
});
|
|
82
134
|
}
|
|
@@ -84,6 +136,43 @@ export function cardsBoard(statePath: string): BoardNode[] {
|
|
|
84
136
|
return projects;
|
|
85
137
|
}
|
|
86
138
|
|
|
139
|
+
/** `taskAgentBoard` 주입 자리 — 시험은 관측을 갈아끼워 결정성을 얻는다. */
|
|
140
|
+
export interface TaskAgentBoardDeps {
|
|
141
|
+
/** 진전 관측. 기본 = `queryRunningRuns({ caller: 'task-agent.board' })`. 던지면 progress=null — 보드는 그대로 돌려준다. */
|
|
142
|
+
readonly runningRuns?: () => RunningRunsResult;
|
|
143
|
+
/** 경과 계산의 기준 시각(`buildRunProgressRows` 의 nowMs) · 기본 = Date.now(). */
|
|
144
|
+
readonly nowMs?: number;
|
|
145
|
+
/** 진전 관측을 돌릴지 — 기본 false(progress=null · «요청 안 함»). ⛔ 운영 원장에서 queryRunningRuns 는 동기 수 초(10-12 실측 4.3초)라
|
|
146
|
+
* 데몬 이벤트 루프를 멈춘다 → 라우트는 `?progress=1` 일 때만 켠다(UX 수확 리뷰 should-fix). runningRuns 를 주입하면 이 값과 무관하게 돈다. */
|
|
147
|
+
readonly withProgress?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** 관측 결과 → progress 칸. running 수가 `{ count: null, lowerBound }` 꼴이거나 읽지 못한 원장(unreadable)이 있으면 부분 관측으로 친다. */
|
|
151
|
+
function runProgressFrom(result: RunningRunsResult, nowMs: number): TaskAgentBoardProgress {
|
|
152
|
+
const objectCount = result.count !== undefined && typeof result.count !== 'number' ? result.count : null;
|
|
153
|
+
// 판정 출처는 관측 결과의 completeness 가 1순위 — count 꼴·unreadable 은 그것이 없을 때의 보조다.
|
|
154
|
+
const partial = result.completeness === 'partial' || objectCount !== null || (result.unreadable?.length ?? 0) > 0;
|
|
155
|
+
return {
|
|
156
|
+
rows: buildRunProgressRows(result, nowMs),
|
|
157
|
+
partial,
|
|
158
|
+
lowerBound: partial ? (objectCount !== null ? objectCount.lowerBound : result.counts.running + result.counts['probable-running']) : null,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** 읽기 전용 — 원장이 없으면 빈 보드. 원장이 손상됐으면 `TaskAgentStateError` 를 그대로 던진다(빈 보드로 속이지 않는다). progress 는 진전 관측을 싣는다 — 관측이 던지면 progress=null(0을 «없다»로 쓰지 않는다) · 보드는 그대로. */
|
|
163
|
+
export function taskAgentBoard(statePath: string, deps: TaskAgentBoardDeps = {}): TaskAgentBoardResponse {
|
|
164
|
+
const board = cardsBoard(statePath, { ledger: true });
|
|
165
|
+
if (!deps.runningRuns && !deps.withProgress) return { board, progress: null };
|
|
166
|
+
const observe = deps.runningRuns ?? (() => queryRunningRuns({ caller: 'task-agent.board' }));
|
|
167
|
+
let progress: TaskAgentBoardProgress | null = null;
|
|
168
|
+
try {
|
|
169
|
+
progress = runProgressFrom(observe(), deps.nowMs ?? Date.now());
|
|
170
|
+
} catch (error) {
|
|
171
|
+
debug.log('task-agent', 'board-progress-unavailable', { error: error instanceof Error ? error.message : String(error) });
|
|
172
|
+
}
|
|
173
|
+
return { board, progress };
|
|
174
|
+
}
|
|
175
|
+
|
|
87
176
|
function releaseStatus(status: ChecklistStatus): BoardStatus {
|
|
88
177
|
return status === 'green' || status === 'done' ? 'done' : status === 'red' ? 'blocked' : 'open';
|
|
89
178
|
}
|
|
@@ -13,7 +13,7 @@ import { readRunExits, type RunExit } from '../harness/harness-incidents.js';
|
|
|
13
13
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
14
14
|
import { debug } from '../debug/log.js';
|
|
15
15
|
import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
|
|
16
|
-
import type
|
|
16
|
+
import { appendRunLedgerEntry, type RunLedgerEntry } from '../self-implement/run-ledger.js';
|
|
17
17
|
import { cardPrNumber, taskAgentStatePath, updateTaskCard, readTaskCard, type TaskCard } from './task-hand.js';
|
|
18
18
|
import { judgeNextMove, type TaskJudgeInput } from './judge.js';
|
|
19
19
|
import { remoteParentAlive, type SshRunner } from './parent-host.js';
|
|
@@ -342,3 +342,90 @@ export async function refreshCardRunBinding(cardId: string, statePath = taskAgen
|
|
|
342
342
|
}
|
|
343
343
|
return { card: next, evidence };
|
|
344
344
|
}
|
|
345
|
+
|
|
346
|
+
/** TA-WIRING-CHECK — `live-verified` 원장 줄의 이벤트 이름 · 카드 런 원장에 적는다. */
|
|
347
|
+
export const WIRING_LIVE_VERIFIED_EVENT = 'live-verified';
|
|
348
|
+
|
|
349
|
+
export interface WiringLiveVerifiedInput { pr: number; ref: string; ok: boolean }
|
|
350
|
+
export interface WiringLiveVerifiedDeps { ledgerDir?: string; now?: () => Date }
|
|
351
|
+
export type WiringLiveVerifiedOutcome = { written: true; entry: RunLedgerEntry } | { written: false; reason: string };
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* 실물 1회를 돌린 뒤 남기는 기록 — 카드 런 원장에 `live-verified {pr, ref, ok, card}` 한 줄.
|
|
355
|
+
* `ref`(실물로 돌린 명령·화면 근거)가 비거나 카드에 런이 없거나 PR 번호가 자연수가 아니면 거부하고 쓰지 않는다.
|
|
356
|
+
*/
|
|
357
|
+
export function recordWiringLiveVerified(card: Pick<TaskCard, 'id' | 'runId'>, input: WiringLiveVerifiedInput, deps: WiringLiveVerifiedDeps = {}): WiringLiveVerifiedOutcome {
|
|
358
|
+
const ref = typeof input.ref === 'string' ? input.ref.trim() : '';
|
|
359
|
+
if (!ref) return { written: false, reason: 'ref 가 비었다 — 실물로 돌린 명령·화면 근거 한 줄이 필요하다' };
|
|
360
|
+
if (!Number.isSafeInteger(input.pr) || input.pr <= 0) return { written: false, reason: `pr 은 자연수다: ${input.pr}` };
|
|
361
|
+
if (!card.runId) return { written: false, reason: `카드 ${card.id} 에 런(runId)이 없다 — 기록할 원장이 없다` };
|
|
362
|
+
const entry: RunLedgerEntry = {
|
|
363
|
+
timestamp: (deps.now ?? (() => new Date()))().toISOString(),
|
|
364
|
+
runId: card.runId,
|
|
365
|
+
event: WIRING_LIVE_VERIFIED_EVENT,
|
|
366
|
+
data: { pr: input.pr, ref, ok: input.ok, card: card.id },
|
|
367
|
+
};
|
|
368
|
+
try {
|
|
369
|
+
appendRunLedgerEntry(entry, deps.ledgerDir);
|
|
370
|
+
} catch (error) {
|
|
371
|
+
return { written: false, reason: `원장 쓰기 실패: ${(error instanceof Error ? error.message : String(error)).slice(0, 200)}` };
|
|
372
|
+
}
|
|
373
|
+
return { written: true, entry };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export interface WiringEvidence {
|
|
377
|
+
/** 이 PR 이 배선(진입점·명령 등록·호출자 대입)을 바꿨나 — 그렇다면 실물 1회가 필요하다. */
|
|
378
|
+
required: boolean;
|
|
379
|
+
/** 카드 런 원장에 이 PR 의 `live-verified` ok 기록이 있나. */
|
|
380
|
+
liveRunRecorded: boolean;
|
|
381
|
+
/** 근거를 못 읽었다(gh 실패 · 원장 읽기 실패) — 관측만 하고 green 을 막지 않는다. */
|
|
382
|
+
unknown: boolean;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface WiringEvidenceDeps {
|
|
386
|
+
/** 카드 — 없으면 liveRunRecorded 는 false. */
|
|
387
|
+
card?: Pick<TaskCard, 'id' | 'runId'>;
|
|
388
|
+
/** `gh pr diff <pr>` 의 통합 diff 원문 — 한 번만 부른다(시험 주입). */
|
|
389
|
+
prDiff?: (pr: number) => string | Promise<string>;
|
|
390
|
+
loadLedger?: (runId: string) => RunLedgerEntry[] | null;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const WIRING_PATH = /(^|\/)(bin|scripts|cli)\/|(^|\/)[^/]*(install|auth|entrypoint)[^/]*$/i;
|
|
394
|
+
const NON_WIRING_PATH = /^docs\/|\.md$|\.test\.[cm]?[jt]sx?$/;
|
|
395
|
+
const WIRING_LINE = /\bregisterCommand\b|\.command\(|\.set\(|\.on\(|\bhandlers(?:\.\w+|\[[^\]]+\])\s*=(?!=)/;
|
|
396
|
+
|
|
397
|
+
async function defaultPrDiff(pr: number): Promise<string> {
|
|
398
|
+
const { execFile } = await import('node:child_process');
|
|
399
|
+
return new Promise((resolveDiff, reject) => {
|
|
400
|
+
execFile('gh', ['pr', 'diff', String(pr)], { encoding: 'utf8', timeout: 30_000, maxBuffer: 32 * 1024 * 1024 }, (error, stdout) => (error ? reject(error) : resolveDiff(stdout)));
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** 순수 — 통합 diff 가 배선을 바꾸나. 문서·시험 파일은 보지 않는다. */
|
|
405
|
+
export function diffTouchesWiring(diff: string): boolean {
|
|
406
|
+
for (const chunk of diff.split(/^diff --git /m)) {
|
|
407
|
+
const path = /^\S+ b\/(\S+)/.exec(chunk)?.[1] ?? '';
|
|
408
|
+
if (path && NON_WIRING_PATH.test(path)) continue;
|
|
409
|
+
if (path && WIRING_PATH.test(path)) return true;
|
|
410
|
+
const added = chunk.split('\n').filter((line) => line.startsWith('+') && !line.startsWith('+++'));
|
|
411
|
+
if (added.some((line) => WIRING_LINE.test(line))) return true;
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* 수집기 — 판단부(judge.ts) 밖에서만 gh 를 부른다. PR diff 는 «한 번» 읽고, gh·원장 읽기 실패는 던지지 않고 `unknown: true` 로 돌려준다.
|
|
418
|
+
*/
|
|
419
|
+
export async function collectWiringEvidence(pr: number, deps: WiringEvidenceDeps = {}): Promise<WiringEvidence> {
|
|
420
|
+
let unknown = false;
|
|
421
|
+
let required = false;
|
|
422
|
+
try { required = diffTouchesWiring(await (deps.prDiff ?? defaultPrDiff)(pr)); } catch { unknown = true; }
|
|
423
|
+
let liveRunRecorded = false;
|
|
424
|
+
if (deps.card?.runId) {
|
|
425
|
+
try {
|
|
426
|
+
const entries = (deps.loadLedger ?? await defaultLoadLedger())(deps.card.runId) ?? [];
|
|
427
|
+
liveRunRecorded = entries.some((entry) => entry.event === WIRING_LIVE_VERIFIED_EVENT && entry.data?.ok === true && entry.data?.pr === pr);
|
|
428
|
+
} catch { unknown = true; }
|
|
429
|
+
}
|
|
430
|
+
return { required, liveRunRecorded, unknown };
|
|
431
|
+
}
|
package/src/task-agent/cover.ts
CHANGED
|
@@ -157,3 +157,68 @@ export function formatTaskAgentCover(row: CoverRow): string {
|
|
|
157
157
|
const value = (count: number | null): string => count === null ? '-' : String(count);
|
|
158
158
|
return `${row.verb}: TA ${value(row.byTaskAgent)}/${value(row.total)} (${row.ratio === null ? '-' : `${(row.ratio * 100).toFixed(1)}%`}) · live ${value(row.liveActions)} · shadow ${value(row.shadowActions)} · steward-transition ${row.stewardTransition}`;
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
/** 7동사의 이름 — 리뷰·착지·수리·검증·저작·구현·정리 (decision·deliver 는 7동사 밖이라 세지 않는다). */
|
|
162
|
+
export type SevenVerbName = '리뷰' | '착지' | '수리' | '검증' | '저작' | '구현' | '정리';
|
|
163
|
+
|
|
164
|
+
/** no-source 는 출처 배선이 아직 없는 동사 · unreadable 은 TASK-AGENT 행동 원장을 못 읽은 것이다. */
|
|
165
|
+
export type SevenVerbState = 'live' | 'shadow-only' | 'none' | 'no-source' | 'unreadable';
|
|
166
|
+
|
|
167
|
+
/** 7동사 출처 표의 한 칸 — source 는 그 동사를 관측하는 TASK-AGENT action kind, null 이면 출처가 아직 없다. */
|
|
168
|
+
export interface SevenVerbSource {
|
|
169
|
+
verb: SevenVerbName;
|
|
170
|
+
source: Exclude<NextActionKind, 'decision' | 'deliver'> | null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** TA-THEME-VERBS-LIVE — 7동사와 출처 표(코드로 고정). 저작·구현·정리의 출처 배선은 다음 조각. */
|
|
174
|
+
export const SEVEN_VERB_SOURCES: readonly SevenVerbSource[] = [
|
|
175
|
+
{ verb: '리뷰', source: 'review' },
|
|
176
|
+
{ verb: '착지', source: 'land' },
|
|
177
|
+
{ verb: '수리', source: 'retry' },
|
|
178
|
+
{ verb: '검증', source: 'green' },
|
|
179
|
+
{ verb: '저작', source: null },
|
|
180
|
+
{ verb: '구현', source: null },
|
|
181
|
+
{ verb: '정리', source: null },
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
/** 동사 하나의 관측 — 원장을 못 읽었으면 liveDone·shadow 는 null(0 이 아니다). */
|
|
185
|
+
export interface SevenVerbLiveRow {
|
|
186
|
+
verb: SevenVerbName;
|
|
187
|
+
source: SevenVerbSource['source'];
|
|
188
|
+
liveDone: number | null;
|
|
189
|
+
shadow: number | null;
|
|
190
|
+
state: SevenVerbState;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** 합계 — liveVerbs 는 원장을 못 읽었으면 null(0 으로 쓰지 않는다) · measuredVerbs 는 출처 있는 동사 수. */
|
|
194
|
+
export interface SevenVerbLive {
|
|
195
|
+
verbs: SevenVerbLiveRow[];
|
|
196
|
+
liveVerbs: number | null;
|
|
197
|
+
measuredVerbs: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** live = 창 안에 result done 인 non-shadow 사건 ≥1. 원장이 null 이거나 절단되었으면 전부 unreadable. */
|
|
201
|
+
export function measureSevenVerbLive(input: TaskAgentCoverInput): SevenVerbLive {
|
|
202
|
+
const unreadable = input.taskAgentActions === null || input.truncated?.taskAgentActions === true;
|
|
203
|
+
const verbs = SEVEN_VERB_SOURCES.map(({ verb, source }): SevenVerbLiveRow => {
|
|
204
|
+
if (unreadable) return { verb, source, liveDone: null, shadow: null, state: 'unreadable' };
|
|
205
|
+
if (source === null) return { verb, source: null, liveDone: null, shadow: null, state: 'no-source' };
|
|
206
|
+
const actions = input.taskAgentActions!.filter((action) => action.kind === source);
|
|
207
|
+
const liveDone = actions.filter((action) => action.result === 'done').length;
|
|
208
|
+
const shadow = actions.filter((action) => action.result === 'shadow').length;
|
|
209
|
+
return { verb, source, liveDone, shadow, state: liveDone >= 1 ? 'live' : shadow >= 1 ? 'shadow-only' : 'none' };
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
verbs,
|
|
213
|
+
liveVerbs: unreadable ? null : verbs.filter((row) => row.state === 'live').length,
|
|
214
|
+
measuredVerbs: SEVEN_VERB_SOURCES.filter((row) => row.source !== null).length,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** 한 줄 요약 — 못 읽었으면 n 자리를 `-` 로 적는다(0 으로 읽히지 않게). */
|
|
219
|
+
export function formatSevenVerbLive(measurement: SevenVerbLive): string {
|
|
220
|
+
const total = SEVEN_VERB_SOURCES.length;
|
|
221
|
+
if (measurement.liveVerbs === null) return `${total}동사 live -/${total} · 못 잼(행동 원장 null·절단)`;
|
|
222
|
+
const noSource = measurement.verbs.filter((row) => row.state === 'no-source').map((row) => row.verb).join('·');
|
|
223
|
+
return `${total}동사 live ${measurement.liveVerbs}/${total}${noSource ? ` · 출처 없음 ${noSource}` : ''}`;
|
|
224
|
+
}
|