elanous 0.2.24 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
- package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
- package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/release-loop.yaml +5 -5
- package/graphs/steward/recipes.yaml +4 -0
- package/graphs/steward/steward.yaml +10 -1
- package/package.json +1 -1
- package/scripts/bench-report.ts +46 -1
- package/scripts/ci-typecheck-changed.ts +88 -7
- package/scripts/coord-msg-bridge.ts +209 -0
- package/scripts/coord-post.sh +40 -7
- package/scripts/coord-requests-bridge.ts +10 -5
- package/scripts/expose-rubric-suggest.ts +1 -1
- package/scripts/measure-tsc-affected-roots.ts +10 -1
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- package/scripts/release-loop/export-check-node.ts +8 -5
- package/scripts/release-loop/gate-closure.ts +286 -0
- package/scripts/release-loop/gate-node.ts +73 -13
- package/scripts/release-loop/gate-partial.ts +34 -6
- package/scripts/release-loop/node-verdict.ts +7 -2
- package/scripts/release-loop/ops-upgrade-node.ts +63 -42
- package/scripts/release-loop/publish-node.ts +6 -0
- package/scripts/release-loop/resume-release.ts +37 -10
- package/scripts/release-loop/resume.ts +69 -4
- package/scripts/tsc-baseline-cache.ts +28 -3
- package/scripts/usage-rollup.ts +27 -13
- package/scripts/ux-sim.ts +30 -1
- package/skills/youtube-master/scripts/main.ts +4 -1
- package/skills/youtube-master/src/obsidian.ts +9 -0
- package/src/agent/task-notification.ts +30 -1
- package/src/agent-substrate/acp-implementer.ts +14 -7
- package/src/agent-substrate/pr-reviewer.ts +30 -10
- package/src/agent-substrate/review-observation.ts +9 -2
- package/src/agent-substrate/self-review-cli.ts +154 -16
- package/src/boot/daemon-tools/self-implement.ts +72 -4
- package/src/budget/cost-tier-advisor.ts +91 -0
- package/src/budget/llm-cost.ts +5 -1
- package/src/budget/shadow-arms.ts +77 -0
- package/src/budget/types.ts +5 -3
- package/src/budget/unified-usage.ts +172 -8
- package/src/cli/control-cli.ts +29 -0
- package/src/cli/doctor-cli.ts +106 -3
- package/src/cli/friendly-errors.ts +113 -0
- package/src/cli/intake-cli.ts +3 -1
- package/src/cli/memory-cli.ts +182 -0
- package/src/cli/model-watch-cli.ts +4 -1
- package/src/cli/msg-cli.ts +15 -5
- package/src/cli/pr-cli.ts +53 -0
- package/src/cli/pr-land-overlap-evidence.ts +18 -10
- package/src/cli/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +41 -12
- package/src/cli/release-run-if-ready.ts +11 -0
- package/src/cli/resource-cli.ts +48 -0
- package/src/cli/retro-cli.ts +12 -3
- package/src/cli/seat-cli.ts +121 -0
- package/src/cli/seat-requests-cli.ts +25 -0
- package/src/cli/self-utterances-cli.ts +140 -0
- package/src/cli/tasks-cli.ts +168 -14
- package/src/cli/usage-cli.ts +3 -1
- package/src/compact/verify-probe.ts +23 -3
- package/src/context-card/cell.ts +40 -0
- package/src/context-card/index.ts +50 -0
- package/src/control/control-status.ts +30 -1
- package/src/dashboard/boot-timing.ts +35 -0
- package/src/dashboard/index.ts +86 -24
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/debug/log-diet.ts +16 -4
- package/src/debug/log.ts +1 -1
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +29 -8
- package/src/domains/surface-events.ts +16 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +446 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/runner.ts +12 -6
- package/src/graph-wizard/archetypes.ts +14 -8
- package/src/graph-wizard/generate.ts +77 -1
- package/src/grok.ts +13 -7
- package/src/harness/harness-cli-command.ts +102 -51
- package/src/harness/harness-stop.ts +93 -19
- package/src/index.ts +52 -179
- package/src/instance/current.ts +2 -6
- package/src/instance/resolve.ts +5 -6
- package/src/intake-plane/collect-github.ts +7 -2
- package/src/intake-plane/lens.ts +46 -4
- package/src/intake-plane/requirement-funnel.ts +53 -1
- package/src/intelligence-map/catalog-feed.ts +119 -0
- package/src/intelligence-map/model-watch-intake.ts +40 -0
- package/src/intelligence-map/model-watch-mission.ts +14 -1
- package/src/llm/open-weight-discipline.ts +21 -0
- package/src/llm/openai-sampling-fields.ts +89 -0
- package/src/llm/runtime-model-family.ts +61 -0
- package/src/llm/zai-coding-plan.ts +27 -1
- package/src/llm.ts +17 -97
- package/src/machines/machine-ledger.ts +31 -3
- package/src/maturity/cli-maturity.ts +13 -3
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/msg/msg-store.ts +69 -7
- package/src/nexus/api/http-server.ts +22 -0
- package/src/oauth/codex-account-rotation.ts +4 -1
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-quota-policy.ts +33 -4
- package/src/ops/overview-collect.ts +3 -2
- package/src/ops/overview-owner.ts +29 -0
- package/src/plugin-hooks/shell-hook.ts +17 -2
- package/src/plugin-missions/evaluator-runner.ts +18 -2
- package/src/plugins/install/plugin-install.ts +11 -1
- package/src/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/prompt-enhance/enhance.ts +11 -0
- package/src/release-loop/auto-start.ts +7 -5
- package/src/release-loop/checklist.ts +52 -5
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/gate-shards.ts +4 -0
- package/src/release-loop/light-rc.ts +84 -13
- package/src/release-loop/merged-pr-checklist.ts +35 -5
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/seat-loop/duty-ledger.ts +64 -0
- package/src/seat-loop/seat-loop.ts +5 -1
- package/src/self-dev/decompose.ts +37 -3
- package/src/self-dev/dev-pipeline.ts +32 -7
- package/src/self-dev/draft-residue.ts +16 -6
- package/src/self-dev/draft-sweep.ts +75 -18
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/orchestrate.ts +6 -2
- package/src/self-dev/run-supervisor.ts +72 -8
- package/src/self-implement/gate-cli.ts +29 -10
- package/src/self-implement/gate-remote.ts +4 -1
- package/src/self-implement/goal-author.ts +15 -29
- package/src/self-implement/goal-command-execution.ts +26 -0
- package/src/self-implement/goal-new-paths.ts +42 -0
- package/src/self-implement/host-regate.ts +124 -30
- package/src/self-implement/importer-test-index.ts +3 -1
- package/src/self-implement/l8-merge-queue.ts +80 -2
- package/src/self-implement/merge-train.ts +19 -0
- package/src/self-implement/off-diff-evidence.ts +40 -1
- package/src/self-implement/orchestrator.ts +90 -20
- package/src/self-implement/premise-review.ts +159 -0
- package/src/self-implement/pwa-import-graph.ts +194 -7
- package/src/self-implement/regate-detail.ts +79 -0
- package/src/self-implement/review-deferred-to-host.ts +21 -0
- package/src/self-implement/rework-budget-judgment.ts +23 -3
- package/src/self-implement/running-runs.ts +2 -2
- package/src/self-implement/scope-adjacency.ts +23 -0
- package/src/self-implement/seams.ts +42 -7
- package/src/self-implement/self-implement-runtime.ts +126 -21
- package/src/session/index.ts +14 -4
- package/src/session-runtime/index.ts +55 -11
- package/src/skills/tools/agent.ts +16 -1
- package/src/skills/tools/persistent-grounding.ts +11 -1
- package/src/skills/tools/shell.ts +33 -1
- package/src/steward/rejudge-tick.ts +142 -0
- package/src/task-agent/board.ts +92 -3
- package/src/task-agent/card-evidence.ts +88 -1
- package/src/task-agent/cover.ts +85 -1
- package/src/task-agent/live-moves.ts +14 -6
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +370 -29
- package/src/task-agent/review-result-capture.ts +67 -2
- package/src/task-agent/shadow.ts +148 -21
- package/src/task-agent/task-hand.ts +22 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
- package/src/tool-runtime/tool-search-runtime.ts +25 -0
- package/src/tui.ts +20 -1
- package/src/user-config.ts +21 -63
- package/src/ux-sim/fault-cred-expiry.ts +100 -0
- package/src/ux-sim/fault-pod-death.ts +74 -0
- package/src/ux-sim/fault-pool-cap.ts +81 -0
- package/src/version/packed-revision.json +1 -1
- package/src/webclone/qa-table.ts +22 -0
- package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
- /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
package/scripts/bench-report.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { spawnSync } from 'node:child_process';
|
|
14
14
|
import { readFileSync } from 'node:fs';
|
|
15
15
|
import { dirname, join } from 'node:path';
|
|
16
|
+
import { dedupePodRollupRows } from './usage-rollup.js';
|
|
16
17
|
|
|
17
18
|
export interface LogRow { category?: string; event?: string; data?: Record<string, unknown> | null }
|
|
18
19
|
export interface ArmDecl { id: string; provider: string; model: string | null }
|
|
@@ -40,6 +41,40 @@ export interface ArmReport {
|
|
|
40
41
|
reviewMustFixCount: number | null;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
export interface ProbeJudgment {
|
|
45
|
+
model: string;
|
|
46
|
+
runs: number;
|
|
47
|
+
passed: number;
|
|
48
|
+
failed: number;
|
|
49
|
+
unmeasured: number;
|
|
50
|
+
verdict: 'pass' | 'fail' | 'unmeasured';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function judgeProbe(
|
|
54
|
+
arms: readonly ArmReport[],
|
|
55
|
+
opts?: { passNumerator?: number; passDenominator?: number },
|
|
56
|
+
): ProbeJudgment[] {
|
|
57
|
+
const passNumerator = opts?.passNumerator ?? 8;
|
|
58
|
+
const passDenominator = opts?.passDenominator ?? 9;
|
|
59
|
+
const groups = new Map<string, { runs: number; passed: number; failed: number; unmeasured: number }>();
|
|
60
|
+
for (const arm of arms) {
|
|
61
|
+
const model = arm.declared?.model ?? '못 이음';
|
|
62
|
+
const group = groups.get(model) ?? { runs: 0, passed: 0, failed: 0, unmeasured: 0 };
|
|
63
|
+
group.runs++;
|
|
64
|
+
if (arm.gatePassed === null || arm.leakCalls === null) group.unmeasured++;
|
|
65
|
+
else if (arm.gatePassed === true && arm.leakCalls === 0) group.passed++;
|
|
66
|
+
else group.failed++;
|
|
67
|
+
groups.set(model, group);
|
|
68
|
+
}
|
|
69
|
+
return [...groups].map(([model, counts]) => ({
|
|
70
|
+
model,
|
|
71
|
+
...counts,
|
|
72
|
+
verdict: counts.unmeasured > 0
|
|
73
|
+
? 'unmeasured'
|
|
74
|
+
: counts.passed * passDenominator >= counts.runs * passNumerator ? 'pass' : 'fail',
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
|
|
43
78
|
const num = (v: unknown): number => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
|
|
44
79
|
const str = (v: unknown): string | null => (typeof v === 'string' && v.length > 0 ? v : null);
|
|
45
80
|
const armKey = (id: string): string => (id.startsWith('pod/') ? id : `pod/${id}`);
|
|
@@ -99,7 +134,8 @@ export function buildBenchReport(rows: readonly LogRow[], runId: string): { runI
|
|
|
99
134
|
a.reviewMustFixCount = typeof r.data!.reviewMustFixCount === 'number' ? r.data!.reviewMustFixCount : null;
|
|
100
135
|
}
|
|
101
136
|
const leak = new Map<string, number>();
|
|
102
|
-
|
|
137
|
+
// ⭐ METER-POD-ROLLUP-GAP-2 — 같은 Pod 의 재방출(부분 ⊕ 최종 · abort ⊕ resume)은 podRollupKey 로 한 번만 센다(팔 사용량 이중계상 방지).
|
|
138
|
+
for (const r of dedupePodRollupRows(mine, (row) => (row.event === 'llm-usage' ? row.data ?? {} : {}))) {
|
|
103
139
|
if (r.event !== 'llm-usage') continue;
|
|
104
140
|
const site = str(r.data!.site);
|
|
105
141
|
const id = str(r.data!.armId);
|
|
@@ -203,6 +239,15 @@ export function renderBenchReport(rep: ReturnType<typeof buildBenchReport>): str
|
|
|
203
239
|
lines.push(leaked.length
|
|
204
240
|
? `⛔ 팔 밖 모델로 간 호출이 있다(${leaked.join(', ')}) — 이 판으로 팔을 비교하지 않는다.`
|
|
205
241
|
: '⛔ 한 판(팔당 N=1)이다 — 결론이 아니라 관측이다. 비교는 팔마다 표본이 쌓인 뒤에.');
|
|
242
|
+
const probe = judgeProbe(rep.arms);
|
|
243
|
+
lines.push(
|
|
244
|
+
'',
|
|
245
|
+
'## 프로브 판정',
|
|
246
|
+
'',
|
|
247
|
+
'| 모델 | 통과/런 | 판정 |',
|
|
248
|
+
'|---|---:|---|',
|
|
249
|
+
...probe.map((row) => `| ${row.model} | ${row.passed}/${row.runs} | ${row.verdict} |`),
|
|
250
|
+
);
|
|
206
251
|
return lines.join('\n');
|
|
207
252
|
}
|
|
208
253
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Changed-file tsc gate with a visible ratchet for pre-existing test-only debt. */
|
|
2
2
|
import { execFileSync, execSync } from 'node:child_process';
|
|
3
|
-
import { existsSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync } from 'node:fs';
|
|
3
|
+
import { existsSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import ts from 'typescript';
|
|
@@ -13,10 +13,12 @@ import {
|
|
|
13
13
|
type TypecheckError,
|
|
14
14
|
} from '../src/typecheck-ratchet.js';
|
|
15
15
|
import { debug } from '../src/debug/log.js';
|
|
16
|
+
import { reverseImportAffectedRoots, type AffectedRoots } from '../src/self-implement/pwa-import-graph.js';
|
|
16
17
|
import {
|
|
17
18
|
ROOT_PLACEHOLDER,
|
|
18
19
|
baselineCacheEnabled,
|
|
19
20
|
computeBaselineCacheKey,
|
|
21
|
+
workingTreeInstallKey,
|
|
20
22
|
lookupBaselineCache,
|
|
21
23
|
storeBaselineCache,
|
|
22
24
|
toPlaceholderPaths,
|
|
@@ -819,22 +821,23 @@ export function rebaseWorktreePaths(diagnostics: readonly TypecheckError[], work
|
|
|
819
821
|
export type BaselineCacheIo = BaselineCacheOptions & { log?: (message: string) => void };
|
|
820
822
|
|
|
821
823
|
/**
|
|
822
|
-
* 같은 base 커밋 ⊕ 같은 명령 ⊕ 같은 설정
|
|
824
|
+
* 같은 base 커밋 ⊕ 같은 명령 ⊕ 같은 설정 해시 ⊕ 같은 작업 트리 설치 키면 저장된 진단을 재사용한다(워크트리·tsc 0회).
|
|
823
825
|
* 캐시의 어떤 실패도 던지지 않는다 — miss 로 떨어져 아래 측정이 그대로 돈다.
|
|
824
826
|
*/
|
|
825
|
-
function lookupCachedBaseline(key: string, command: string, cwd: string, cacheIo: BaselineCacheIo): BaselineDiagnostics | undefined {
|
|
827
|
+
function lookupCachedBaseline(key: string, command: string, cwd: string, cacheIo: BaselineCacheIo, installKey?: string): BaselineDiagnostics | undefined {
|
|
826
828
|
const lookup = lookupBaselineCache(key, cacheIo);
|
|
827
829
|
const result = lookup.result === 'hit' ? 'hit' : lookup.result === 'corrupt' ? 'corrupt' : 'miss';
|
|
828
|
-
cacheIo.log?.(`[tsc-gate] typecheck baseline-cache ${result === 'hit' ? 'hit' : 'miss'} ${key.slice(0, 12)}`);
|
|
829
|
-
debug.log('typecheck.gate', 'baseline-cache', { result, key, command });
|
|
830
|
+
cacheIo.log?.(`[tsc-gate] typecheck baseline-cache ${result === 'hit' ? 'hit' : 'miss'} ${key.slice(0, 12)} installKey ${installKey?.slice(0, 12) ?? 'n/a'}`);
|
|
831
|
+
debug.log('typecheck.gate', 'baseline-cache', { result, key, command, installKey: installKey ?? null });
|
|
830
832
|
if (lookup.result !== 'hit') return undefined;
|
|
831
833
|
return { diagnostics: rebaseWorktreePaths(lookup.diagnostics, ROOT_PLACEHOLDER, cwd) };
|
|
832
834
|
}
|
|
833
835
|
|
|
834
836
|
export function readMergeBaseDiagnostics(base: string, command: string, cwd = process.cwd(), run = runTsc, cacheIo: BaselineCacheIo = {}): BaselineDiagnostics {
|
|
835
837
|
const cacheKey = baselineCacheEnabled(cacheIo.env ?? process.env) ? computeBaselineCacheKey(base, command, cwd, cacheIo) : undefined;
|
|
838
|
+
const installKey = cacheKey ? workingTreeInstallKey(cwd, cacheIo) : undefined;
|
|
836
839
|
if (cacheKey) {
|
|
837
|
-
const cached = lookupCachedBaseline(cacheKey, command, cwd, cacheIo);
|
|
840
|
+
const cached = lookupCachedBaseline(cacheKey, command, cwd, cacheIo, installKey);
|
|
838
841
|
if (cached) return cached;
|
|
839
842
|
}
|
|
840
843
|
const workspace = mkdtempSync(join(tmpdir(), 'ci-typecheck-baseline-'));
|
|
@@ -874,6 +877,10 @@ export type GateIo = {
|
|
|
874
877
|
cwd?: string;
|
|
875
878
|
/** Explicit base revision. Same rule as TSC_BASE_REF, without reading the process environment. */
|
|
876
879
|
baseRef?: string;
|
|
880
|
+
/** Source of TSC_GATE_ROOTS / ELANOUS_TSC_AFFECTED_ROOTS. Defaults to process.env. */
|
|
881
|
+
env?: NodeJS.ProcessEnv;
|
|
882
|
+
/** Changed gate sources → themselves plus their direct importers. Defaults to the repository import-graph reader. */
|
|
883
|
+
affectedRoots?: (cwd: string, changed: ReadonlySet<string>) => AffectedRoots;
|
|
877
884
|
log: (message: string) => void;
|
|
878
885
|
warn: (message: string) => void;
|
|
879
886
|
error: (message: string) => void;
|
|
@@ -942,6 +949,47 @@ function inspectTscResult(tsc: TscRun, changed: ReadonlySet<string>, baseline: R
|
|
|
942
949
|
return false;
|
|
943
950
|
}
|
|
944
951
|
|
|
952
|
+
/** Above this many roots a narrowed program stops being much smaller than the whole one. */
|
|
953
|
+
export const TSC_GATE_ROOT_LIMIT = 400;
|
|
954
|
+
/** Files tsconfig.gate.json compiles as roots (its `include`); other changed .ts files are never part of that program. */
|
|
955
|
+
const GATE_ROOT_SOURCE = /^(?:src|scripts|test)\/.*\.ts$/;
|
|
956
|
+
|
|
957
|
+
export type RootPlan =
|
|
958
|
+
| { mode: 'affected'; roots: string[]; changedCount: number }
|
|
959
|
+
| { mode: 'full'; fallbackReason: string; roots?: number };
|
|
960
|
+
|
|
961
|
+
/** Narrow the root-config check to changed files ∪ direct importers, or say why the whole program must run. */
|
|
962
|
+
export function planRootCheck(input: {
|
|
963
|
+
wholeRepository: boolean;
|
|
964
|
+
rootChanged: ReadonlySet<string>;
|
|
965
|
+
env: NodeJS.ProcessEnv;
|
|
966
|
+
cwd: string;
|
|
967
|
+
affectedRoots: (cwd: string, changed: ReadonlySet<string>) => AffectedRoots;
|
|
968
|
+
}): RootPlan {
|
|
969
|
+
if (input.wholeRepository) return { mode: 'full', fallbackReason: '승격(저장소 전체 검사)' };
|
|
970
|
+
if (input.env.ELANOUS_TSC_AFFECTED_ROOTS === '0') return { mode: 'full', fallbackReason: 'ELANOUS_TSC_AFFECTED_ROOTS=0' };
|
|
971
|
+
if (input.env.TSC_GATE_ROOTS === 'full') return { mode: 'full', fallbackReason: 'TSC_GATE_ROOTS=full' };
|
|
972
|
+
const gateChanged = new Set([...input.rootChanged].filter((file) => GATE_ROOT_SOURCE.test(file)));
|
|
973
|
+
if (gateChanged.size === 0) return { mode: 'full', fallbackReason: 'tsconfig.gate.json 루트에 드는 변경 파일 없음' };
|
|
974
|
+
let computed: AffectedRoots;
|
|
975
|
+
try { computed = input.affectedRoots(input.cwd, gateChanged); }
|
|
976
|
+
catch (cause) { return { mode: 'full', fallbackReason: `루트 계산 실패: ${cause instanceof Error ? cause.message : String(cause)}` }; }
|
|
977
|
+
if (computed.failure !== undefined) return { mode: 'full', fallbackReason: `루트 계산 실패: ${computed.failure}` };
|
|
978
|
+
if (!computed.roots || [...gateChanged].some((file) => !computed.roots?.has(file))) {
|
|
979
|
+
return { mode: 'full', fallbackReason: '루트 계산 실패: 변경 파일 누락' };
|
|
980
|
+
}
|
|
981
|
+
const roots = [...computed.roots].filter((file) => GATE_ROOT_SOURCE.test(file)).sort();
|
|
982
|
+
if (roots.length > TSC_GATE_ROOT_LIMIT) return { mode: 'full', fallbackReason: `루트 ${roots.length}개 > 상한 ${TSC_GATE_ROOT_LIMIT}`, roots: roots.length };
|
|
983
|
+
return { mode: 'affected', roots, changedCount: gateChanged.size };
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* K-OP-039 · 노하우를 «도구 출력»에 싣는 첫 조각(대표 2026-10-12 «어떤 에이전트가 와도 같은 수준»).
|
|
987
|
+
* 승격된 전체 판정은 `apps/pwa/node_modules` 가 없으면 «가짜» PWA 타입 에러만 낸다 —
|
|
988
|
+
* 10-12 하루 TC·UX 두 자리가 같은 가짜 TS2322(ChatMessage.tsx)로 코드를 고치려 했다.
|
|
989
|
+
* 카드(내부 문서 `KNOWHOW` K-OP-039)의 처방 문면을 그대로 도구 출력에 싣는다.
|
|
990
|
+
*/
|
|
991
|
+
const PWA_DEPS_MISSING_HINT = '환경: apps/pwa 의존성 없음 — (cd apps/pwa && bun install --frozen-lockfile) 뒤 재실행 · 코드 결함 아님(K-OP-039)';
|
|
992
|
+
|
|
945
993
|
export function runGate(io: Partial<GateIo> = {}): void {
|
|
946
994
|
const cwd = io.cwd ?? process.cwd();
|
|
947
995
|
const defaultChanged = () => changedTsFiles((cmd) => sh(cmd, cwd), process.env, cwd, io.baseRef);
|
|
@@ -1051,6 +1099,14 @@ export function runGate(io: Partial<GateIo> = {}): void {
|
|
|
1051
1099
|
}, { level: 'info' });
|
|
1052
1100
|
log(`[tsc-gate] root 설정 범위 ${rootScope.size}개 관측 (apps/pwa/** 제외).`);
|
|
1053
1101
|
if (runsPwa) log(`[tsc-gate] PWA 설정 범위 ${pwaScope.size}개 관측.`);
|
|
1102
|
+
// ⛔ K-OP-039: 승격된 전체 판정은 apps/pwa 의존성 없이는 «가짜» PWA 타입 에러만 낸다(환경 문제 · 코드 결함 아님).
|
|
1103
|
+
// 그 오류를 내기 «전에» 이 한 줄로 멈춘다(환경 줄이 곧 마지막 줄 = 판정) — 의존성이 있으면 아래
|
|
1104
|
+
// 판정 규칙·출력 형식은 기존 그대로다. «못 쟀다 ≠ 통과» — PWA 미측정을 통과로 접지 않는다.
|
|
1105
|
+
if (wholeRepository && !existsSync(join(cwd, 'apps/pwa/node_modules'))) {
|
|
1106
|
+
error(`[tsc-gate] ${PWA_DEPS_MISSING_HINT}`);
|
|
1107
|
+
exit(1);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1054
1110
|
const tscBin = existsSync(join(cwd, 'node_modules/.bin/tsc')) ? 'node_modules/.bin/tsc' : 'npx tsc';
|
|
1055
1111
|
const baseline = readTestTypecheckBaseline(cwd);
|
|
1056
1112
|
const rootCommand = `${tscBin} --noEmit -p ${TYPECHECK_GATE_CONFIG}`;
|
|
@@ -1059,7 +1115,32 @@ export function runGate(io: Partial<GateIo> = {}): void {
|
|
|
1059
1115
|
const rootPromotionBaseline = wholeRepository ? readBaselineDiagnostics(base, rootCommand) : undefined;
|
|
1060
1116
|
const pwaPromotionBaseline = wholeRepository && runsPwa ? readBaselineDiagnostics(base, pwaCommand) : undefined;
|
|
1061
1117
|
const pwaEnvPromotionBaseline = wholeRepository && runsPwaEnv ? readBaselineDiagnostics(base, pwaEnvCommand) : undefined;
|
|
1062
|
-
|
|
1118
|
+
let rootPlan = planRootCheck({ wholeRepository, rootChanged, env: io.env ?? process.env, cwd, affectedRoots: io.affectedRoots ?? reverseImportAffectedRoots });
|
|
1119
|
+
let rootsConfig: string | undefined;
|
|
1120
|
+
if (rootPlan.mode === 'affected') {
|
|
1121
|
+
rootsConfig = `tsconfig.gate-roots.${process.pid}.${Date.now()}.json`;
|
|
1122
|
+
try {
|
|
1123
|
+
// `include` is replaced (not merged) so only the listed roots plus ambient declarations enter the program.
|
|
1124
|
+
writeFileSync(join(cwd, rootsConfig), JSON.stringify({ extends: `./${TYPECHECK_GATE_CONFIG}`, include: ['src/**/*.d.ts', 'scripts/**/*.d.ts', 'test/**/*.d.ts'], files: rootPlan.roots }, null, 2), { flag: 'wx' });
|
|
1125
|
+
} catch (cause) {
|
|
1126
|
+
if (rootsConfig && (cause as NodeJS.ErrnoException).code !== 'EEXIST') {
|
|
1127
|
+
try { rmSync(join(cwd, rootsConfig), { force: true }); }
|
|
1128
|
+
catch { /* The full-program fallback still runs if cleanup is unavailable. */ }
|
|
1129
|
+
}
|
|
1130
|
+
rootsConfig = undefined;
|
|
1131
|
+
rootPlan = { mode: 'full', fallbackReason: `임시 tsconfig 쓰기 실패: ${cause instanceof Error ? cause.message : String(cause)}`, roots: rootPlan.roots.length };
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (rootPlan.mode === 'affected') {
|
|
1135
|
+
log(`[tsc-gate] 영향 루트 ${rootPlan.roots.length}개 (변경 ${rootPlan.changedCount} + importer·전역 선언 ${rootPlan.roots.length - rootPlan.changedCount}) — 임시 tsconfig 로 root 검사.`);
|
|
1136
|
+
debug.log('typecheck.gate', 'roots', { mode: 'affected', roots: rootPlan.roots.length, fallbackReason: null }, { level: 'info' });
|
|
1137
|
+
} else {
|
|
1138
|
+
log(`[tsc-gate] 영향 루트 ${rootPlan.roots ?? '?'}개(전체로 폴백: ${rootPlan.fallbackReason})`);
|
|
1139
|
+
debug.log('typecheck.gate', 'roots', { mode: 'full', roots: rootPlan.roots ?? null, fallbackReason: rootPlan.fallbackReason }, { level: 'info' });
|
|
1140
|
+
}
|
|
1141
|
+
let rootTsc: TscRun;
|
|
1142
|
+
try { rootTsc = runTscCmd(rootsConfig ? `${tscBin} --noEmit -p ${rootsConfig}` : rootCommand); }
|
|
1143
|
+
finally { if (rootsConfig) rmSync(join(cwd, rootsConfig), { force: true }); }
|
|
1063
1144
|
let unmeasured = !rootTsc.ran;
|
|
1064
1145
|
let passed = inspectTscResult(rootTsc, rootScope, baseline, error, warn, wholeRepository, ['apps/pwa/'], [], rootPromotionBaseline);
|
|
1065
1146
|
if (runsPwa) {
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** One channel fetch, one recipient's durable cursor, and idempotent msg insertion. */
|
|
3
|
+
import { Database } from 'bun:sqlite';
|
|
4
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { effectiveInstanceRoot } from '../src/instance/resolve.js';
|
|
8
|
+
import { SEAT_ALIASES, canonicalSeatId, defaultMsgStorePath, openMsgStore } from '../src/msg/msg-store.js';
|
|
9
|
+
import trackData from './coord-tracks.json';
|
|
10
|
+
import { fetchCoordChannelComments, type CoordChannelComment } from './coord-requests-bridge.js';
|
|
11
|
+
|
|
12
|
+
const seats = new Set(trackData.tracks.map((track) => track.id));
|
|
13
|
+
const allSeats = [...seats];
|
|
14
|
+
type Options = { seat: string; channel: string; since?: string; dryRun: boolean };
|
|
15
|
+
type Cursor = { lastId: number; createdAt: string; sinceFloor?: string; parserHash?: string };
|
|
16
|
+
type Routed = { sender: string; recipients: string[] };
|
|
17
|
+
|
|
18
|
+
function parseOptions(args: string[]): Options {
|
|
19
|
+
let seat = '', channel = '26146', since: string | undefined;
|
|
20
|
+
let dryRun = false;
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
const arg = args[i];
|
|
23
|
+
if (arg === '--seat' && args[i + 1]) seat = canonicalSeatId(args[++i]!);
|
|
24
|
+
else if (arg === '--channel' && args[i + 1]) channel = args[++i]!;
|
|
25
|
+
else if (arg === '--since' && args[i + 1]) since = args[++i]!;
|
|
26
|
+
else if (arg === '--dry-run') dryRun = true;
|
|
27
|
+
else if (arg === '--json') continue; // output formatting belongs to the CLI entry point
|
|
28
|
+
else throw new Error(`unknown option or missing value: ${arg}`);
|
|
29
|
+
}
|
|
30
|
+
if (!seats.has(seat)) throw new Error('--seat must name a channel seat');
|
|
31
|
+
if (!/^[1-9]\d*$/.test(channel)) throw new Error('--channel must be a positive integer');
|
|
32
|
+
if (since && (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(since)
|
|
33
|
+
|| !Number.isFinite(Date.parse(since)))) throw new Error('--since must be an ISO timestamp');
|
|
34
|
+
return { seat, channel, ...(since ? { since } : {}), dryRun };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Only the address part of the first line and explicit body mentions route messages. */
|
|
38
|
+
export function routeCoordComment(body: string): Routed | null {
|
|
39
|
+
const [header = '', ...bodyLines] = body.split(/\r?\n/);
|
|
40
|
+
const match = /^\s*(?:#+\s*)?\*\*\[([^\]]+)\]\*\*[^\n]*?→\s*(.+)$/.exec(header);
|
|
41
|
+
if (!match) return null;
|
|
42
|
+
let sender: string;
|
|
43
|
+
try { sender = canonicalSeatId(match[1]!); } catch { return null; }
|
|
44
|
+
const recipients = new Set<string>();
|
|
45
|
+
// The channel also uses `MK(⊕ UX·TC)` for a primary addressee plus copied seats.
|
|
46
|
+
const address = match[2]!.replace(/\(⊕\s*([^)]*)\)/g, ' · cc $1');
|
|
47
|
+
const fields = address.split('·').map((part) => part.trim());
|
|
48
|
+
let inAddress = true;
|
|
49
|
+
for (const field of fields) {
|
|
50
|
+
const cc = /^cc\s+(.+)$/i.exec(field);
|
|
51
|
+
if (!inAddress && !cc) continue;
|
|
52
|
+
const tokens = (cc?.[1] ?? field).split(/[\s,]+/).filter(Boolean);
|
|
53
|
+
// A title may follow the addressee without a middle dot, for example
|
|
54
|
+
// `→ OP 🎓 확인:`. Only the leading seat tokens belong to the address.
|
|
55
|
+
const firstNonSeat = tokens.findIndex((name) => !seats.has(name)
|
|
56
|
+
&& name !== '전체' && name !== '전원');
|
|
57
|
+
const names = tokens.slice(0, firstNonSeat < 0 ? tokens.length : firstNonSeat);
|
|
58
|
+
if (!names.length) {
|
|
59
|
+
if (!cc) inAddress = false;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (names.includes('전체') || names.includes('전원')) {
|
|
63
|
+
for (const seat of allSeats) recipients.add(seat);
|
|
64
|
+
} else for (const name of names) recipients.add(name);
|
|
65
|
+
if (!cc && names.length < tokens.length) inAddress = false;
|
|
66
|
+
}
|
|
67
|
+
for (const match of bodyLines.join('\n').matchAll(/🙋\s*([A-Z][A-Z0-9_-]*)/g)) {
|
|
68
|
+
if (seats.has(match[1]!)) recipients.add(match[1]!);
|
|
69
|
+
}
|
|
70
|
+
recipients.delete(sender);
|
|
71
|
+
return { sender, recipients: [...recipients] };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Include the sender canonicalizer and its aliases: either can change which
|
|
75
|
+
// comments route. A harmless build-only hash change causes one safe replay.
|
|
76
|
+
const parserHash = createHash('sha256').update(routeCoordComment.toString())
|
|
77
|
+
.update(canonicalSeatId.toString()).update(JSON.stringify(SEAT_ALIASES))
|
|
78
|
+
.update(JSON.stringify(allSeats)).digest('hex');
|
|
79
|
+
const REPLAY_WINDOW_MS = 6 * 60 * 60 * 1000;
|
|
80
|
+
|
|
81
|
+
function validComment(value: CoordChannelComment): void {
|
|
82
|
+
if (!value || !Number.isSafeInteger(value.id) || value.id <= 0 || typeof value.body !== 'string'
|
|
83
|
+
|| typeof value.created_at !== 'string' || !Number.isFinite(Date.parse(value.created_at))
|
|
84
|
+
|| typeof value.html_url !== 'string') throw new Error('invalid channel comment');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readCursor(path: string): Cursor | null {
|
|
88
|
+
if (!existsSync(path)) return null;
|
|
89
|
+
// Each run appends one small record. Concurrent runs cannot replace a newer cursor
|
|
90
|
+
// with an older snapshot; the highest comment ID remains the effective cursor.
|
|
91
|
+
let latest: Cursor | null = null;
|
|
92
|
+
// A process can stop mid-append. The next complete record begins with the
|
|
93
|
+
// stable key prefix and remains readable even when joined to a torn suffix.
|
|
94
|
+
const records = readFileSync(path, 'utf8').replaceAll('{"lastId":', '\n{"lastId":').split('\n').filter(Boolean);
|
|
95
|
+
for (const line of records) {
|
|
96
|
+
let value: Partial<Cursor>;
|
|
97
|
+
try { value = JSON.parse(line) as Partial<Cursor>; }
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (error instanceof SyntaxError) continue;
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
if (!Number.isSafeInteger(value.lastId) || value.lastId! < 0 || typeof value.createdAt !== 'string'
|
|
103
|
+
|| !Number.isFinite(Date.parse(value.createdAt)) || (value.sinceFloor !== undefined
|
|
104
|
+
&& (typeof value.sinceFloor !== 'string' || !Number.isFinite(Date.parse(value.sinceFloor))))
|
|
105
|
+
|| (value.parserHash !== undefined && !/^[a-f0-9]{64}$/.test(value.parserHash))) {
|
|
106
|
+
throw new Error('invalid channel cursor');
|
|
107
|
+
}
|
|
108
|
+
// On equal IDs, keep the current parser marker even if an older overlapping
|
|
109
|
+
// process appends its stale cursor afterward. A current marker also replaces
|
|
110
|
+
// an older marker at the same ID after a replay with no newly fetched comment.
|
|
111
|
+
if (!latest || value.lastId! > latest.lastId || (value.lastId === latest.lastId
|
|
112
|
+
&& (value.parserHash === parserHash || latest.parserHash !== parserHash))) latest = {
|
|
113
|
+
lastId: value.lastId!, createdAt: value.createdAt,
|
|
114
|
+
...(value.sinceFloor ? { sinceFloor: value.sinceFloor } : {}),
|
|
115
|
+
...(value.parserHash ? { parserHash: value.parserHash } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return latest;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function saveCursor(path: string, cursor: Cursor): void {
|
|
122
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
123
|
+
appendFileSync(path, `${JSON.stringify(cursor)}\n`, { mode: 0o600 });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function hasProvenance(db: Database, key: string): boolean {
|
|
127
|
+
return db.query('SELECT 1 FROM msg_provenance WHERE provenance_key = ?').get(key) !== null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function runBridge(args: string[], fetch = fetchCoordChannelComments): {
|
|
131
|
+
seat: string; read: number; picked: number; added: number; existing: number; cursor: number;
|
|
132
|
+
} {
|
|
133
|
+
return runBridgeWithClock(args, fetch, Date.now);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function runBridgeWithClock(args: string[], fetch: typeof fetchCoordChannelComments, now: () => number): {
|
|
137
|
+
seat: string; read: number; picked: number; added: number; existing: number; cursor: number;
|
|
138
|
+
} {
|
|
139
|
+
const options = parseOptions(args);
|
|
140
|
+
const cursorPath = join(effectiveInstanceRoot(), 'msg', `coord-bridge-${options.channel}-${options.seat}.json`);
|
|
141
|
+
const cursor = readCursor(cursorPath);
|
|
142
|
+
const replayFloor = cursor && cursor.parserHash !== parserHash ? now() - REPLAY_WINDOW_MS : undefined;
|
|
143
|
+
// GitHub filters `since` by updated_at; the creation-time check below limits
|
|
144
|
+
// parser replay to comments created in the last six hours, even if older
|
|
145
|
+
// comments were edited recently. Numeric IDs decide normal progress.
|
|
146
|
+
// GitHub's `since` is exclusive. Fetch one second before the replay floor
|
|
147
|
+
// so a comment created exactly on the six-hour boundary remains visible.
|
|
148
|
+
const since = cursor ? new Date(Math.min(Date.parse(cursor.createdAt) - 1000,
|
|
149
|
+
replayFloor === undefined ? Infinity : replayFloor - 1000)).toISOString() : options.since;
|
|
150
|
+
const comments = fetch(options.channel, since);
|
|
151
|
+
for (const comment of comments) validComment(comment); // no writes if fetching/parsing fails mid-page
|
|
152
|
+
// GitHub's `since` filters updated_at, so a caller's creation-time floor persists across runs.
|
|
153
|
+
const unseen = comments.filter((comment) => comment.id > (cursor?.lastId ?? 0));
|
|
154
|
+
const sinceFloor = cursor?.sinceFloor ?? (cursor ? undefined : options.since);
|
|
155
|
+
const pending = comments.filter((comment) =>
|
|
156
|
+
(comment.id > (cursor?.lastId ?? 0) || (replayFloor !== undefined
|
|
157
|
+
&& Date.parse(comment.created_at) >= replayFloor))
|
|
158
|
+
&& (!sinceFloor || Date.parse(comment.created_at) >= Date.parse(sinceFloor)));
|
|
159
|
+
const candidate = unseen.reduce<CoordChannelComment | null>((last, comment) =>
|
|
160
|
+
!last || comment.id > last.id ? comment : last, null);
|
|
161
|
+
let picked = 0, added = 0, existing = 0;
|
|
162
|
+
const dbPath = defaultMsgStorePath();
|
|
163
|
+
if (options.dryRun) {
|
|
164
|
+
const db = existsSync(dbPath) ? new Database(dbPath, { readonly: true }) : null;
|
|
165
|
+
try {
|
|
166
|
+
for (const comment of pending) {
|
|
167
|
+
const route = routeCoordComment(comment.body);
|
|
168
|
+
if (!route?.recipients.includes(options.seat)) continue;
|
|
169
|
+
picked++;
|
|
170
|
+
if (db && hasProvenance(db, `coord:${comment.id}:${options.seat}`)) existing++;
|
|
171
|
+
else added++;
|
|
172
|
+
}
|
|
173
|
+
} finally { db?.close(); }
|
|
174
|
+
} else {
|
|
175
|
+
const store = openMsgStore();
|
|
176
|
+
try {
|
|
177
|
+
store.db.transaction(() => {
|
|
178
|
+
for (const comment of pending) {
|
|
179
|
+
const route = routeCoordComment(comment.body);
|
|
180
|
+
if (!route?.recipients.includes(options.seat)) continue;
|
|
181
|
+
picked++;
|
|
182
|
+
const key = `coord:${comment.id}:${options.seat}`;
|
|
183
|
+
if (hasProvenance(store.db, key)) existing++;
|
|
184
|
+
else added++;
|
|
185
|
+
store.appendWithProvenance({ from: route.sender, to: options.seat, body: comment.body, kind: 'coord' }, key);
|
|
186
|
+
}
|
|
187
|
+
}).immediate();
|
|
188
|
+
} finally { store.close(); }
|
|
189
|
+
if (candidate || (!cursor && sinceFloor) || replayFloor !== undefined) {
|
|
190
|
+
const createdAt = candidate?.created_at ?? cursor?.createdAt ?? sinceFloor!;
|
|
191
|
+
saveCursor(cursorPath, { lastId: candidate?.id ?? cursor?.lastId ?? 0,
|
|
192
|
+
createdAt: sinceFloor && Date.parse(createdAt) < Date.parse(sinceFloor) ? sinceFloor : createdAt,
|
|
193
|
+
...(sinceFloor ? { sinceFloor } : {}), parserHash });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return { seat: options.seat, read: comments.length, picked, added, existing,
|
|
197
|
+
cursor: options.dryRun ? cursor?.lastId ?? 0 : readCursor(cursorPath)?.lastId ?? 0 };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (import.meta.main) {
|
|
201
|
+
try {
|
|
202
|
+
const result = runBridge(process.argv.slice(2));
|
|
203
|
+
console.log(process.argv.includes('--json') ? JSON.stringify(result)
|
|
204
|
+
: `${result.seat}: read ${result.read}, picked ${result.picked}, added ${result.added}, existing ${result.existing}, cursor ${result.cursor}`);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
207
|
+
process.exitCode = 1;
|
|
208
|
+
}
|
|
209
|
+
}
|
package/scripts/coord-post.sh
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
# coord-post.sh — 조율 채널 발신 «한 자리». 시각과 명시적 값을 본문에 안전하게 넣는다.
|
|
3
3
|
# 사용: scripts/coord-post.sh [--set KEY=VALUE]... <본문파일>
|
|
4
4
|
set -u
|
|
5
|
-
|
|
5
|
+
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) || { echo '⛔ 스크립트 위치를 못 읽었다' >&2; exit 3; }
|
|
6
|
+
REPO_ROOT=$(dirname -- "$SCRIPT_DIR")
|
|
7
|
+
CLI="$REPO_ROOT/bin/elanous.mjs"
|
|
8
|
+
CANON="$REPO_ROOT/docs/manual/MANUAL-multi-agent-coordination-channel-2026-07-28.md"
|
|
6
9
|
|
|
7
10
|
resolve_pr() {
|
|
8
11
|
[ -f "$CANON" ] || return 0
|
|
@@ -40,7 +43,7 @@ BODY="${1:-}"
|
|
|
40
43
|
grep -q '{{TS}}' "$BODY" || echo "⚠️ 본문에 {{TS}} 자리표시가 «없다» — 시각을 손으로 적지 않았는지 확인하라" >&2
|
|
41
44
|
|
|
42
45
|
# 트랙 신원은 «정본 한 곳»에서 읽는다 — scripts/coord-tracks.json. 못 읽으면 추측하지 않고 선다.
|
|
43
|
-
TRACKS_FILE="$
|
|
46
|
+
TRACKS_FILE="$SCRIPT_DIR/coord-tracks.json"
|
|
44
47
|
# 신원 = 2글자 id(OP·MK·TC·UX…) ⊕ 옛 한 글자 alias(S·T·O·F — 전환기엔 받되 경고). 목록은 정본에서만.
|
|
45
48
|
IDS=$(grep -o '"id": *"[A-Z][A-Z]*"' "$TRACKS_FILE" 2>/dev/null | sed 's/.*"\([A-Z]*\)"$/\1/' | tr '\n' ' ')
|
|
46
49
|
ALIASES=$(grep -o '"alias": *"[A-Z][A-Z]*"' "$TRACKS_FILE" 2>/dev/null | sed 's/.*"\([A-Z]*\)"$/\1/' | tr '\n' ' ')
|
|
@@ -192,7 +195,7 @@ if [ "${COORD_DRY_RUN:-}" = "1" ]; then
|
|
|
192
195
|
exit 0
|
|
193
196
|
fi
|
|
194
197
|
|
|
195
|
-
POST_OUTPUT=$(bun
|
|
198
|
+
POST_OUTPUT=$(bun "$CLI" gh pr comment "$PR" --body-file "$TMP" 2>&1)
|
|
196
199
|
RC=$?
|
|
197
200
|
printf '%s\n' "$POST_OUTPUT" | tail -2
|
|
198
201
|
VIA=""
|
|
@@ -204,11 +207,11 @@ if [ "$RC" -ne 0 ] && printf '%s' "$POST_OUTPUT" | grep -qiE 'rate limit|Somethi
|
|
|
204
207
|
FIRSTOUT=$(head -1 "$TMP")
|
|
205
208
|
# issues 코멘트 목록은 오래된 순이고 정렬 인자를 안 받는다 ⇒ 최근 10분만 since 로 자른다.
|
|
206
209
|
SINCE10=$(date -u -v-10M +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '-10 min' +%Y-%m-%dT%H:%M:%SZ)
|
|
207
|
-
if bun
|
|
210
|
+
if bun "$CLI" gh api "repos/{owner}/{repo}/issues/$PR/comments?since=$SINCE10&per_page=100" --jq '.[].body | split("\n")[0]' 2>/dev/null | grep -qxF -- "$FIRSTOUT"; then
|
|
208
211
|
echo "[coord-post] 같은 첫 줄이 이미 채널에 있다 — GraphQL 이 실제로는 올렸다(이중 발신 안 함)" >&2
|
|
209
212
|
exit 0
|
|
210
213
|
fi
|
|
211
|
-
POST_OUTPUT=$(bun
|
|
214
|
+
POST_OUTPUT=$(bun "$CLI" gh api -X POST "repos/{owner}/{repo}/issues/$PR/comments" -F "body=@$TMP" -q .html_url 2>&1)
|
|
212
215
|
RC=$?
|
|
213
216
|
printf '%s\n' "$POST_OUTPUT" | tail -2
|
|
214
217
|
VIA=" · REST 폴백"
|
|
@@ -224,13 +227,43 @@ POST_URL=$(printf '%s\n' "$POST_OUTPUT" | grep -oE 'https://github\.com/[^[:spac
|
|
|
224
227
|
# test universe (OP 10-04 18:00). An explicit ELANOUS_STATE_DIR is the caller's chosen universe and wins;
|
|
225
228
|
# otherwise prefer the installed CLI (resolves prod from any tree), else pin the source CLI to prod.
|
|
226
229
|
if [ -n "${ELANOUS_STATE_DIR:-}" ]; then
|
|
227
|
-
RECORD=(bun
|
|
230
|
+
RECORD=(bun "$CLI" coord event record)
|
|
231
|
+
MESSAGE=(bun "$CLI" msg post)
|
|
228
232
|
elif command -v eln >/dev/null 2>&1; then
|
|
229
233
|
RECORD=(eln coord event record)
|
|
234
|
+
MESSAGE=(eln msg post)
|
|
230
235
|
else
|
|
231
|
-
RECORD=(env ELANOUS_STATE_DIR="$HOME/.elanous" bun
|
|
236
|
+
RECORD=(env ELANOUS_STATE_DIR="$HOME/.elanous" bun "$CLI" --config-dir "$HOME/.elanous" coord event record)
|
|
237
|
+
MESSAGE=(env ELANOUS_STATE_DIR="$HOME/.elanous" bun "$CLI" --config-dir "$HOME/.elanous" msg post)
|
|
232
238
|
fi
|
|
233
239
|
if ! "${RECORD[@]}" --seat "$ID" --header "$(head -1 "$TMP")" --url "$POST_URL" >/dev/null 2>&1; then
|
|
234
240
|
echo '⚠️ 맥락 원장 기록 실패(발신은 됐다)' >&2
|
|
235
241
|
fi
|
|
242
|
+
# S1's channel reader and this sender must agree on recipients. Keep the complete sent body
|
|
243
|
+
# for msg, while the provenance key makes a later S1 scan (or a partial retry) idempotent.
|
|
244
|
+
COMMENT_ID=${POST_URL##*#issuecomment-}
|
|
245
|
+
if [ "$COMMENT_ID" = "$POST_URL" ] || ! [[ "$COMMENT_ID" =~ ^[0-9]+$ ]]; then
|
|
246
|
+
echo '⚠️ 채널 댓글 ID를 못 읽어 msg 반영을 건너뛴다(발신은 됐다 · S1 다리가 회수)' >&2
|
|
247
|
+
exit 0
|
|
248
|
+
fi
|
|
249
|
+
ROUTES=$(bun -e '
|
|
250
|
+
import { readFileSync } from "node:fs";
|
|
251
|
+
import { join } from "node:path";
|
|
252
|
+
import { pathToFileURL } from "node:url";
|
|
253
|
+
const { routeCoordComment } = await import(pathToFileURL(join(process.argv[3], "coord-msg-bridge.ts")).href);
|
|
254
|
+
const { canonicalSeatId } = await import(pathToFileURL(join(process.argv[3], "../src/msg/msg-store.ts")).href);
|
|
255
|
+
const route = routeCoordComment(readFileSync(process.argv[2], "utf8"));
|
|
256
|
+
if (!route || route.sender !== canonicalSeatId(process.argv[1])) process.exit(2);
|
|
257
|
+
console.log(route.recipients.join("\n"));
|
|
258
|
+
' "$ID" "$TMP" "$SCRIPT_DIR") || {
|
|
259
|
+
echo '⚠️ msg 수신자 해석 실패(발신은 됐다 · S1 다리가 회수)' >&2
|
|
260
|
+
exit 0
|
|
261
|
+
}
|
|
262
|
+
while IFS= read -r RECIPIENT; do
|
|
263
|
+
[ -n "$RECIPIENT" ] || continue
|
|
264
|
+
if ! "${MESSAGE[@]}" --from "$ID" --to "$RECIPIENT" --kind coord \
|
|
265
|
+
--origin-key "coord:$COMMENT_ID:$RECIPIENT" < "$TMP" >/dev/null; then
|
|
266
|
+
echo "⚠️ msg 원장 기록 실패: $RECIPIENT(발신은 됐다 · S1 다리가 회수)" >&2
|
|
267
|
+
fi
|
|
268
|
+
done <<< "$ROUTES"
|
|
236
269
|
exit 0
|
|
@@ -7,10 +7,17 @@ import { registerStandaloneLogSink } from '../src/domains/standalone-log-sink.js
|
|
|
7
7
|
import { effectiveInstanceRoot } from '../src/instance/resolve.js';
|
|
8
8
|
import trackData from './coord-tracks.json';
|
|
9
9
|
|
|
10
|
-
type
|
|
10
|
+
export type CoordChannelComment = { id: number; body: string; created_at: string; html_url: string };
|
|
11
11
|
type Options = { seat: string; channel: string; since?: string; dryRun: boolean; json: boolean };
|
|
12
12
|
const seatIds = new Set(trackData.tracks.map((track) => track.id));
|
|
13
13
|
|
|
14
|
+
/** Shared channel retrieval. Callers validate the complete result before changing a ledger. */
|
|
15
|
+
export function fetchCoordChannelComments(channel: string, since?: string): CoordChannelComment[] {
|
|
16
|
+
const endpoint = `repos/{owner}/{repo}/issues/${channel}/comments${since ? `?since=${encodeURIComponent(since)}` : ''}`;
|
|
17
|
+
const output = execFileSync('gh', ['api', endpoint, '--paginate', '--jq', '.[]'], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
18
|
+
return output.split('\n').filter(Boolean).map((line) => JSON.parse(line) as CoordChannelComment);
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
function options(args: string[]): Options {
|
|
15
22
|
let seat = '';
|
|
16
23
|
let channel = '23032';
|
|
@@ -98,15 +105,13 @@ async function run(args: string[]): Promise<void> {
|
|
|
98
105
|
seat = selected.seat;
|
|
99
106
|
const { channel, since, dryRun, json } = selected;
|
|
100
107
|
reason = 'gh';
|
|
101
|
-
const
|
|
102
|
-
const output = execFileSync('gh', ['api', endpoint, '--paginate', '--jq', '.[]'], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
103
|
-
const comments = output.split('\n').filter(Boolean).map((line) => JSON.parse(line) as unknown);
|
|
108
|
+
const comments = fetchCoordChannelComments(channel, since);
|
|
104
109
|
reason = 'ledger';
|
|
105
110
|
const path = join(effectiveInstanceRoot(), 'seat-requests', 'requests.jsonl');
|
|
106
111
|
const seen = existingSeatComments(path);
|
|
107
112
|
let picked = 0, added = 0, existing = 0;
|
|
108
113
|
for (const item of comments) {
|
|
109
|
-
const comment = item as Partial<
|
|
114
|
+
const comment = item as Partial<CoordChannelComment>;
|
|
110
115
|
if (typeof comment.id !== 'number' || !Number.isSafeInteger(comment.id) || typeof comment.body !== 'string'
|
|
111
116
|
|| typeof comment.created_at !== 'string' || typeof comment.html_url !== 'string') throw new Error('gh api 댓글 필드가 잘못됐다');
|
|
112
117
|
if (since && Date.parse(comment.created_at) < Date.parse(since)) continue;
|
|
@@ -28,7 +28,7 @@ function measure(run: () => Criterion): Criterion {
|
|
|
28
28
|
export function suggestExposeRubric(root: string, files?: readonly string[], help?: HelpRunner, rulesPath?: string): Suggestion[] {
|
|
29
29
|
const names = files ?? readdirSync(join(root, DOCS)).filter((name) => name.endsWith('.md')).map((name) => `${DOCS}/${name}`);
|
|
30
30
|
const paths = [...new Set(names.map((name) => relative(root, resolve(root, name)).split(sep).join('/')))];
|
|
31
|
-
if (paths.some((path) => !/^release\/public\/docs\/[^/]
|
|
31
|
+
if (paths.some((path) => !/^(?:release\/public\/docs\/[^/]+|docs\/marketing\/BLOG-[^/]+)\.md$/.test(path))) throw new Error('문서 경로는 release/public/docs/*.md 또는 docs/marketing/BLOG-*.md 이어야 합니다');
|
|
32
32
|
type HelpResult = ReturnType<HelpRunner> & { failure?: string };
|
|
33
33
|
let helpRuns = 0;
|
|
34
34
|
const rootHelp: (args: string[]) => HelpResult = help ?? ((args) => {
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Measures the changed-file gate against the whole program on recently merged PRs.
|
|
3
|
+
* The narrowed run is the gate's default root check (changed .ts ∪ direct importers), so `missed` / `same` judge that mode:
|
|
4
|
+
* the run pins TSC_GATE_ROOTS to a non-`full` value and disables the rollback switch
|
|
5
|
+
* even when the caller's shell requests a full run.
|
|
6
|
+
* `missed > 0` is reverted without a code change by running the gate with env `TSC_GATE_ROOTS=full`.
|
|
7
|
+
*/
|
|
1
8
|
import { spawn } from 'node:child_process';
|
|
2
9
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
10
|
import { tmpdir } from 'node:os';
|
|
@@ -223,7 +230,9 @@ async function measurePr(repo: string, pr: Pr, run: Runner, platform: NodeJS.Pla
|
|
|
223
230
|
const added = compareDiagnostics(current, baseline);
|
|
224
231
|
if (added.kind === 'unavailable') throw new Error(added.reason);
|
|
225
232
|
result.addedDiagnostics = added.added;
|
|
226
|
-
const gateRun = await timed(run, platform, 'bun', ['scripts/ci-typecheck-changed.ts', '--local'], worktree, {
|
|
233
|
+
const gateRun = await timed(run, platform, 'bun', ['scripts/ci-typecheck-changed.ts', '--local'], worktree, {
|
|
234
|
+
...process.env, TSC_BASE_REF: base, TSC_GATE_ROOTS: 'affected', ELANOUS_TSC_AFFECTED_ROOTS: '1',
|
|
235
|
+
});
|
|
227
236
|
result.narrowed = elapsed(gateRun, platform);
|
|
228
237
|
result.gateExitCode = gateRun.status;
|
|
229
238
|
const seen = gateDiagnostics(gateRun, worktree);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
4
4
|
import { debug } from '../../src/debug/log.js';
|
|
5
|
+
import { registerStandaloneLogSink } from '../../src/domains/standalone-log-sink.js';
|
|
5
6
|
import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
6
7
|
import { emitNodeResult, readGraphContext, type GraphContext } from './node-verdict.js';
|
|
7
8
|
import { regressWarning, validatedTuiRegress } from './tui-node-checks.js';
|
|
@@ -78,6 +79,11 @@ export function runAutoApprove(context: GraphContext = readGraphContext(), deps:
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
if (import.meta.main) {
|
|
82
|
+
// GATE-OBS2-1 — the release graph spawns this node as its own process, which inherits no daemon sink. Without this the
|
|
83
|
+
// `release-loop.approve / auto-decision` event (the one that says why a release was or was not published unattended)
|
|
84
|
+
// stayed in the file trail and `elanous logs` read 0 rows. Same pattern as gate-node.ts.
|
|
85
|
+
// Observability must never stop the release node from emitting its verdict — a failed sink registration is skipped.
|
|
86
|
+
try { await registerStandaloneLogSink('release-loop'); } catch { /* fail-soft: the decision still goes to stdout */ }
|
|
81
87
|
try {
|
|
82
88
|
const result = runAutoApprove();
|
|
83
89
|
emitNodeResult(result);
|