elanous 0.2.23 → 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-ad3bd8084048bee4.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-a648bc464c9dc754.js → page-dea4b795741126fd.js} +1 -1
- 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-48fb31810693c357.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-cb154acadb025414.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/css/72becfd42807b50d.css +1 -0
- package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_buildManifest.js +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
- package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
- package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
- package/catalog/providers/openrouter.yaml +2 -0
- package/graphs/implement-loop.yaml +31 -0
- package/graphs/ops/harness-gc.yaml +17 -0
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/overlays/README.md +1 -1
- package/graphs/overlays/stop-heal-ladder.yaml +105 -0
- 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/add-api-key.sh +1 -1
- package/scripts/bench-report.ts +46 -1
- package/scripts/ci-typecheck-changed.ts +73 -14
- package/scripts/fleet/bedrock-pod-secret.ts +122 -0
- package/scripts/fleet/node-setup-linux.sh +97 -0
- package/scripts/fleet/node-setup.sh +11 -0
- package/scripts/fleet/zai-pod-secret.ts +86 -0
- package/scripts/land-global-checks.ts +3 -0
- package/scripts/measure-log-diet-2.ts +213 -0
- package/scripts/measure-tsc-affected-roots.ts +289 -0
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- package/scripts/release-loop/gate-closure.ts +286 -0
- package/scripts/release-loop/gate-executor.ts +28 -0
- package/scripts/release-loop/gate-node.ts +333 -37
- 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 +46 -13
- package/scripts/release-loop/resume.ts +110 -4
- package/scripts/release-loop/unattended-release.ts +22 -7
- package/scripts/tsc-baseline-cache.ts +172 -0
- package/scripts/usage-rollup.ts +72 -6
- 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/run-context.ts +10 -0
- package/src/agent-mission/driver.ts +18 -3
- package/src/agent-mission/resource-ladder.ts +8 -3
- package/src/agent-mission/review-loop.ts +8 -2
- package/src/agent-substrate/acp-implementer.ts +146 -0
- package/src/agent-substrate/pr-reviewer.ts +60 -13
- package/src/agent-substrate/self-review-cli.ts +170 -15
- package/src/autopilot/mission-critique.ts +18 -5
- package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
- package/src/autopilot/mission-trace.ts +12 -1
- package/src/autopilot/system-lookback-run.ts +16 -10
- package/src/bench/bench.ts +183 -0
- package/src/budget/cost-tier-advisor.ts +91 -0
- package/src/budget/fetchers/grok.ts +15 -5
- package/src/budget/llm-cost.ts +37 -5
- package/src/budget/shadow-arms.ts +77 -0
- package/src/budget/types.ts +10 -2
- package/src/budget/unified-usage.ts +256 -10
- package/src/cli/bench-cli.ts +34 -0
- package/src/cli/doctor-cli.ts +21 -0
- package/src/cli/friendly-errors.ts +113 -0
- package/src/cli/guardian-cli.ts +26 -1
- package/src/cli/image-cli.ts +101 -0
- package/src/cli/intake-cli.ts +3 -1
- package/src/cli/log-event-names.ts +4 -0
- package/src/cli/memory-cli.ts +182 -0
- package/src/cli/model-watch-cli.ts +4 -1
- package/src/cli/pr-cli.ts +62 -5
- package/src/cli/pr-land-overlap-evidence.ts +160 -12
- package/src/cli/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +27 -16
- 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/rfc-status.ts +52 -2
- package/src/cli/seat-requests-cli.ts +25 -0
- package/src/cli/self-update.ts +104 -0
- package/src/cli/tasks-cli.ts +139 -10
- package/src/cli/usage-cli.ts +93 -8
- 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/core-turn/run-goal-loop.ts +5 -4
- package/src/dashboard/ad-run-setup-bindings.ts +279 -0
- package/src/dashboard/index.ts +18 -276
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +4 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/dashboard/stale-install-check.ts +11 -0
- package/src/debug/log-diet.ts +53 -10
- package/src/debug/log.ts +19 -1
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +43 -0
- package/src/error-report/report.ts +21 -4
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +375 -0
- package/src/github/pr-labels.ts +1 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/graph-cli.ts +42 -1
- package/src/graph-runner/runner.ts +176 -11
- package/src/graph-wizard/archetypes.ts +14 -8
- package/src/graph-wizard/generate.ts +77 -1
- package/src/grok/usage.ts +23 -2
- package/src/grok.ts +13 -7
- package/src/grounding/ref-index.ts +253 -0
- package/src/harness/dispatch-backpressure.ts +10 -2
- package/src/harness/harness-clean.ts +199 -78
- package/src/harness/harness-cli-command.ts +176 -52
- package/src/harness/harness-gc.ts +331 -0
- package/src/harness/harness-stop.ts +82 -10
- package/src/harness/harness-substrate-default.ts +142 -7
- package/src/harness/launch-registry.ts +6 -0
- package/src/harness/worktree-branch-prefix.ts +9 -0
- package/src/hq/fence.ts +187 -0
- package/src/hq/seats.ts +38 -22
- package/src/images/image-ledger.ts +179 -0
- package/src/index.ts +110 -186
- package/src/instance/child-scope.ts +32 -1
- package/src/instance/dev-project.ts +133 -0
- package/src/instance/resolve.ts +24 -0
- package/src/instance/spawn-elanous.ts +45 -0
- package/src/intake-plane/collect-github.ts +7 -2
- package/src/intake-plane/lens.ts +46 -4
- package/src/intake-plane/ref-prefetch.ts +110 -0
- package/src/intake-plane/requirement-funnel.ts +53 -1
- package/src/intelligence-map/catalog-feed.ts +119 -0
- package/src/intelligence-map/model-catalog.ts +72 -0
- package/src/intelligence-map/model-watch-intake.ts +40 -0
- package/src/intelligence-map/model-watch-mission.ts +14 -1
- package/src/llm/bedrock-eventstream.ts +215 -0
- package/src/llm/bedrock-provider.ts +114 -41
- package/src/llm/bedrock.ts +174 -28
- package/src/llm/open-weight-discipline.ts +21 -0
- package/src/llm/openrouter-byok-cost.ts +96 -0
- package/src/llm/openrouter-deepseek.ts +151 -0
- package/src/llm/openrouter-upstream-pins.config.ts +25 -0
- package/src/llm/zai-coding-plan.ts +700 -0
- package/src/llm.ts +91 -24
- package/src/loops/checker.ts +148 -9
- package/src/loops/orchestrator/resync-shadow.ts +34 -7
- package/src/maturity/feature-maturity.ts +3 -3
- package/src/model-tier/llm-tier-map.ts +9 -5
- package/src/models/prompts.ts +2 -1
- package/src/mss/logging/log-store.ts +58 -11
- package/src/nexus/api/http-server.ts +22 -0
- package/src/nexus/api/missions.ts +73 -2
- package/src/nexus/api/ops-api.ts +18 -0
- package/src/nexus/index.ts +7 -75
- package/src/nexus/tools-kind.ts +78 -0
- package/src/oauth/codex-account-rotation.ts +43 -3
- package/src/oauth/codex-account-store.ts +339 -27
- package/src/oauth/codex-quota-policy.ts +33 -4
- package/src/oauth/fallback-chain.ts +53 -15
- package/src/onboarding/first-run.ts +37 -18
- package/src/onboarding/web-first.ts +20 -2
- package/src/ops/machine-heartbeat.ts +185 -0
- package/src/ops/overview-cache.ts +175 -0
- package/src/ops/overview.ts +8 -0
- package/src/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/prompt-cache/openai.ts +3 -0
- package/src/prompt-cache/types.ts +5 -0
- package/src/prompt-enhance/enhance.ts +23 -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/placement.ts +16 -1
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/requirements/requirement-ledger.ts +536 -0
- package/src/retro/daily.ts +5 -5
- package/src/seat-loop/duty-ledger.ts +64 -0
- package/src/seat-loop/seat-loop.ts +32 -10
- package/src/self-dev/decompose.ts +37 -3
- package/src/self-dev/dev-cli.ts +44 -10
- package/src/self-dev/dev-pipeline.ts +39 -9
- package/src/self-dev/draft-residue.ts +27 -5
- package/src/self-dev/draft-sweep.ts +151 -0
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/graph-journey-route.ts +6 -0
- package/src/self-dev/orchestrate-cli.ts +25 -3
- package/src/self-dev/orchestrate.ts +41 -6
- package/src/self-dev/run-supervisor.ts +218 -15
- package/src/self-dev/run-types.ts +13 -0
- package/src/self-dev/supervisor-verdict-edges.ts +1 -0
- package/src/self-implement/budget-gate.ts +53 -13
- package/src/self-implement/child-context-composition.ts +139 -0
- package/src/self-implement/child-llm-preference.ts +13 -5
- package/src/self-implement/claude-acp-implement.ts +67 -0
- package/src/self-implement/flex-signals.ts +59 -0
- package/src/self-implement/frozen-merges.ts +8 -3
- package/src/self-implement/gate-cli.ts +29 -10
- package/src/self-implement/gate-remote.ts +4 -1
- package/src/self-implement/goal-author-decompose.ts +10 -2
- package/src/self-implement/goal-author.ts +36 -11
- package/src/self-implement/goal-new-paths.ts +42 -0
- package/src/self-implement/graph-overlay-condition.ts +28 -0
- package/src/self-implement/graph-overlay-yaml.ts +41 -7
- package/src/self-implement/graph-templates.ts +33 -1
- package/src/self-implement/graph-yaml.ts +56 -0
- package/src/self-implement/heal-intake.ts +5 -1
- 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 +230 -32
- 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 +75 -5
- package/src/self-implement/scope-adjacency.ts +23 -0
- package/src/self-implement/seams.ts +89 -8
- package/src/self-implement/self-implement-cli.ts +9 -4
- package/src/self-implement/stop-autoheal.ts +69 -2
- package/src/session-runtime/retry-policy.ts +2 -1
- 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/launch.ts +5 -4
- package/src/steward/rejudge-tick.ts +142 -0
- package/src/steward/triage-budget.ts +62 -0
- package/src/steward/triage.ts +83 -22
- package/src/task-agent/actions.ts +62 -5
- package/src/task-agent/board.ts +92 -3
- package/src/task-agent/card-evidence.ts +88 -1
- package/src/task-agent/completion-evidence.ts +5 -0
- package/src/task-agent/cover.ts +166 -3
- package/src/task-agent/judge.ts +16 -0
- package/src/task-agent/land-order-ledger.ts +95 -0
- package/src/task-agent/live-move-history.ts +87 -1
- package/src/task-agent/live-moves.ts +350 -20
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +223 -24
- package/src/task-agent/review-prior-fix.ts +146 -0
- package/src/task-agent/review-result-capture.ts +3 -1
- package/src/task-agent/run-adopt.ts +136 -0
- package/src/task-agent/shadow.ts +65 -9
- package/src/task-agent/task-hand.ts +57 -7
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
- package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
- package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +14 -1
- package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +79 -6
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +17 -5
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +11 -5
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +73 -4
- package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +432 -35
- package/src/task-orchestrator/surfaces/self-implement.ts +19 -1
- package/src/typecheck-ratchet.ts +1 -0
- package/src/user-config.ts +69 -15
- 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/src/workflow-runtime/triggers/registry.ts +59 -0
- package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
- 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-b23d2e92161d11fd.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-fbef064c213b2b18.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-d5341ac96203a983.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-6168a7c43e6ef8f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.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-2bd9ce9c020d02d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.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-745d9b6c015076f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.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/css/5619d59e87eddf66.css +0 -1
- /package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_ssgManifest.js +0 -0
|
@@ -7,14 +7,21 @@
|
|
|
7
7
|
* - 무엇을: `--overlap-evidence <file>` 의 JSON 을 «믿지 않고» 잰다.
|
|
8
8
|
* ① 재기반 — 원격 base 의 «지금» 끝(`git ls-remote`)이 고정 머리의 조상인가(`git merge-base --is-ancestor`).
|
|
9
9
|
* ② 재게이트 — 증거의 게이트 기록이 «그 머리»를 «그 base 끝» 위에서 통과했다고 말하는가(머리·base 끝이 ① 과 맞물린다).
|
|
10
|
+
* ②' 재게이트 뒤 base 가 앞섰다(OVERLAP-EVIDENCE-BASE-WINDOW) — `gate.baseCommit ≠ 지금 끝`이면 «창»을 잰다:
|
|
11
|
+
* ⓐ `gate.baseCommit` 이 고정 머리의 조상 ⊕ 지금 끝의 조상이고 ⓑ 창 `gate.baseCommit..지금 끝`의 커밋이 «하나도»
|
|
12
|
+
* PR 의 바뀐 파일(머리 vs merge-base)을 안 건드리면 통과(관측 reason `base-advanced-disjoint`).
|
|
13
|
+
* 겹치면 `base-stale-overlap`(REJUDGE 가 재게이트를 청한다) · 못 재면 `base-window-unmeasured` · ⓐ 가 아니면 종전 사유.
|
|
10
14
|
* ③ 리뷰 — 증거가 가리키는 `review-results/<card>-<pr>-<head12>.json`(TA 가 받는 `self review --json` stdout)이
|
|
11
|
-
* 같은 PR·같은 머리에 대해 `reviewed:true` · `verdict
|
|
15
|
+
* 같은 PR·같은 머리에 대해 `reviewed:true` · `verdict ∈ {pass, warn}` · must-fix 가 «잰 수» 0 인가
|
|
16
|
+
* (자동 병합 canAuto · TA-LAND-WARN-MUSTFIX0 과 같은 규칙 — must-fix 를 못 셌으면 거부).
|
|
12
17
|
* ⓐ 이미 조상(TC #26019 실측) — 겹친 최근 착지 커밋이 «전부» 고정 머리의 조상이면 그 겹침은 이미 그 머리의 게이트·리뷰에
|
|
13
18
|
* 반영됐다 ⇒ ①② 없이 ③ 만으로 통과(관측 reason `already-ancestor`). 하나라도 조상이 아니면 ①②③ 전부.
|
|
19
|
+
* ⓐ' 증거 파일이 없을 때(`verifyAncestorAutoPass`) — 같은 ⓐ 를 표준 자리 `review-results/*-<pr>-<head12>.json` 만으로 잰다
|
|
20
|
+
* (관측 reason `already-ancestor-auto`). 조상이 아닌 착지가 하나라도 있거나 리뷰 결과가 없으면 거부.
|
|
14
21
|
* 하나라도 못 재거나 어긋나면 거부 — 호출부는 종전 거부를 그대로 낸다(fail-closed).
|
|
15
22
|
* - 관측: `pr.land` · `overlap-evidence` (decision · reason · 잰 값).
|
|
16
23
|
*/
|
|
17
|
-
import { basename, dirname } from 'node:path';
|
|
24
|
+
import { basename, dirname, join } from 'node:path';
|
|
18
25
|
import { debug } from '../debug/log.js';
|
|
19
26
|
import type { CmdRunner } from '../autopilot/pr-manager.js';
|
|
20
27
|
import { parseReviewResultOutput } from '../task-agent/review-result-capture.js';
|
|
@@ -33,6 +40,7 @@ interface OverlapEvidenceFile {
|
|
|
33
40
|
export type OverlapEvidenceVerdict =
|
|
34
41
|
| { ok: true; mode: 'already-ancestor'; reviewResult: string }
|
|
35
42
|
| { ok: true; mode: 'rebased'; baseTip: string; reviewResult: string }
|
|
43
|
+
| { ok: true; mode: 'base-advanced-disjoint'; baseTip: string; gateBase: string; windowCommits: number; reviewResult: string }
|
|
36
44
|
| { ok: false; reason: string };
|
|
37
45
|
|
|
38
46
|
export interface VerifyOverlapEvidenceInput {
|
|
@@ -48,9 +56,14 @@ export interface VerifyOverlapEvidenceInput {
|
|
|
48
56
|
overlappingLandings?: readonly string[];
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
type Checked = { ok: false; reason: string; baseTip?: string
|
|
59
|
+
type Checked = { ok: false; reason: string; baseTip?: string; gateBase?: string; windowCommits?: number }
|
|
60
|
+
| (OverlapEvidenceVerdict & { ok: true; baseTip?: string });
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
/** 리뷰가 받는 판정 — 자동 병합(canAuto)·TA 착지(TA-LAND-WARN-MUSTFIX0)와 같은 집합. */
|
|
63
|
+
const ACCEPTED_REVIEW_VERDICTS: ReadonlySet<string> = new Set(['pass', 'warn']);
|
|
64
|
+
const COMMIT_MARK = '\u0001';
|
|
65
|
+
|
|
66
|
+
function checkReview(input: Pick<VerifyOverlapEvidenceInput, 'pr' | 'readFile'>, e: Partial<OverlapEvidenceFile>, head: string, baseTip?: string): { ok: false; reason: string; baseTip?: string } | { ok: true; reviewResult: string } {
|
|
54
67
|
if (typeof e.reviewResult !== 'string' || !e.reviewResult) return { ok: false, reason: 'review-missing', baseTip };
|
|
55
68
|
// TA 가 받는 자리(`<state>/review-results/<card>-<pr>-<head12>.json` · reviewResultPath)만 — 아무 디렉터리의 같은 이름은 안 받는다.
|
|
56
69
|
if (basename(dirname(e.reviewResult)) !== 'review-results'
|
|
@@ -65,11 +78,67 @@ function checkReview(input: VerifyOverlapEvidenceInput, e: Partial<OverlapEviden
|
|
|
65
78
|
if (!review.head || review.head.toLowerCase() !== head) return { ok: false, reason: 'review-head-mismatch', baseTip };
|
|
66
79
|
if (review.error) return { ok: false, reason: 'review-error', baseTip };
|
|
67
80
|
if (review.reviewed !== true) return { ok: false, reason: 'review-not-reviewed', baseTip };
|
|
68
|
-
if (review.verdict
|
|
81
|
+
if (review.verdict === null || !ACCEPTED_REVIEW_VERDICTS.has(review.verdict)) return { ok: false, reason: `review-verdict-${review.verdict ?? 'null'}`, baseTip };
|
|
69
82
|
if (review.mustFix !== 0) return { ok: false, reason: review.mustFix === null ? 'review-must-fix-unknown' : `review-must-fix-${review.mustFix}`, baseTip };
|
|
70
83
|
return { ok: true, reviewResult: e.reviewResult };
|
|
71
84
|
}
|
|
72
85
|
|
|
86
|
+
type WindowResult = { ok: true; windowCommits: number } | { ok: false; reason: string; windowCommits?: number };
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* ②' — 재게이트 뒤 앞선 base 의 창 `gateBase..baseTip` 이 PR 의 바뀐 파일과 «서로소»인가. 읽기 전용 git 만 쓴다
|
|
90
|
+
* (끝 커밋이 로컬에 없을 때만 ref 를 안 쓰는 fetch). `staleReason` 은 ⓐ(조상 아님)일 때 그대로 내는 종전 사유다.
|
|
91
|
+
*/
|
|
92
|
+
function checkBaseWindow(input: VerifyOverlapEvidenceInput, head: string, baseTip: string, gateBase: string, staleReason: string): WindowResult {
|
|
93
|
+
const git = (args: string[]) => input.run('git', args, { cwd: input.cwd });
|
|
94
|
+
const short = (sha: string) => sha.slice(0, 12);
|
|
95
|
+
if (!git(['merge-base', '--is-ancestor', gateBase, head]).ok) {
|
|
96
|
+
return { ok: false, reason: `${staleReason} (gate base is not an ancestor of head)` };
|
|
97
|
+
}
|
|
98
|
+
if (!git(['cat-file', '-e', `${baseTip}^{commit}`]).ok) {
|
|
99
|
+
// ref 를 안 바꾸는 fetch — FETCH_HEAD 도 원격 추적 ref 도 안 쓴다.
|
|
100
|
+
git(['fetch', '--quiet', '--no-write-fetch-head', '--refmap=', input.remote, `refs/heads/${input.branch}`]);
|
|
101
|
+
if (!git(['cat-file', '-e', `${baseTip}^{commit}`]).ok) {
|
|
102
|
+
return { ok: false, reason: `base-window-unmeasured: ${input.remote}/${input.branch} ${short(baseTip)} not available locally · ${staleReason}` };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!git(['merge-base', '--is-ancestor', gateBase, baseTip]).ok) {
|
|
106
|
+
return { ok: false, reason: `${staleReason} (gate base is not an ancestor of ${input.remote}/${input.branch})` };
|
|
107
|
+
}
|
|
108
|
+
const mergeBase = git(['merge-base', baseTip, head]);
|
|
109
|
+
const forkPoint = mergeBase.ok ? mergeBase.out.trim() : '';
|
|
110
|
+
if (!SHA40.test(forkPoint)) return { ok: false, reason: `base-window-unmeasured: merge-base ${short(baseTip)} ${short(head)} failed · ${staleReason}` };
|
|
111
|
+
const diff = git(['diff', '--name-only', '--no-renames', forkPoint, head]);
|
|
112
|
+
if (!diff.ok) return { ok: false, reason: `base-window-unmeasured: diff --name-only ${short(forkPoint)} ${short(head)} failed · ${staleReason}` };
|
|
113
|
+
const prFiles = new Set(diff.out.split('\n').map((line) => line.trim()).filter(Boolean));
|
|
114
|
+
if (prFiles.size === 0) return { ok: false, reason: `base-window-unmeasured: PR changed files are empty · ${staleReason}` };
|
|
115
|
+
// 병합 커밋은 첫 부모 대비 diff(-m --first-parent) — base 에 «들어온» 변경만, 빠짐없이.
|
|
116
|
+
const log = git(['log', '--first-parent', '-m', '--no-renames', '--name-only', `--format=${COMMIT_MARK}%H`, `${gateBase}..${baseTip}`]);
|
|
117
|
+
if (!log.ok) return { ok: false, reason: `base-window-unmeasured: log ${short(gateBase)}..${short(baseTip)} failed · ${staleReason}` };
|
|
118
|
+
const touched = new Map<string, string[]>();
|
|
119
|
+
let current = '';
|
|
120
|
+
for (const raw of log.out.split('\n')) {
|
|
121
|
+
const line = raw.trim();
|
|
122
|
+
if (!line) continue;
|
|
123
|
+
if (line.startsWith(COMMIT_MARK)) { current = line.slice(COMMIT_MARK.length); if (!touched.has(current)) touched.set(current, []); continue; }
|
|
124
|
+
if (current && prFiles.has(line)) touched.get(current)!.push(line);
|
|
125
|
+
}
|
|
126
|
+
const windowCommits = touched.size;
|
|
127
|
+
if (windowCommits === 0 || [...touched.keys()].some((sha) => !SHA40.test(sha))) {
|
|
128
|
+
return { ok: false, reason: `base-window-unmeasured: window ${short(gateBase)}..${short(baseTip)} listed no commits · ${staleReason}` };
|
|
129
|
+
}
|
|
130
|
+
const overlapping = [...touched.entries()].filter(([, files]) => files.length > 0);
|
|
131
|
+
if (overlapping.length > 0) {
|
|
132
|
+
const files = [...new Set(overlapping.flatMap(([, f]) => f))];
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
windowCommits,
|
|
136
|
+
reason: `base-stale-overlap: gate ${short(gateBase)} ≠ ${input.remote}/${input.branch} ${short(baseTip)} · ${overlapping.length}/${windowCommits} window commits touch PR files (${overlapping.map(([sha]) => short(sha)).slice(0, 5).join(', ')}): ${files.slice(0, 10).join(', ')}`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return { ok: true, windowCommits };
|
|
140
|
+
}
|
|
141
|
+
|
|
73
142
|
function check(input: VerifyOverlapEvidenceInput): Checked {
|
|
74
143
|
const head = input.expectedHead.toLowerCase();
|
|
75
144
|
let raw: unknown;
|
|
@@ -94,15 +163,32 @@ function check(input: VerifyOverlapEvidenceInput): Checked {
|
|
|
94
163
|
const baseTip = remote.ok ? remote.out.trim().split(/\s+/)[0] ?? '' : '';
|
|
95
164
|
if (!SHA40.test(baseTip)) return { ok: false, reason: `rebase-unmeasured: ls-remote ${input.remote} ${input.branch} failed` };
|
|
96
165
|
const ancestor = input.run('git', ['merge-base', '--is-ancestor', baseTip, head], { cwd: input.cwd });
|
|
97
|
-
|
|
166
|
+
const gate = e.gate;
|
|
167
|
+
// ②' 의 입구 — 게이트 기록이 «그 머리»를 통과했고 base 만 지금 끝과 다르다.
|
|
168
|
+
const gateBase = gate && typeof gate === 'object' && gate.passed === true
|
|
169
|
+
&& typeof gate.head === 'string' && gate.head.toLowerCase() === head
|
|
170
|
+
&& typeof gate.baseCommit === 'string' && SHA40.test(gate.baseCommit) && gate.baseCommit.toLowerCase() !== baseTip.toLowerCase()
|
|
171
|
+
? gate.baseCommit.toLowerCase() : undefined;
|
|
172
|
+
const advanced = (staleReason: string): Checked => {
|
|
173
|
+
const window = checkBaseWindow(input, head, baseTip, gateBase!, staleReason);
|
|
174
|
+
if (!window.ok) return { ok: false, reason: window.reason, baseTip, gateBase, windowCommits: window.windowCommits };
|
|
175
|
+
const review = checkReview(input, e, head, baseTip);
|
|
176
|
+
return review.ok
|
|
177
|
+
? { ok: true, mode: 'base-advanced-disjoint', baseTip, gateBase: gateBase!, windowCommits: window.windowCommits, reviewResult: review.reviewResult }
|
|
178
|
+
: { ...review, gateBase, windowCommits: window.windowCommits };
|
|
179
|
+
};
|
|
180
|
+
if (!ancestor.ok) {
|
|
181
|
+
const notRebased = `not-rebased: ${input.remote}/${input.branch} ${baseTip.slice(0, 12)} is not an ancestor of ${head.slice(0, 12)}`;
|
|
182
|
+
return gateBase ? advanced(notRebased) : { ok: false, reason: notRebased, baseTip };
|
|
183
|
+
}
|
|
98
184
|
|
|
99
185
|
// ② 재게이트 — 그 머리를, ① 의 그 base 끝 위에서.
|
|
100
|
-
const gate = e.gate;
|
|
101
186
|
if (!gate || typeof gate !== 'object') return { ok: false, reason: 'gate-missing', baseTip };
|
|
102
187
|
if (gate.passed !== true) return { ok: false, reason: 'gate-not-passed', baseTip };
|
|
103
188
|
if (typeof gate.head !== 'string' || gate.head.toLowerCase() !== head) return { ok: false, reason: 'gate-head-mismatch', baseTip };
|
|
104
189
|
if (typeof gate.baseCommit !== 'string' || gate.baseCommit.toLowerCase() !== baseTip.toLowerCase()) {
|
|
105
|
-
|
|
190
|
+
const stale = `gate-base-stale: gate ${String(gate.baseCommit).slice(0, 12)} ≠ ${input.remote}/${input.branch} ${baseTip.slice(0, 12)}`;
|
|
191
|
+
return gateBase ? advanced(stale) : { ok: false, reason: stale, baseTip };
|
|
106
192
|
}
|
|
107
193
|
|
|
108
194
|
// ③ 리뷰 — 그 PR · 그 머리의 pass ⊕ must-fix 0.
|
|
@@ -110,22 +196,84 @@ function check(input: VerifyOverlapEvidenceInput): Checked {
|
|
|
110
196
|
return review.ok ? { ok: true, mode: 'rebased', baseTip, reviewResult: review.reviewResult } : review;
|
|
111
197
|
}
|
|
112
198
|
|
|
199
|
+
export type AncestorAutoVerdict =
|
|
200
|
+
| { ok: true; mode: 'already-ancestor-auto'; reviewResult: string }
|
|
201
|
+
| { ok: false; reason: string };
|
|
202
|
+
|
|
203
|
+
export interface VerifyAncestorAutoInput {
|
|
204
|
+
pr: number;
|
|
205
|
+
expectedHead: string;
|
|
206
|
+
cwd: string;
|
|
207
|
+
run: CmdRunner;
|
|
208
|
+
readFile: (path: string) => string;
|
|
209
|
+
/** 표준 자리 `<state>/review-results` — 이 안의 `*-<pr>-<head12>.json` 만 본다. */
|
|
210
|
+
reviewResultsDir: string;
|
|
211
|
+
listDir: (dir: string) => readonly string[];
|
|
212
|
+
/** 겹침 관문이 찾은 «겹친» 최근 착지 커밋들. */
|
|
213
|
+
overlappingLandings: readonly string[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function checkAncestorAuto(input: VerifyAncestorAutoInput): AncestorAutoVerdict {
|
|
217
|
+
const head = input.expectedHead.toLowerCase();
|
|
218
|
+
const landings = input.overlappingLandings;
|
|
219
|
+
if (landings.length === 0) return { ok: false, reason: 'ancestor-auto-no-overlapping-landings' };
|
|
220
|
+
const notAncestor = landings.find((sha) => !(/^[0-9a-f]{7,40}$/i.test(sha)
|
|
221
|
+
&& input.run('git', ['merge-base', '--is-ancestor', sha, head], { cwd: input.cwd }).ok));
|
|
222
|
+
if (notAncestor !== undefined) return { ok: false, reason: `ancestor-auto-not-ancestor: ${notAncestor.slice(0, 12)} is not an ancestor of ${head.slice(0, 12)}` };
|
|
223
|
+
let names: readonly string[];
|
|
224
|
+
try { names = input.listDir(input.reviewResultsDir); } catch { return { ok: false, reason: 'review-missing' }; }
|
|
225
|
+
const suffix = new RegExp(`-${input.pr}-${head.slice(0, 12)}\\.json$`, 'i');
|
|
226
|
+
// 같은 <pr>-<head12> 리뷰가 여럿이면 «전부» 통과해야 한다 — 하나라도 거부면 거부(fail-closed · 처음 통과한 하나로 승인하지 않는다).
|
|
227
|
+
let accepted: string | undefined;
|
|
228
|
+
for (const name of [...names].filter((n) => suffix.test(n)).sort()) {
|
|
229
|
+
const review = checkReview(input, { reviewResult: join(input.reviewResultsDir, name) }, head);
|
|
230
|
+
if (!review.ok) return { ok: false, reason: review.reason };
|
|
231
|
+
accepted = review.reviewResult;
|
|
232
|
+
}
|
|
233
|
+
return accepted === undefined ? { ok: false, reason: 'review-missing' } : { ok: true, mode: 'already-ancestor-auto', reviewResult: accepted };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* 증거 파일이 없을 때의 already-ancestor 자동 판정 — 겹친 착지가 «전부» 고정 머리의 조상이고 표준 자리의 리뷰 결과가
|
|
238
|
+
* pass|warn ⊕ must-fix 0 이면 통과. 던지지 않는다 — 어떤 실패도 거부(fail-closed)이고 관측 한 줄을 남긴다.
|
|
239
|
+
*/
|
|
240
|
+
export function verifyAncestorAutoPass(input: VerifyAncestorAutoInput): AncestorAutoVerdict {
|
|
241
|
+
let verdict: AncestorAutoVerdict;
|
|
242
|
+
try { verdict = checkAncestorAuto(input); } catch (error) { verdict = { ok: false, reason: `verify-threw: ${String(error).slice(0, 200)}` }; }
|
|
243
|
+
debug.log('pr.land', 'overlap-evidence', {
|
|
244
|
+
decision: verdict.ok ? 'accepted' : 'rejected',
|
|
245
|
+
reason: verdict.ok ? 'already-ancestor-auto' : verdict.reason,
|
|
246
|
+
overlappingLandings: input.overlappingLandings,
|
|
247
|
+
pr: input.pr,
|
|
248
|
+
head: input.expectedHead,
|
|
249
|
+
evidencePath: null,
|
|
250
|
+
reviewResultsDir: input.reviewResultsDir,
|
|
251
|
+
});
|
|
252
|
+
return verdict;
|
|
253
|
+
}
|
|
254
|
+
|
|
113
255
|
/** 던지지 않는다 — 어떤 실패도 거부(fail-closed)이고 관측 한 줄을 남긴다. */
|
|
114
256
|
export function verifyOverlapEvidence(input: VerifyOverlapEvidenceInput): OverlapEvidenceVerdict {
|
|
115
257
|
let verdict: Checked;
|
|
116
258
|
try { verdict = check(input); } catch (error) { verdict = { ok: false, reason: `verify-threw: ${String(error).slice(0, 200)}` }; }
|
|
117
259
|
debug.log('pr.land', 'overlap-evidence', {
|
|
118
260
|
decision: verdict.ok ? 'accepted' : 'rejected',
|
|
119
|
-
reason: verdict.ok
|
|
261
|
+
reason: verdict.ok
|
|
262
|
+
? (verdict.mode === 'already-ancestor' ? 'already-ancestor' : verdict.mode === 'base-advanced-disjoint' ? 'base-advanced-disjoint' : 'rebased+gated+reviewed')
|
|
263
|
+
: verdict.reason,
|
|
120
264
|
overlappingLandings: input.overlappingLandings ?? [],
|
|
121
265
|
pr: input.pr,
|
|
122
266
|
head: input.expectedHead,
|
|
123
267
|
base: `${input.remote}/${input.branch}`,
|
|
124
268
|
baseTip: verdict.baseTip ?? null,
|
|
125
269
|
evidencePath: input.evidencePath,
|
|
270
|
+
gateBase: (verdict.ok ? (verdict.mode === 'base-advanced-disjoint' ? verdict.gateBase : undefined) : verdict.gateBase) ?? null,
|
|
271
|
+
windowCommits: (verdict.ok ? (verdict.mode === 'base-advanced-disjoint' ? verdict.windowCommits : undefined) : verdict.windowCommits) ?? null,
|
|
126
272
|
});
|
|
127
273
|
if (!verdict.ok) return { ok: false, reason: verdict.reason };
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
274
|
+
if (verdict.mode === 'already-ancestor') return { ok: true, mode: 'already-ancestor', reviewResult: verdict.reviewResult };
|
|
275
|
+
if (verdict.mode === 'base-advanced-disjoint') {
|
|
276
|
+
return { ok: true, mode: 'base-advanced-disjoint', baseTip: verdict.baseTip!, gateBase: verdict.gateBase, windowCommits: verdict.windowCommits, reviewResult: verdict.reviewResult };
|
|
277
|
+
}
|
|
278
|
+
return { ok: true, mode: 'rebased', baseTip: verdict.baseTip!, reviewResult: verdict.reviewResult };
|
|
131
279
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRLAND-HEAVY-ON-POD-1 — `pr land` 무거운 판정을 Pod 에서 그림자 리허설한다.
|
|
3
|
+
*
|
|
4
|
+
* 착지 경로에 아직 잇지 않는다. `--heavy-on-pod-shadow` 플래그·실제 Pod 러너 바인딩은
|
|
5
|
+
* 다음 조각(pr-cli.ts · pod-command-job.ts 무접촉). 이번 단위는 주입형 순수 함수만:
|
|
6
|
+
* 켜지면 가짜/실 Pod 러너를 한 번 부르고 `pr.land`/`heavy-on-pod-shadow` 관측 한 줄을 남긴 뒤
|
|
7
|
+
* 로컬 판정을 그대로 반환한다. 끄면 러너 0회. 러너가 던져도 경고 한 줄만 내고 로컬을 지킨다.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface HeavyOnPodShadowInput<T> {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
pr: number;
|
|
13
|
+
head: string;
|
|
14
|
+
local: T;
|
|
15
|
+
runPod: () => T | Promise<T>;
|
|
16
|
+
log: (category: string, event: string, data: Record<string, unknown>) => void;
|
|
17
|
+
warn: (message: string) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function agree(local: unknown, pod: unknown): boolean {
|
|
21
|
+
if (Object.is(local, pod)) return true;
|
|
22
|
+
try {
|
|
23
|
+
return JSON.stringify(local) === JSON.stringify(pod);
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function elapsedMs(started: number): number {
|
|
30
|
+
return Math.max(0, performance.now() - started);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function runHeavyOnPodShadow<T>(input: HeavyOnPodShadowInput<T>): Promise<T> {
|
|
34
|
+
const { enabled, pr, head, local, runPod, log, warn } = input;
|
|
35
|
+
if (!enabled) return local;
|
|
36
|
+
|
|
37
|
+
const localMs = 0;
|
|
38
|
+
const started = performance.now();
|
|
39
|
+
try {
|
|
40
|
+
const pod = await runPod();
|
|
41
|
+
log('pr.land', 'heavy-on-pod-shadow', {
|
|
42
|
+
pr,
|
|
43
|
+
head,
|
|
44
|
+
local,
|
|
45
|
+
pod,
|
|
46
|
+
agree: agree(local, pod),
|
|
47
|
+
podMs: elapsedMs(started),
|
|
48
|
+
localMs,
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
warn(error instanceof Error ? error.message : String(error));
|
|
52
|
+
}
|
|
53
|
+
return local;
|
|
54
|
+
}
|
package/src/cli/release-cli.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// elanous release tag --version <x.y.z> --source <commit> [--yes]
|
|
6
6
|
// elanous release verify [--version <x.y.z>]
|
|
7
7
|
// elanous release notes --from <ref> [--to <ref>]
|
|
8
|
-
// elanous release run --version <x.y.z> [--prerelease rc] [--main-cut | --cut-commit <sha>] [--publish-at <iso>] [--dry-run] [--json] [--if-ready]
|
|
9
|
-
// elanous release resume --run <runId> --from <node> [--waive <node> --reason <text>] [--accepted-regressions <json>] [--json]
|
|
8
|
+
// elanous release run --version <x.y.z> [--prerelease rc] [--main-cut | --cut-commit <sha>] [--publish-at <iso>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--dry-run] [--json] [--if-ready]
|
|
9
|
+
// elanous release resume --run <runId> --from <node> [--waive <node> --reason <text>] [--accepted-regressions <json>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--json]
|
|
10
10
|
// elanous release auto-start [--window-minutes <n>] [--apply] [--json]
|
|
11
11
|
// elanous release rehearsal tick [--apply] [--checkout <dir>] [--json]
|
|
12
12
|
// elanous release preflight --version <x.y.z> [--publish-at <iso>] [--json] (컷 30분 전 사전 점검 · 읽기 전용 · ⛔ 있으면 exit 1)
|
|
@@ -989,7 +989,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
989
989
|
.action(async (o: { version: string; base: string; pick: string[]; append?: boolean; dryRun?: boolean; json?: boolean }) => {
|
|
990
990
|
await jsonAction(o.json, async (log) => cutReleaseBranch({ ...o, log }), () => true);
|
|
991
991
|
});
|
|
992
|
-
const runAction = async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; json?: boolean }, logRun = console.log): Promise<boolean | AutoStartDeferral | undefined> => {
|
|
992
|
+
const runAction = async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }, logRun = console.log): Promise<boolean | AutoStartDeferral | undefined> => {
|
|
993
993
|
// Only the rc rehearsal channel is operated for now (alpha/beta stay valid version shapes, not run options).
|
|
994
994
|
if (o.prerelease !== undefined && o.prerelease !== 'rc') {
|
|
995
995
|
const message = `--prerelease supports rc only: ${o.prerelease}`;
|
|
@@ -1038,7 +1038,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1038
1038
|
const outcome = await runReleaseIfReady(o.version, {
|
|
1039
1039
|
ledgerRoot: releaseRunDeps.ledgerRoot,
|
|
1040
1040
|
readiness: (version, options) => releaseReadiness(version, { ledgerRoot: releaseRunDeps.ledgerRoot, checklist: releaseRunDeps.checklist, ...options }),
|
|
1041
|
-
run: () => runUnattendedRelease({ version: o.version, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt }, releaseRunDeps),
|
|
1041
|
+
run: () => runUnattendedRelease({ version: o.version, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps),
|
|
1042
1042
|
});
|
|
1043
1043
|
if (outcome.skipped) {
|
|
1044
1044
|
if (o.json) await writeStdoutJson(`${JSON.stringify(outcome)}\n`);
|
|
@@ -1066,7 +1066,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1066
1066
|
}
|
|
1067
1067
|
}
|
|
1068
1068
|
await jsonAction(o.json, async (log) => {
|
|
1069
|
-
const result = await runUnattendedRelease({ version: o.version, dryRun: o.dryRun, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt }, releaseRunDeps);
|
|
1069
|
+
const result = await runUnattendedRelease({ version: o.version, dryRun: o.dryRun, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps);
|
|
1070
1070
|
log(`${result.dryRun ? '· 드라이런' : '▶ 릴리스 루프'} ${result.input.version} · 입력 ${JSON.stringify(result.input)}`);
|
|
1071
1071
|
return result;
|
|
1072
1072
|
}, (r) => r.dryRun || r.state?.status === 'done' || r.state?.status === 'awaiting-approval');
|
|
@@ -1081,8 +1081,10 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1081
1081
|
.option('--if-ready', '준비되지 않았으면 사유를 출력하고 성공으로 건너뛴다')
|
|
1082
1082
|
.option('--publish-at <iso>', '승인·선행 노드 통과 뒤 지정 시각까지 발행 대기(오프셋 포함 ISO 시각)')
|
|
1083
1083
|
.option('--force-freeze', '동결 중 게이트·발행 강행(관측 기록) — 가지 컷은 동결이 필요 없다 · 동결은 비상 스위치로 남는다')
|
|
1084
|
+
.option('--gate-executor <pod|host>', 'gate 노드 실행기(기본 pod) — host 는 Pod 대신 SSH 호스트의 깨끗한 클론에서 같은 판정(면제 아님)')
|
|
1085
|
+
.option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 release.loop.gateRemote)')
|
|
1084
1086
|
.option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
|
|
1085
|
-
.action(async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; json?: boolean }) => { await runAction(o); });
|
|
1087
|
+
.action(async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }) => { await runAction(o); });
|
|
1086
1088
|
release.command('preflight')
|
|
1087
1089
|
.description('컷 30분 전 사전 점검(읽기 전용) — 체크리스트 게이트 모의 · 발행 뒤 칸 · run --dry-run 입력 · 동결 · 일정/게이트 실측. ⛔ 있으면 exit 1')
|
|
1088
1090
|
.requiredOption('--version <v>', '점검할 판(x.y.z)')
|
|
@@ -1105,17 +1107,18 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1105
1107
|
.description('가벼운 RC 점검 — 직전 판 컷(또는 --base) 이후 변경 범위 self gate ⊕ 상시 목록(release/light-rc-always.txt)을 원격 게이트 호스트에서 · 새 회귀(introduced>0)면 exit 1')
|
|
1106
1108
|
.requiredOption('--version <v>', '점검할 판(x.y.z)')
|
|
1107
1109
|
.option('--base <ref>', '비교 기준(기본: git merge-base origin/main origin/release/<원장 직전 판>)')
|
|
1110
|
+
.option('--head <ref>', '잴 커밋(기본: git fetch origin main 뒤 origin/main — 작업 트리 HEAD 가 아니다 · 다르면 분리 체크아웃에서 잰다)')
|
|
1108
1111
|
.option('--remote <host>', '게이트 호스트(기본 config gateRemote.host)')
|
|
1109
1112
|
.option('--local', '원격 대신 이 기계에서 돌린다(원격 자식이 이것으로 다시 불린다)')
|
|
1110
1113
|
.option('--shards <n>', '시험 분할 수', '4')
|
|
1111
1114
|
.option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
|
|
1112
|
-
.action(async (o: { version: string; base?: string; remote?: string; local?: boolean; shards: string; json?: boolean }) => {
|
|
1115
|
+
.action(async (o: { version: string; base?: string; head?: string; remote?: string; local?: boolean; shards: string; json?: boolean }) => {
|
|
1113
1116
|
// The root strips `--local` from argv (remote-bookmark attach) before Commander sees it — same read as `self gate`.
|
|
1114
1117
|
const local = !!o.local || process.argv.slice(2).includes('--local');
|
|
1115
1118
|
await jsonAction(o.json, async (log) => {
|
|
1116
1119
|
if (o.remote !== undefined && local) throw new Error('release light-rc: --remote and --local cannot be combined');
|
|
1117
1120
|
const shards = Number(o.shards);
|
|
1118
|
-
const result = await runLightRc(o.version, { base: o.base, remote: o.remote, local, shards, ledgerRoot: releaseRunDeps.ledgerRoot, log: (l) => console.error(l) }, lightRcDeps);
|
|
1121
|
+
const result = await runLightRc(o.version, { base: o.base, head: o.head, remote: o.remote, local, shards, ledgerRoot: releaseRunDeps.ledgerRoot, log: (l) => console.error(l) }, lightRcDeps);
|
|
1119
1122
|
for (const line of formatLightRc(result)) log(line);
|
|
1120
1123
|
return result;
|
|
1121
1124
|
}, (r) => r.ok);
|
|
@@ -1124,12 +1127,15 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1124
1127
|
.description('실패한 릴리스 런을 이어 달린다 — cut-branch --append 로 고친 release/<v> 새 끝을 version-release 기록에 반영(빨리감기만·상태 백업) 뒤 --from 노드부터')
|
|
1125
1128
|
.requiredOption('--run <runId>', '실패한 release-loop 런 ID')
|
|
1126
1129
|
.requiredOption('--from <node>', '다시 시작할 노드(예: gate)')
|
|
1127
|
-
.option('--partial', 'GATE-PARTIAL — --from gate 에서 앞
|
|
1130
|
+
.option('--partial', 'GATE-PARTIAL — --from gate 에서 바뀐 시험 ⊕ 앞 실패 ⊕ 바뀐 코드에 import 로 닿는 시험만 다시 돈다(끝이 움직인 --from gate 는 기본 · 의심이면 전체 게이트)')
|
|
1131
|
+
.option('--no-partial', 'GATE-REUSE-BY-DIFF 기본 부분 재검을 끄고 전체 게이트')
|
|
1128
1132
|
.option('--waive <node>', '저장된 실패 노드 한 개를 면제(--from 은 그 노드 그대로)')
|
|
1129
1133
|
.option('--reason <text>', '면제 사유 — 공개 알려진 문제에 들어갈 사용자 영향 설명')
|
|
1130
1134
|
.option('--accepted-regressions <json>', '알려진 문제 추가 입력 JSON 배열 [{"id":"…","note":"…"}]')
|
|
1135
|
+
.option('--gate-executor <pod|host>', '다시 도는 gate 의 실행기 전환(--from gate 이전만) — 런 입력에 기록 · 면제 아님')
|
|
1136
|
+
.option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 저장된 런 입력 gateRemote)')
|
|
1131
1137
|
.option('--json', '결과 한 줄 JSON(stdout)')
|
|
1132
|
-
.action(async (o: { run: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: string; json?: boolean }) => {
|
|
1138
|
+
.action(async (o: { run: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: string; gateExecutor?: string; gateHost?: string; json?: boolean }) => {
|
|
1133
1139
|
await jsonAction(o.json, async (log) => {
|
|
1134
1140
|
let acceptedRegressions: AcceptedRegression[] | undefined;
|
|
1135
1141
|
if (o.acceptedRegressions !== undefined) {
|
|
@@ -1143,12 +1149,17 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1143
1149
|
const result = await resumeReleaseRun({ runId: o.run, from: o.from, partial: o.partial,
|
|
1144
1150
|
...(o.waive === undefined ? {} : { waive: o.waive }),
|
|
1145
1151
|
...(o.reason === undefined ? {} : { reason: o.reason }),
|
|
1146
|
-
...(o.acceptedRegressions === undefined ? {} : { acceptedRegressions })
|
|
1152
|
+
...(o.acceptedRegressions === undefined ? {} : { acceptedRegressions }),
|
|
1153
|
+
...(o.gateExecutor === undefined ? {} : { gateExecutor: o.gateExecutor }),
|
|
1154
|
+
...(o.gateHost === undefined ? {} : { gateHost: o.gateHost }) });
|
|
1155
|
+
const override = result.state.inputOverrides?.at(-1);
|
|
1156
|
+
if (o.gateExecutor !== undefined && override) log(`⇄ gate 실행기 ${override.set.gateExecutor}${override.set.gateRemote ? ` @ ${override.set.gateRemote}` : ''} (런 입력에 기록 · 면제 아님)`);
|
|
1147
1157
|
if (result.partial.requested) log(result.partial.applied
|
|
1148
|
-
? `◐ 부분
|
|
1158
|
+
? `◐ 부분 재검${result.partial.auto ? '(기본)' : ''}: ${result.partial.files}파일${result.partial.closure ? ` (코드 닿음 ${result.partial.closure.reached} · 닫힘 불투명 ${result.partial.closure.opaque})` : ''} · 나머지는 앞 게이트(${result.partial.priorCommit.slice(0, 12)}) 결과를 잇는다`
|
|
1149
1159
|
: `● 전체 게이트로: ${result.partial.reason}`);
|
|
1150
1160
|
log(`${result.tip.changed ? `↻ ${result.tip.branch} ${result.tip.from.slice(0, 12)} → ${result.tip.to.slice(0, 12)} (백업 ${result.tip.backup})` : `· ${result.tip.branch} 끝 그대로 ${result.tip.to.slice(0, 12)}`} · ${o.from} 부터 → ${result.state.status}`);
|
|
1151
|
-
return { tip: result.tip, partial: result.partial, status: result.state.status, runId: result.state.runId
|
|
1161
|
+
return { tip: result.tip, partial: result.partial, status: result.state.status, runId: result.state.runId,
|
|
1162
|
+
...(o.gateExecutor !== undefined && result.state.inputOverrides?.length ? { gateExecutor: result.state.inputOverrides.at(-1) } : {}) };
|
|
1152
1163
|
}, (r) => r.status === 'done' || r.status === 'awaiting-approval');
|
|
1153
1164
|
});
|
|
1154
1165
|
release.command('rehearsal').description('판 일정에서 컷 전 가벼운 RC 두 단계').command('tick')
|
|
@@ -1175,14 +1186,14 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1175
1186
|
const result = await autoStartScheduledRelease({
|
|
1176
1187
|
windowMinutes: Number(o.windowMinutes), apply: o.apply, ledgerRoot: scheduleLedgerRoot(),
|
|
1177
1188
|
readiness: (version, ledgerRoot, now) => releaseReadiness(version, { ledgerRoot, now: () => now, checklist: releaseRunDeps.checklist }),
|
|
1178
|
-
launch: async (version) => {
|
|
1179
|
-
const ran = await runAction({ version, ifReady: true, json: false }, log);
|
|
1189
|
+
launch: async (version, launchOptions) => {
|
|
1190
|
+
const ran = await runAction({ version, ifReady: true, publishAt: launchOptions?.publishAt, json: false }, log);
|
|
1180
1191
|
if (ran && typeof ran === 'object' && ran.deferred) return ran;
|
|
1181
1192
|
if (ran !== true) throw new Error(`release run 미시작 또는 실패: ${version}`);
|
|
1182
1193
|
},
|
|
1183
1194
|
});
|
|
1184
1195
|
if (result.status === 'planned') log(`· 미리 보기 ${result.version} · 컷 ${result.cutAt} · 실행하려면 --apply`);
|
|
1185
|
-
else if (result.status === 'started') log(`▶ 릴리스 시작 ${result.version} · 컷 ${result.cutAt}`);
|
|
1196
|
+
else if (result.status === 'started') log(`▶ 릴리스 시작 ${result.version} · 컷 ${result.cutAt}${result.publishAt ? ` · 발행 ${result.publishAt}` : ''}`);
|
|
1186
1197
|
else if (result.status === 'skipped') log(`· 릴리스 연기 ${result.version} · ${result.reason}`);
|
|
1187
1198
|
else log('· 선택할 컷 없음');
|
|
1188
1199
|
return result;
|
|
@@ -2,6 +2,8 @@ import { closeSync, mkdirSync, openSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { debug } from '../debug/log.js';
|
|
4
4
|
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
5
|
+
import { adviseLaunch, compareLaunchAdvice } from '../harness/launch-advice.js';
|
|
6
|
+
import type { QueuePool } from '../harness/harness-queue.js';
|
|
5
7
|
import type { ReleaseReadiness } from '../../scripts/release-loop/release-readiness.js';
|
|
6
8
|
|
|
7
9
|
export type ReleaseIfReadySkip = { skipped: true; reason: Exclude<ReleaseReadiness, { ready: true }>['reason']; detail: string };
|
|
@@ -12,6 +14,8 @@ export async function runReleaseIfReady<T>(version: string, deps: {
|
|
|
12
14
|
ledgerRoot?: string;
|
|
13
15
|
pid?: number;
|
|
14
16
|
now?: () => Date;
|
|
17
|
+
advice?: typeof adviseLaunch;
|
|
18
|
+
pool?: () => QueuePool | undefined;
|
|
15
19
|
}): Promise<ReleaseIfReadySkip | { skipped: false; result: T }> {
|
|
16
20
|
const skip = (readiness: Exclude<ReleaseReadiness, { ready: true }>): ReleaseIfReadySkip => {
|
|
17
21
|
const detail = readiness.reason === 'checklist-blocked'
|
|
@@ -40,6 +44,13 @@ export async function runReleaseIfReady<T>(version: string, deps: {
|
|
|
40
44
|
const insideLock = await deps.readiness(version, { isPidAlive: () => false });
|
|
41
45
|
if (!insideLock.ready) return skip(insideLock);
|
|
42
46
|
debug.log('release-loop.readiness', 'ready', { version });
|
|
47
|
+
try {
|
|
48
|
+
const advice = (deps.advice ?? adviseLaunch)({ pool: deps.pool?.(), caller: 'release-run' });
|
|
49
|
+
const { kind } = compareLaunchAdvice(advice, 'launched');
|
|
50
|
+
debug.log('resource.advice', 'launch-advice', { caller: 'release-run', verdict: advice.verdict, why: advice.why, actual: 'launched', kind, version });
|
|
51
|
+
} catch {
|
|
52
|
+
// Shadow only: a throwing advice seam must never affect the launch decision or result.
|
|
53
|
+
}
|
|
43
54
|
return { skipped: false, result: await deps.run() };
|
|
44
55
|
} finally {
|
|
45
56
|
closeSync(fd);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
import { TRAFFIC_SEATS, type TrafficResult } from '../loops/orchestrator/traffic.js';
|
|
4
|
+
import { observeLoopResources } from '../nexus/api/loop-resources.js';
|
|
5
|
+
import { writeStdoutJson } from './stdout-json.js';
|
|
6
|
+
|
|
7
|
+
/** 칸 제목은 여러 줄(«대상 경로:»·«신설:» …)이다 — 표의 한 칸에는 첫 줄만, 상한을 넘으면 «…» 로 자른 것을 표시한다. */
|
|
8
|
+
export const RESOURCE_TITLE_MAX_CHARS = 60;
|
|
9
|
+
export function oneLineTitle(title: string): string {
|
|
10
|
+
const first = (title.split(/\r?\n/).find((line) => line.trim()) ?? '').replace(/\s+/g, ' ').trim();
|
|
11
|
+
return first.length > RESOURCE_TITLE_MAX_CHARS ? `${first.slice(0, RESOURCE_TITLE_MAX_CHARS - 1)}…` : first;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Read-only CLI view of the same traffic snapshot returned by the Nexus resource GET. */
|
|
15
|
+
export function registerResourceCommands(program: Command, observe: () => TrafficResult = observeLoopResources): void {
|
|
16
|
+
program.command('resource').description('자리별 루프 자원 관측 (읽기 전용)')
|
|
17
|
+
.command('status').description('자리별 공급·다음 칸·임대 상태')
|
|
18
|
+
.option('--json', '관측 스냅샷 JSON 출력')
|
|
19
|
+
.action(async (opts: { json?: boolean }) => {
|
|
20
|
+
let resource: TrafficResult;
|
|
21
|
+
try { resource = observe(); }
|
|
22
|
+
catch (error) {
|
|
23
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
24
|
+
debug.log('resource.loop', 'status-read', { readStatus: 'unreadable', seats: null, cells: null });
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
if (opts.json) await writeStdoutJson(JSON.stringify({ readStatus: 'unreadable', reason }) + '\n');
|
|
27
|
+
else console.error(`resource status: 못 읽음 — ${reason}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
debug.log('resource.loop', 'status-read', {
|
|
31
|
+
readStatus: 'ok', seats: resource.seats.length,
|
|
32
|
+
cells: resource.seats.filter(row => row.nextCell !== null).length,
|
|
33
|
+
});
|
|
34
|
+
if (opts.json) {
|
|
35
|
+
await writeStdoutJson(JSON.stringify({ resource, readStatus: 'ok' }) + '\n');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
console.log('자리\t쓰는 자리/공급\t다음 칸\t임대(빌림/빌려줌)\t대기 이유');
|
|
39
|
+
for (const seat of TRAFFIC_SEATS) {
|
|
40
|
+
const row = resource.seats.find(item => item.seat === seat);
|
|
41
|
+
if (!row) { console.log(`${seat}\t못 읽음\t못 읽음\t못 읽음\t자리 관측 없음`); continue; }
|
|
42
|
+
const cell = row.nextCell;
|
|
43
|
+
const reason = !cell ? '다음 칸 없음' : row.launchCap <= row.running ? '발사 자리 없음' : '다음 칸 대기';
|
|
44
|
+
console.log(`${seat}\t${row.running}/${row.cap}\t${cell ? `1 · ${cell.id} ${oneLineTitle(cell.title)}` : '0'}\t${row.borrowed}/${row.lent}\t${reason}`);
|
|
45
|
+
}
|
|
46
|
+
if (resource.unassigned > 0) console.log(`미배정\t${resource.unassigned}`);
|
|
47
|
+
});
|
|
48
|
+
}
|
package/src/cli/retro-cli.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import type { Command } from 'commander';
|
|
3
|
+
import { readRunExits } from '../harness/harness-incidents.js';
|
|
4
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
3
5
|
import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
|
|
4
6
|
|
|
5
|
-
type RetroFact = { store: string; at: string; category: string; event: string; kind: 'draft-birth' | 'draft-death' | 'stop-reason' | 'ta-outcome'; data: unknown };
|
|
7
|
+
type RetroFact = { store: string; at: string; category: string; event: string; kind: 'draft-birth' | 'draft-death' | 'stop-reason' | 'ta-outcome' | 'incident'; data: unknown };
|
|
6
8
|
|
|
7
9
|
const FACT_EVENTS = new Map<string, RetroFact['kind']>([
|
|
8
10
|
['rework-blocked-draft-pr', 'draft-birth'],
|
|
@@ -21,7 +23,7 @@ export function parseRetroSince(value: string, now = Date.now()): number {
|
|
|
21
23
|
return now - duration;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
export function collectRetroFacts(sinceMs: number, targets: readonly { name: string; dbPath: string }[] = [{ name: 'current', dbPath: logsDbPath() }]): { facts: RetroFact[]; unavailable: string[] } {
|
|
26
|
+
export function collectRetroFacts(sinceMs: number, targets: readonly { name: string; dbPath: string }[] = [{ name: 'current', dbPath: logsDbPath() }], incidentRoot?: string): { facts: RetroFact[]; unavailable: string[] } {
|
|
25
27
|
const facts: RetroFact[] = [];
|
|
26
28
|
const unavailable: string[] = [];
|
|
27
29
|
const untilMs = Date.now();
|
|
@@ -53,13 +55,20 @@ export function collectRetroFacts(sinceMs: number, targets: readonly { name: str
|
|
|
53
55
|
} finally { store.close(); }
|
|
54
56
|
} catch { unavailable.push(target.name); }
|
|
55
57
|
}
|
|
58
|
+
try {
|
|
59
|
+
for (const row of readRunExits(incidentRoot ?? effectiveInstanceRoot())) {
|
|
60
|
+
if (Date.parse(row.at) < sinceMs) continue;
|
|
61
|
+
facts.push({ store: 'incidents', at: row.at, category: 'harness.incident', event: row.reason, kind: 'incident',
|
|
62
|
+
data: { runId: row.runId, seat: row.seat, entrance: row.entrance } });
|
|
63
|
+
}
|
|
64
|
+
} catch { unavailable.push('incidents'); }
|
|
56
65
|
facts.sort((a, b) => b.at.localeCompare(a.at));
|
|
57
66
|
return { facts, unavailable };
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
export function registerRetroCommands(program: Command): void {
|
|
61
70
|
program.command('retro').description('Read-only retrospective facts from existing logs')
|
|
62
|
-
.command('facts').description('Draft births/deaths, stop reasons
|
|
71
|
+
.command('facts').description('Draft births/deaths, stop reasons, task-agent outcomes and run incidents')
|
|
63
72
|
.option('--since <duration>', 'Lookback duration', '24h')
|
|
64
73
|
.option('--json', 'JSON output')
|
|
65
74
|
.action((opts: { since: string; json?: boolean }) => {
|