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
|
@@ -52,6 +52,8 @@ export interface GraphWizardResult {
|
|
|
52
52
|
recipes?: string;
|
|
53
53
|
/** 실행 가능성 증명: 그 recipes 로 `graph run --dry-run` 을 걸어 본 결과. 하니스만. */
|
|
54
54
|
dryRun?: { status: string; path: string[] };
|
|
55
|
+
/** 검증을 통과했지만 곁들인 경고(생성 실패 아님) — 예: «smell: linear-chain» 과 칸 내리기·유닛 끼우기 제안. */
|
|
56
|
+
warnings?: string[];
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export interface GraphWizardDeps {
|
|
@@ -303,6 +305,74 @@ export function validateWizardYaml(kind: GraphKind, yaml: string): string[] {
|
|
|
303
305
|
return issues;
|
|
304
306
|
}
|
|
305
307
|
|
|
308
|
+
/** 그래프 값어치 신호(RFC SW-GRAPH-SMELL · G1~G7) — 기계로 셀 수 있는 넷만 센다. */
|
|
309
|
+
export interface GraphSignals {
|
|
310
|
+
/** G1 검증 노드 = kind judge|gate 비종단 노드의 결과 map 이 둘 이상으로 갈림 · G2 되돌림 루프 = 뒤로 가는 간선(이미 지난 노드로) ⊕ 그 노드 max_visits ≥ 2 · G3 승인 지점 = kind hitl 노드 · G4 갈래 = 비종단 노드의 결과 map 이 종단 아닌 서로 다른 둘 이상으로 갈림 */
|
|
311
|
+
counted: { G1: number; G2: number; G3: number; G4: number };
|
|
312
|
+
/** 못 셈 표시 — G5(재개)·G6(병렬)·G7(해상도). 0 으로 지어내지 않는다. */
|
|
313
|
+
notCounted: readonly ['G5', 'G6', 'G7'];
|
|
314
|
+
/** counted 넷의 합 — 둘 이상이면 그래프 값어치가 있다. */
|
|
315
|
+
total: number;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const GRAPH_SIGNALS_NOT_COUNTED = ['G5', 'G6', 'G7'] as const;
|
|
319
|
+
|
|
320
|
+
/** 순수 함수 — YAML 텍스트만 받아 센다(LLM·파일·실행 0). 못 세는 신호는 0 으로 지어내지 않고 «못 셈»으로 둔다. */
|
|
321
|
+
export function graphSignals(yaml: string): GraphSignals {
|
|
322
|
+
const counted = { G1: 0, G2: 0, G3: 0, G4: 0 };
|
|
323
|
+
const none = (): GraphSignals => ({ counted, notCounted: GRAPH_SIGNALS_NOT_COUNTED, total: 0 });
|
|
324
|
+
let doc: {
|
|
325
|
+
entry_node?: unknown; terminal_nodes?: unknown;
|
|
326
|
+
nodes?: Array<{ node_id?: unknown; kind?: unknown; max_visits?: unknown }>;
|
|
327
|
+
edges?: Array<{ from?: unknown; to?: unknown; map?: unknown }>;
|
|
328
|
+
} | null;
|
|
329
|
+
try { doc = parseYaml(yaml) as typeof doc; } catch { return none(); }
|
|
330
|
+
if (!doc) return none();
|
|
331
|
+
const nodes = (Array.isArray(doc.nodes) ? doc.nodes : []).filter((n) => n != null && typeof n.node_id === 'string');
|
|
332
|
+
const ids = new Set(nodes.map((n) => n.node_id as string));
|
|
333
|
+
const kindOf = new Map(nodes.map((n) => [n.node_id as string, typeof n.kind === 'string' ? n.kind : '']));
|
|
334
|
+
const visitsOf = new Map(nodes.map((n) => [n.node_id as string, Number(n.max_visits) || 0]));
|
|
335
|
+
const terminals = new Set((Array.isArray(doc.terminal_nodes) ? doc.terminal_nodes : []).map((t) => String(t)));
|
|
336
|
+
const targetsOf = new Map<string, Set<string>>();
|
|
337
|
+
for (const edge of Array.isArray(doc.edges) ? doc.edges : []) {
|
|
338
|
+
if (edge == null || typeof edge.from !== 'string' || !ids.has(edge.from)) continue;
|
|
339
|
+
const tos = typeof edge.to === 'string' ? [edge.to]
|
|
340
|
+
: edge.map && typeof edge.map === 'object'
|
|
341
|
+
? Object.values(edge.map as Record<string, unknown>).filter((to): to is string => typeof to === 'string') : [];
|
|
342
|
+
const targets = targetsOf.get(edge.from) ?? new Set<string>();
|
|
343
|
+
for (const to of tos) if (ids.has(to)) targets.add(to);
|
|
344
|
+
if (targets.size > 0) targetsOf.set(edge.from, targets);
|
|
345
|
+
}
|
|
346
|
+
const entry = typeof doc.entry_node === 'string' && ids.has(doc.entry_node) ? doc.entry_node : undefined;
|
|
347
|
+
/** entry 에서 avoid 노드를 거치지 않고 닿는 노드들 = «이미 지난 노드»(avoid = 되돌림 간선의 출발 노드). entry 자신도 지난 노드로 센다. */
|
|
348
|
+
const passedBefore = (avoid?: string): ReadonlySet<string> => {
|
|
349
|
+
if (!entry) return new Set<string>();
|
|
350
|
+
const visited = new Set<string>([entry]);
|
|
351
|
+
const queue = [entry];
|
|
352
|
+
while (queue.length > 0) {
|
|
353
|
+
const current = queue.shift()!;
|
|
354
|
+
if (current === avoid) continue;
|
|
355
|
+
for (const to of targetsOf.get(current) ?? []) if (!visited.has(to)) { visited.add(to); queue.push(to); }
|
|
356
|
+
}
|
|
357
|
+
return visited;
|
|
358
|
+
};
|
|
359
|
+
for (const node of nodes) {
|
|
360
|
+
const id = node.node_id as string;
|
|
361
|
+
const targets = targetsOf.get(id) ?? new Set<string>();
|
|
362
|
+
if (kindOf.get(id) === 'hitl') counted.G3 += 1;
|
|
363
|
+
if (terminals.has(id)) continue;
|
|
364
|
+
if ((kindOf.get(id) === 'judge' || kindOf.get(id) === 'gate') && targets.size >= 2) counted.G1 += 1;
|
|
365
|
+
if ([...targets].filter((to) => !terminals.has(to)).length >= 2) counted.G4 += 1;
|
|
366
|
+
}
|
|
367
|
+
for (const [from, targets] of targetsOf) {
|
|
368
|
+
for (const to of targets) {
|
|
369
|
+
if (terminals.has(to) || (visitsOf.get(to) ?? 0) < 2) continue;
|
|
370
|
+
if (to === from ? passedBefore().has(from) : passedBefore(from).has(to)) counted.G2 += 1;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return { counted, notCounted: GRAPH_SIGNALS_NOT_COUNTED, total: counted.G1 + counted.G2 + counted.G3 + counted.G4 };
|
|
374
|
+
}
|
|
375
|
+
|
|
306
376
|
/** 노드 줄 끝 주석 `# 이름 | 단계 | 인자` 를 읽는다. 흐름식 노드 줄에서만. */
|
|
307
377
|
export function parseNodeAnnotations(yaml: string): Record<string, WizardNodeStep> {
|
|
308
378
|
const out: Record<string, WizardNodeStep> = {};
|
|
@@ -562,11 +632,17 @@ export async function generateGraphFromPrompt(req: GraphWizardRequest, deps: Gra
|
|
|
562
632
|
}
|
|
563
633
|
attempts = Math.min(attempts, maxAttempts);
|
|
564
634
|
const ok = issues.length === 0;
|
|
635
|
+
// «선형 사슬» 냄새(SW-GRAPH-SMELL) — 경고만, 생성 실패가 아니다. 값어치 신호가 둘 이하면 칸 내리기·유닛 끼우기를 제안한다.
|
|
636
|
+
const warnings: string[] = [];
|
|
637
|
+
if (kind === 'harness' && ok) {
|
|
638
|
+
const signals = graphSignals(yaml);
|
|
639
|
+
if (signals.total <= 1) warnings.push(`smell: linear-chain — G 신호 ${signals.total} · 칸 내리기(스킬 사슬) 또는 유닛 끼우기(unit-verify = G1·G2 · 승인 노드 = G3) 제안`);
|
|
640
|
+
}
|
|
565
641
|
const counted = summarizeChange(kind, editing ? req.currentYaml : undefined, yaml);
|
|
566
642
|
const summary = llmSummary ? `${llmSummary} (${counted})` : counted;
|
|
567
643
|
debug.log('graph.wizard', ok ? 'validated' : 'failed', { id, kind, base, attempts, editing, issues: issues.slice(0, 10), summary, dryRun: dryRun?.status, ms: Date.now() - startedAt });
|
|
568
644
|
const labels = Object.fromEntries(Object.entries(steps).filter(([, v]) => v.label).map(([k, v]) => [k, v.label!]));
|
|
569
|
-
return { ok, id, yaml, ...(base ? { base } : {}), ...(base && baseReason ? { baseReason } : {}), issues, attempts, summary, labels, steps, ...(recipes ? { recipes } : {}), ...(dryRun ? { dryRun } : {}) };
|
|
645
|
+
return { ok, id, yaml, ...(base ? { base } : {}), ...(base && baseReason ? { baseReason } : {}), issues, attempts, summary, labels, steps, ...(recipes ? { recipes } : {}), ...(dryRun ? { dryRun } : {}), ...(warnings.length ? { warnings } : {}) };
|
|
570
646
|
}
|
|
571
647
|
|
|
572
648
|
/** v1 이름 유지 — 생성 YAML 의 노드 주석(단계·인자)으로 실제 recipes.yaml 을 낸다(v1 의 «미구현» 자리표시를 대체). */
|
package/src/grok.ts
CHANGED
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
import type { GrokAnalysis, DiffResult, EnvDelta } from './types.js';
|
|
15
15
|
import * as ui from './ui.js';
|
|
16
16
|
import { getUserConfig } from './user-config.js';
|
|
17
|
-
import { getProviderForConfig, anyProviderAvailable,
|
|
17
|
+
import { getProviderForConfig, anyProviderAvailable, logAgentTurnUsage, type LLMMessage } from './llm.js';
|
|
18
|
+
import type { LLMUsage } from './prompt-cache/types.js';
|
|
18
19
|
|
|
19
20
|
/** True when any provider (env OR user-config, including Codex OAuth)
|
|
20
21
|
* can answer. Thin wrapper around llm.anyProviderAvailable() kept
|
|
@@ -34,19 +35,24 @@ async function callAnalyzer(prompt: string, systemPrompt?: string): Promise<stri
|
|
|
34
35
|
if (systemPrompt) messages.push({ role: 'system', content: systemPrompt });
|
|
35
36
|
messages.push({ role: 'user', content: prompt });
|
|
36
37
|
|
|
37
|
-
const
|
|
38
|
-
? provider.streamChat(messages, { temperature: 0.1, maxTokens: 1024 })
|
|
39
|
-
: null;
|
|
38
|
+
const llmOpts = { temperature: 0.1, maxTokens: 1024 };
|
|
40
39
|
let text = '';
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
let usage: LLMUsage = {};
|
|
41
|
+
if (provider.streamChat) {
|
|
42
|
+
for await (const ev of provider.streamChat(messages, llmOpts)) {
|
|
43
|
+
if (ev.type === 'text' && ev.delta) text += ev.delta;
|
|
44
|
+
else if (ev.type === 'usage') usage = { ...usage, ...ev.usage };
|
|
45
|
+
}
|
|
43
46
|
} else {
|
|
44
47
|
// Fallback to text-only chat (shouldn't happen — every provider
|
|
45
48
|
// ships streamChat now).
|
|
46
|
-
for await (const chunk of provider.chat(messages,
|
|
49
|
+
for await (const chunk of provider.chat(messages, llmOpts)) {
|
|
47
50
|
text += chunk;
|
|
48
51
|
}
|
|
49
52
|
}
|
|
53
|
+
try {
|
|
54
|
+
logAgentTurnUsage(provider.defaultModel, usage, { providerName: provider.name, site: 'grok.direct' });
|
|
55
|
+
} catch { /* best-effort observation */ }
|
|
50
56
|
return text;
|
|
51
57
|
}
|
|
52
58
|
|
|
@@ -19,11 +19,14 @@ import { Command, Option } from 'commander';
|
|
|
19
19
|
import { runGitCommand } from '../git-fs/runner.js';
|
|
20
20
|
import { GOAL_TYPES, lintGoalFile, parseGoalId, parseGoalType, resolveGoalAuthorGrade, tracedPathReferences, type GoalAuthorGrade, type GoalAuthorGradeSelection, type GoalType } from '../self-implement/goal-author.js';
|
|
21
21
|
import { templateForGoalType } from '../self-implement/graph-templates.js';
|
|
22
|
-
import { listRunLedgers, loadFederatedRunLedger, loadRunLedger, queryRunScreenKey, runLedgerDir, type RunLedgerMatch } from '../self-implement/run-ledger.js';
|
|
22
|
+
import { appendRunLedgerEntry, listRunLedgers, loadFederatedRunLedger, loadRunLedger, queryRunScreenKey, runLedgerDir, type RunLedgerEntry, type RunLedgerMatch, type RunLedgerWriter } from '../self-implement/run-ledger.js';
|
|
23
|
+
import { classifyPodExit, type PodExitClass } from '../task-orchestrator/surfaces/pod-failure-reason.js';
|
|
23
24
|
import { classifyPodExitStop, recordRunStop, runStopRecorded, RUN_STOP_EVENT } from '../self-implement/run-stop.js';
|
|
24
25
|
import { ensureOpenRouterChildModelLive, resolveChildLlmEffort, resolveImplementationChildModel } from '../self-dev/dev-cli.js';
|
|
25
26
|
import { resolveHarnessTarget } from '../self-implement/harness-target-options.js';
|
|
26
|
-
import { buildRunProgressRows, queryRunningRuns, renderRunProgressTable } from '../self-implement/running-runs.js';
|
|
27
|
+
import { buildRunProgressRows, isPartialRunningRuns, queryRunningRuns, renderRunProgressTable } from '../self-implement/running-runs.js';
|
|
28
|
+
import { launchBindingRunIds, readLaunchBinding } from './launch-registry.js';
|
|
29
|
+
import { psProcessStartMs } from './harness-stop.js';
|
|
27
30
|
import { DevPipelineError } from '../self-dev/dev-pipeline.js';
|
|
28
31
|
import { collectDraftMetrics, collectOverlapMetrics, DRAFT_SWEEP_CONCURRENCY, mapBounded, resolveDraftSweepCloseCap, runDraftSweep, sweepFailureReason, type DraftSweepAdapters, type DraftSweepResult, type OverlapMetricAdapters, type SweepDraft, type SweepMergedPr, type SweepReviewGate } from '../self-dev/draft-sweep.js';
|
|
29
32
|
import { readAskPreflightRowsSince, readSalvagedRowsSince } from '../self-dev/ask-launch-io.js';
|
|
@@ -34,11 +37,10 @@ import { debug } from '../debug/log.js';
|
|
|
34
37
|
import { installHarnessSalvageCommand, installHarnessSalvageRetentionCommand } from './harness-salvage-cli.js';
|
|
35
38
|
import { decideNestedElanousLaunch, readNestedElanousDepth } from './nested-elanous-policy.js';
|
|
36
39
|
import { dispatchTask, type DispatchTaskInput, type DispatchTaskDeps } from '../execution-loop/dispatch-task.js';
|
|
37
|
-
import { launchRequestId, preLaunchGate, type PreLaunchGateDeps } from '../execution-loop/launch-gate.js';
|
|
40
|
+
import { harnessLaunchBudgetDecision, launchRequestId, preLaunchGate, resolveLaunchBudget, type PreLaunchGateDeps } from '../execution-loop/launch-gate.js';
|
|
38
41
|
import { PR_LABELS } from '../github/pr-labels.js';
|
|
39
42
|
import { ghAutomationEnv } from '../autopilot/pr-manager.js';
|
|
40
|
-
import {
|
|
41
|
-
import { DEFAULT_FALLBACK_CHAIN } from '../oauth/fallback-chain.js';
|
|
43
|
+
import { decideBudget, readBudgetInputsLive, type BudgetDecision, type BudgetInputs } from '../self-implement/budget-gate.js';
|
|
42
44
|
import { installDeliverableVerifyCliCommand, type InstallDeliverableVerifyCliDeps } from './deliverable-verify-cli.js';
|
|
43
45
|
import { getUserConfig } from '../user-config.js';
|
|
44
46
|
import type { SiblingResyncAdapters, SiblingResyncResult, SiblingRunTarget } from '../self-implement/sibling-resync.js';
|
|
@@ -701,7 +703,7 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
701
703
|
const classified = classifyHarnessPodExit({ status }, output, { ...(runId ? { runId } : {}) });
|
|
702
704
|
recordClassifiedHarnessPodExit(runId ?? harnessPodRunId(output), classified.reason, status,
|
|
703
705
|
{ entrance, seat: o.seat, output });
|
|
704
|
-
recordHarnessPodStop(runId ?? harnessPodRunId(output), status, classified);
|
|
706
|
+
recordHarnessPodStop(runId ?? harnessPodRunId(output), status, classified, output);
|
|
705
707
|
for (const line of classified.lines) console.error(line);
|
|
706
708
|
process.exitCode = status;
|
|
707
709
|
}
|
|
@@ -716,25 +718,62 @@ export function recordHarnessPodStop(
|
|
|
716
718
|
runId: string | undefined,
|
|
717
719
|
status: number,
|
|
718
720
|
classified: { reason: string; lines: string[] },
|
|
719
|
-
|
|
721
|
+
output?: string,
|
|
722
|
+
deps: { loadLedger?: typeof loadRunLedger; record?: typeof recordRunStop; write?: RunLedgerWriter } = {},
|
|
720
723
|
): boolean {
|
|
721
724
|
if (!runId) return false;
|
|
722
725
|
try {
|
|
723
726
|
if (runStopRecorded(runId)) return false;
|
|
724
727
|
if ((deps.loadLedger ?? loadRunLedger)(runId)?.some((entry) => entry.event === RUN_STOP_EVENT)) return false;
|
|
728
|
+
const nextMove = classified.reason === 'no-launch' ? 'Check Pod launch gate and pool, then relaunch'
|
|
729
|
+
: 'Inspect Pod exit classification and harvest the branch before relaunch';
|
|
730
|
+
const evidenceRef = `logs:harness.pod/exit-classified:${runId}`;
|
|
731
|
+
// AUT-POD-EXIT-UNCLASSIFIED ⓑ — only an unclassified exit reads the child output; classified reasons stay byte-identical.
|
|
732
|
+
const detail = classified.reason === 'unknown' ? podExitDetail(runId, status, output) : undefined;
|
|
733
|
+
if (detail) {
|
|
734
|
+
const write = deps.write ?? ((entry: RunLedgerEntry) => appendRunLedgerEntry(entry));
|
|
735
|
+
(deps.record ?? recordRunStop)({
|
|
736
|
+
runId, site: 'pod-exit', class: classifyPodExitStop(classified.reason),
|
|
737
|
+
cause: `Pod exit ${status}: ${detail.podExitClass}${detail.lead ? ` — ${detail.lead}` : ''}`,
|
|
738
|
+
evidenceRef, nextMove,
|
|
739
|
+
}, (entry) => write({ ...entry, data: { ...entry.data, podExitClass: detail.podExitClass, tail: detail.tail } }));
|
|
740
|
+
return true;
|
|
741
|
+
}
|
|
725
742
|
// The classified line is our own one-line verdict («Pod 안 자식이 실패했다 — OOMKilled»), not the raw output tail.
|
|
726
743
|
const verdict = classified.lines[0]?.split(' — ').slice(1).join(' — ').trim();
|
|
727
744
|
(deps.record ?? recordRunStop)({
|
|
728
745
|
runId, site: 'pod-exit', class: classifyPodExitStop(classified.reason),
|
|
729
746
|
cause: `Pod exit ${status}: ${classified.reason}${verdict ? ` — ${verdict}` : ''}`,
|
|
730
|
-
evidenceRef
|
|
731
|
-
|
|
732
|
-
: 'Inspect Pod exit classification and harvest the branch before relaunch',
|
|
733
|
-
});
|
|
747
|
+
evidenceRef, nextMove,
|
|
748
|
+
}, ...(deps.write ? [deps.write] : []));
|
|
734
749
|
return true;
|
|
735
750
|
} catch { return false; /* ledger observation cannot change Pod output or exit */ }
|
|
736
751
|
}
|
|
737
752
|
|
|
753
|
+
const POD_EXIT_TAIL_LINES = 5;
|
|
754
|
+
const POD_EXIT_TAIL_LINE_CHARS = 240;
|
|
755
|
+
const POD_EXIT_CAUSE_LEAD_CHARS = 160;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* The closed Pod exit class ⊕ the last meaningful output lines for an exit the host could not classify.
|
|
759
|
+
* Empty output is no evidence at all — `unknown` with an empty tail, never a guess. Fail-soft: a throw reads as `unknown`.
|
|
760
|
+
*/
|
|
761
|
+
function podExitDetail(runId: string, status: number, output: string | undefined): { podExitClass: PodExitClass; tail: string[]; lead: string } {
|
|
762
|
+
let podExitClass: PodExitClass = 'unknown';
|
|
763
|
+
let tail: string[] = [];
|
|
764
|
+
if (output?.trim()) {
|
|
765
|
+
try {
|
|
766
|
+
const exit = classifyPodExit({ logs: output, containerExitCode: status });
|
|
767
|
+
podExitClass = exit.class;
|
|
768
|
+
tail = exit.tail.slice(-POD_EXIT_TAIL_LINES).map((line) => Array.from(line).slice(0, POD_EXIT_TAIL_LINE_CHARS).join(''));
|
|
769
|
+
} catch { podExitClass = 'unknown'; tail = []; }
|
|
770
|
+
}
|
|
771
|
+
// The last meaningful line is where the child died (`Error: ENOSPC …`) — earlier tail lines are context.
|
|
772
|
+
const lead = Array.from(tail.at(-1) ?? '').slice(0, POD_EXIT_CAUSE_LEAD_CHARS).join('');
|
|
773
|
+
try { debug.log('harness.pod', 'exit-classified-detail', { runId, podExitClass, tailLines: tail.length }); } catch { /* observation is fail-soft */ }
|
|
774
|
+
return { podExitClass, tail, lead };
|
|
775
|
+
}
|
|
776
|
+
|
|
738
777
|
/**
|
|
739
778
|
* POD-ANTHROPIC-PROVIDER ⓓ — 발사 관문과 Pod 가 «한 목록»(`POD_CHILD_PROVIDERS`)을 본다.
|
|
740
779
|
* 🩸 10-10: 관문은 anthropic 을 «예산 판정 밖» 으로 통과시켰고 Pod 단계가 rc=2 로 죽었다(관문·Pod 목록 엇갈림).
|
|
@@ -754,39 +793,7 @@ function refusePodChildProviderBeforeLaunch(resolved: ResolvedHarnessSubstrate,
|
|
|
754
793
|
return true;
|
|
755
794
|
}
|
|
756
795
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
/**
|
|
760
|
-
* L6 발사 관문의 예산 입력 보정 — 발사 우주의 config 에 체인이 없으면(작업 트리 = 시험 우주) 막지 않고
|
|
761
|
-
* 코드 기본 체인으로 판단한다. `--child-llm-provider` 를 명시했으면 그것이 체인이다(예산 판정 밖 provider 는 통과).
|
|
762
|
-
*/
|
|
763
|
-
export function harnessLaunchBudgetDecision(
|
|
764
|
-
inputs: BudgetInputs,
|
|
765
|
-
opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
|
|
766
|
-
): { readonly decision: BudgetDecision; readonly warning?: string; readonly unmeasuredProvider?: string } {
|
|
767
|
-
const explicit = opts.childLlmProvider?.trim();
|
|
768
|
-
const judged = (selected: BudgetInputs) => {
|
|
769
|
-
const { decision, unmeasuredProvider } = decideLaunchBudget(selected);
|
|
770
|
-
return { decision, ...(unmeasuredProvider ? { unmeasuredProvider, warning: `budget: ${unmeasuredProvider} usage unmeasured — launching` } : {}) };
|
|
771
|
-
};
|
|
772
|
-
if (explicit) {
|
|
773
|
-
if (explicit !== CODEX_PROVIDER && explicit !== GROK_PROVIDER) {
|
|
774
|
-
return {
|
|
775
|
-
decision: { action: 'proceed', provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}), reasons: [`${explicit}: 명시 provider — 예산 판정 밖`] },
|
|
776
|
-
warning: `budget: ${explicit} is outside the budget gate — launched as requested`,
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
const chain = [{ provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}) }];
|
|
780
|
-
return judged({ ...inputs, preference: { ...inputs.preference, chain } });
|
|
781
|
-
}
|
|
782
|
-
if (inputs.preference.chain.length > 0) return judged(inputs);
|
|
783
|
-
const chain = DEFAULT_FALLBACK_CHAIN.map((step) => ({ provider: LAUNCH_BUDGET_PROVIDER[step] ?? step }));
|
|
784
|
-
const result = judged({ ...inputs, preference: { ...inputs.preference, chain } });
|
|
785
|
-
return {
|
|
786
|
-
...result,
|
|
787
|
-
warning: `budget: no chain in this universe's config — judged with the code default ${DEFAULT_FALLBACK_CHAIN.join(',')}${result.warning ? ` · ${result.warning}` : ''}`,
|
|
788
|
-
};
|
|
789
|
-
}
|
|
796
|
+
export { harnessLaunchBudgetDecision } from '../execution-loop/launch-gate.js';
|
|
790
797
|
|
|
791
798
|
async function readHarnessLaunchBudget(
|
|
792
799
|
opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
|
|
@@ -1036,8 +1043,12 @@ async function dispatchHarnessAskSay(
|
|
|
1036
1043
|
}
|
|
1037
1044
|
enterJourneyNode('launch-gate', journey);
|
|
1038
1045
|
const decision = await withJourneyNode('launch-gate', journey, async () => {
|
|
1039
|
-
const budget
|
|
1040
|
-
|
|
1046
|
+
const { budget, budgetSource, snapshotAgeSec } = await resolveLaunchBudget({
|
|
1047
|
+
provider: opts.childLlmProvider,
|
|
1048
|
+
measureLocal: gate.readBudget ?? (() => readHarnessLaunchBudget(opts)),
|
|
1049
|
+
env: gate.readBudget ? { ELANOUS_SUBSTRATE: 'local' } : process.env, // an injected budget reader is a host measurement, whatever substrate runs the test
|
|
1050
|
+
});
|
|
1051
|
+
return preLaunchGate({ goalId, budget, budgetSource, ...(snapshotAgeSec !== undefined ? { snapshotAgeSec } : {}), forceLaunch: opts.forceGate === true }, gate);
|
|
1041
1052
|
});
|
|
1042
1053
|
exitJourneyNode('launch-gate', { ...journey, outcome: decision.action === 'proceed' ? 'pass' : 'refuse', data: { action: decision.action } });
|
|
1043
1054
|
if (decision.action !== 'proceed') {
|
|
@@ -2382,6 +2393,7 @@ const defaultDraftSweepStopRun: DraftSweepStopRun = async (runId) => {
|
|
|
2382
2393
|
export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: DraftSweepGitExecute = runGitCommand, cwd = process.cwd(),
|
|
2383
2394
|
executeAsync: (args: string[]) => Promise<string> = execute === executeGh ? executeGhAsync : async (args) => execute(args),
|
|
2384
2395
|
stopRun: DraftSweepStopRun = defaultDraftSweepStopRun): GithubDraftSweepAdapters {
|
|
2396
|
+
const ensuredSweepLabels = new Set<string>();
|
|
2385
2397
|
const inventory = async (repository: string, state: 'open' | 'closed'): Promise<GithubPull[]> => {
|
|
2386
2398
|
// ⛔ A large repository has tens of thousands of closed PRs (2026-09-28: 21k → «exceeded pagination limit», no sweep at all).
|
|
2387
2399
|
// Merged twins only matter after the oldest open draft was opened, so the closed listing stops at that time.
|
|
@@ -2633,11 +2645,19 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
|
|
|
2633
2645
|
.map((line) => line.slice('branch refs/heads/'.length).trim()));
|
|
2634
2646
|
},
|
|
2635
2647
|
setLabels: async (repository, number, change) => {
|
|
2648
|
+
if (change.add.startsWith('elanous:swept:')) {
|
|
2649
|
+
const key = `${repository}:${change.add}`;
|
|
2650
|
+
if (!ensuredSweepLabels.has(key)) {
|
|
2651
|
+
execute(['label', 'create', change.add, '--repo', repository, '--color', '6A737D',
|
|
2652
|
+
'--description', 'Draft sweep close reason; reopen this PR to restore it', '--force']);
|
|
2653
|
+
ensuredSweepLabels.add(key);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2636
2656
|
execute(['pr', 'edit', String(number), '--repo', repository, '--add-label', change.add,
|
|
2637
2657
|
...change.remove.flatMap((name) => ['--remove-label', name])]);
|
|
2638
2658
|
},
|
|
2639
|
-
closeDraft: async (repository, number
|
|
2640
|
-
execute(['pr', 'close', String(number), '--repo', repository
|
|
2659
|
+
closeDraft: async (repository, number) => {
|
|
2660
|
+
execute(['pr', 'close', String(number), '--repo', repository]);
|
|
2641
2661
|
},
|
|
2642
2662
|
getClaimOwner: async (repository, number) => claimCommentOwner(repository, number, execute),
|
|
2643
2663
|
getActiveClaimOwner: async (repository, number) => activeClaimOwnerFromBodies(await claimCommentsFor(repository, number)),
|
|
@@ -3128,7 +3148,13 @@ export interface HarnessCliCommandDeps {
|
|
|
3128
3148
|
mission?: HarnessMissionHandler;
|
|
3129
3149
|
missionLoop?: HarnessMissionLoopHandler;
|
|
3130
3150
|
/** `harness progress` 가 도는 런 관측을 읽는 자리(시험 주입). 기본은 queryRunningRuns. */
|
|
3131
|
-
progress?: {
|
|
3151
|
+
progress?: {
|
|
3152
|
+
query?: typeof queryRunningRuns;
|
|
3153
|
+
nowMs?: () => number;
|
|
3154
|
+
bindingRunIds?: typeof launchBindingRunIds;
|
|
3155
|
+
readBinding?: typeof readLaunchBinding;
|
|
3156
|
+
processStartMs?: typeof psProcessStartMs;
|
|
3157
|
+
};
|
|
3132
3158
|
}
|
|
3133
3159
|
|
|
3134
3160
|
export function installHarnessCliCommand(program: Command, deps: HarnessCliCommandDeps): Command {
|
|
@@ -3189,13 +3215,38 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
3189
3215
|
});
|
|
3190
3216
|
harnessCmd.command('progress').description('도는 골마다 진도를 한 표로 읽는다 — 단계 · 진입 시각 · 마지막 진전 · pty (읽기 전용)')
|
|
3191
3217
|
.option('--json', '같은 행 배열을 JSON 으로 출력')
|
|
3192
|
-
.
|
|
3218
|
+
.option('--pid <number>', '기록된 로컬 PID 에 연결된 런 한 건만 조회')
|
|
3219
|
+
.action((opts: { json?: boolean; pid?: string }) => {
|
|
3193
3220
|
try {
|
|
3221
|
+
if (opts.pid !== undefined) {
|
|
3222
|
+
const pid = Number(opts.pid);
|
|
3223
|
+
if (!Number.isSafeInteger(pid) || pid <= 1) {
|
|
3224
|
+
console.error('❌ --pid 는 2 이상의 정수여야 합니다');
|
|
3225
|
+
process.exitCode = 2;
|
|
3226
|
+
return;
|
|
3227
|
+
}
|
|
3228
|
+
const bindings = (deps.progress?.bindingRunIds ?? launchBindingRunIds)()
|
|
3229
|
+
.map((runId) => ({ runId, binding: (deps.progress?.readBinding ?? readLaunchBinding)(runId) }))
|
|
3230
|
+
.filter(({ binding }) => binding?.pid === pid);
|
|
3231
|
+
const binding = bindings.length === 1 && !bindings[0]!.binding?.podName ? bindings[0] : undefined;
|
|
3232
|
+
const startedAt = binding ? (deps.progress?.processStartMs ?? psProcessStartMs)(pid) : null;
|
|
3233
|
+
// ps lstart has second precision. A wider stop-oriented tolerance would attribute a reused PID to this run.
|
|
3234
|
+
const observed = binding && startedAt !== null
|
|
3235
|
+
&& startedAt === Math.floor(binding.binding!.startedAt / 1_000) * 1_000;
|
|
3236
|
+
const result = observed
|
|
3237
|
+
? (deps.progress?.query ?? queryRunningRuns)({ runIds: [binding.runId], caller: 'harness.progress.pid' })
|
|
3238
|
+
: null;
|
|
3239
|
+
const row = result ? buildRunProgressRows(result, (deps.progress?.nowMs ?? Date.now)())
|
|
3240
|
+
.find((item) => item.runId === binding!.runId && item.status !== 'ended-unclosed' && item.status !== 'unknown') : undefined;
|
|
3241
|
+
if (opts.json) console.log(JSON.stringify({ pid, observation: row ? 'observed' : 'unobserved', runId: row?.runId ?? null, progress: row ?? null }));
|
|
3242
|
+
else console.log(row ? `pid ${pid} · ${renderRunProgressTable({ ...result!, entries: result!.entries.filter((item) => item.runId === row.runId) }, (deps.progress?.nowMs ?? Date.now)()).split('\n').slice(1).join('\n')}` : `pid ${pid} · 미관측`);
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3194
3245
|
const result = (deps.progress?.query ?? queryRunningRuns)({ caller: 'harness.progress' });
|
|
3195
3246
|
const nowMs = (deps.progress?.nowMs ?? Date.now)();
|
|
3196
3247
|
if (opts.json) {
|
|
3197
3248
|
console.log(JSON.stringify(buildRunProgressRows(result, nowMs)));
|
|
3198
|
-
if (result
|
|
3249
|
+
if (isPartialRunningRuns(result)) console.error(renderRunProgressTable(result, nowMs).split('\n')[0]);
|
|
3199
3250
|
} else console.log(renderRunProgressTable(result, nowMs));
|
|
3200
3251
|
} catch (error) {
|
|
3201
3252
|
console.error(humanErrorLine(error));
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
// 🩸 2026-09-27: 멈추려면 사람이 PID 둘(harness ask 부모 · self orchestrate 자식)과 Job 이름을 손으로 찾아야 했고,
|
|
4
4
|
// 그 사이 떠 있던 조각이 main 에 병합됐다(#21048). 부모를 죽이면 자식이 PPID 1 고아로 2h36m 더 돌았다(🅞 보고).
|
|
5
5
|
// B 조각(#21171)이 오케스트레이터에 `self-dev-runs/<runId>/pid.json` ⊕ SIGTERM 정리(새 잡 멈춤 · 자기 Job 삭제 · cancelled)를 넣었다.
|
|
6
|
-
// 이 파일은 그 기록과 런 원장·프로세스 표를 읽고, 시작 시각이 확인된 후보에만 신호를 보내며,
|
|
6
|
+
// 이 파일은 그 기록과 런 원장·프로세스 표를 읽고, 시작 시각이 확인된 후보에만 신호를 보내며, 라벨 일치 Pod Job 을 지운다.
|
|
7
7
|
//
|
|
8
8
|
// ⛔ 불변식: 기록된 시작 시각과 실제 프로세스 시작 시각이 다르면 신호를 보내지 않는다(PID 재사용 방지).
|
|
9
|
-
// ⛔ 불변식: `elanous.run=<runId>` 라벨이
|
|
9
|
+
// ⛔ 불변식: 라벨이 붙은 Job 만 지운다 — `elanous.run=<runId>` · 그 라벨이 0 이면 `elanous.child-run=<runId>` 폴백(자식 런 id 로 쳤을 때).
|
|
10
|
+
// 지우는 것은 라벨 일치 Job 뿐이다: 이름 추측 없음 · Pod 직접 삭제 없음 · namespace 기본값(elanous-test) 불변.
|
|
11
|
+
// (HARNESS-STOP-POD-LABEL 2026-10-11) 문맥마다 삭제 결과를 넷으로 가르고 관측 `harness.stop` `job-delete`(context·outcome·matchedBy) 로 남긴다.
|
|
10
12
|
// ⛔ 불변식: 짧은 runId 의 후보가 둘 이상이면 프로세스 신호·Job 삭제 전에 중단한다.
|
|
11
13
|
|
|
12
14
|
import { existsSync, readdirSync, readFileSync, readlinkSync } from 'node:fs';
|
|
@@ -79,7 +81,7 @@ export function discoverStopProcesses(runId: string, goalPath: string | null, ta
|
|
|
79
81
|
const match = /^\s*(\d+)\s+((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\w+\s+\d+\s+\d\d:\d\d:\d\d\s+\d{4})\s+(.+)$/.exec(line);
|
|
80
82
|
if (!match) return { status: 'failed', reason: 'unparseable process table row' };
|
|
81
83
|
const pid = Number(match[1]);
|
|
82
|
-
const startedAt = Date.parse(match[2]!);
|
|
84
|
+
const startedAt = Date.parse(`${match[2]!} GMT`);
|
|
83
85
|
if (!Number.isSafeInteger(pid) || !Number.isFinite(startedAt)) return { status: 'failed', reason: 'invalid process table row' };
|
|
84
86
|
if (pid <= 1) continue;
|
|
85
87
|
const args = match[3]!.match(/"[^"]*"|'[^']*'|\S+/g)?.map((part) => part.replace(/^(['"])(.*)\1$/, '$2')) ?? [];
|
|
@@ -130,7 +132,9 @@ function stopProcessCwd(pid: number): string | null {
|
|
|
130
132
|
|
|
131
133
|
function scanStopProcessTable(runId: string, goalPath: string | null): StopProcessScan {
|
|
132
134
|
let r: ReturnType<typeof spawnSync>;
|
|
133
|
-
try { r = spawnSync('ps', ['-eo', 'pid=,lstart=,args='], {
|
|
135
|
+
try { r = spawnSync('ps', ['-eo', 'pid=,lstart=,args='], {
|
|
136
|
+
encoding: 'utf8', timeout: 5_000, maxBuffer: 16 * 1024 * 1024, env: { ...process.env, TZ: 'UTC' },
|
|
137
|
+
}); }
|
|
134
138
|
catch (error) { return { status: 'failed', reason: String(error) }; }
|
|
135
139
|
if (r.error || r.status !== 0 || typeof r.stdout !== 'string') return { status: 'failed', reason: String(r.error ?? r.stderr ?? `ps status ${r.status}`) };
|
|
136
140
|
return discoverStopProcesses(runId, goalPath, r.stdout, stopProcessCwd);
|
|
@@ -151,6 +155,19 @@ export interface HarnessStopDeps {
|
|
|
151
155
|
graceMs: number;
|
|
152
156
|
}
|
|
153
157
|
|
|
158
|
+
export type HarnessStopJobMatchedBy = 'elanous.run' | 'elanous.child-run';
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 문맥 하나의 Pod Job 삭제 결과(HARNESS-STOP-POD-LABEL) — «0개 지움» 의 종류를 가른다.
|
|
162
|
+
* deleted N — 라벨 일치 Job N 개 삭제 · none — 두 라벨 다 Job 0(진짜 없음 · Pod 생성 전 등)
|
|
163
|
+
* unreachable — kubectl 실패(그 0 을 진짜 0 으로 믿을 수 없다) · pods-only — Job 0 인데 같은 라벨 Pod 잔존
|
|
164
|
+
*/
|
|
165
|
+
export type HarnessStopJobDelete =
|
|
166
|
+
| { context: string; outcome: 'deleted'; matchedBy: HarnessStopJobMatchedBy; deleted: number }
|
|
167
|
+
| { context: string; outcome: 'none'; matchedBy: null; deleted: 0 }
|
|
168
|
+
| { context: string; outcome: 'unreachable'; matchedBy: null; deleted: 0; error: string }
|
|
169
|
+
| { context: string; outcome: 'pods-only'; matchedBy: null; deleted: 0; podsRemaining: number };
|
|
170
|
+
|
|
154
171
|
export interface HarnessStopResult {
|
|
155
172
|
runId: string;
|
|
156
173
|
givenRunId?: string;
|
|
@@ -161,6 +178,8 @@ export interface HarnessStopResult {
|
|
|
161
178
|
pidRecordFound: boolean;
|
|
162
179
|
dryRun: boolean;
|
|
163
180
|
jobsDeleted: number;
|
|
181
|
+
/** 문맥별 Job 삭제 분류 — 출력 한 줄과 `--json` 의 근원. */
|
|
182
|
+
jobDeletes: HarnessStopJobDelete[];
|
|
164
183
|
contexts: string[];
|
|
165
184
|
}
|
|
166
185
|
|
|
@@ -184,13 +203,15 @@ export function pidRecordFromLaunchBinding(runId: string, registryDir = launchRe
|
|
|
184
203
|
return { pid: binding.pid, startedAt: binding.startedAt, ...(binding.argv0 ? { argv0: binding.argv0 } : {}) };
|
|
185
204
|
}
|
|
186
205
|
|
|
187
|
-
/** macOS·Linux 공통 —
|
|
206
|
+
/** macOS·Linux 공통 — UTC 시작 시각과 상태를 같은 ps 관측에서 읽는다. */
|
|
188
207
|
export function psProcessStartMs(pid: number): number | null {
|
|
189
|
-
const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], {
|
|
208
|
+
const r = spawnSync('ps', ['-o', 'lstart=,stat=', '-p', String(pid)], {
|
|
209
|
+
encoding: 'utf8', timeout: 5_000, env: { ...process.env, TZ: 'UTC' },
|
|
210
|
+
});
|
|
190
211
|
if (r.status !== 0) return null;
|
|
191
|
-
const
|
|
192
|
-
if (!
|
|
193
|
-
const ms = Date.parse(
|
|
212
|
+
const match = /^\s*((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\w+\s+\d+\s+\d\d:\d\d:\d\d\s+\d{4})\s+(\S+)\s*$/.exec(r.stdout);
|
|
213
|
+
if (!match || match[2]!.startsWith('Z')) return null;
|
|
214
|
+
const ms = Date.parse(`${match[1]!} GMT`);
|
|
194
215
|
return Number.isFinite(ms) ? ms : null;
|
|
195
216
|
}
|
|
196
217
|
|
|
@@ -231,6 +252,56 @@ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {},
|
|
|
231
252
|
};
|
|
232
253
|
}
|
|
233
254
|
|
|
255
|
+
/** Pod Job 라벨 — `elanous.run` = 부모(오케스트레이터) 런 id · `elanous.child-run` = 자식 런 id(self-implement-pod podRunLabels). */
|
|
256
|
+
const POD_JOB_LABELS = ['elanous.run', 'elanous.child-run'] as const;
|
|
257
|
+
|
|
258
|
+
/** `kubectl get -o name` 출력에서 `<prefix>` 로 시작하는 줄 수를 센다. */
|
|
259
|
+
function countOutputLines(stdout: string, prefix: string): number {
|
|
260
|
+
return stdout.split('\n').filter((line) => line.startsWith(prefix)).length;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* `kubectl delete job -o name` 출력에서 삭제된 Job 줄 수를 센다.
|
|
265
|
+
* `-o name` 출력은 `job.batch/<name>` 한 줄씩이지만, 일부 kubectl 버전·설정에서는
|
|
266
|
+
* `job.batch "<name>" deleted` 꼴도 나타난다(#26194). 두 꼴을 모두 센다.
|
|
267
|
+
*/
|
|
268
|
+
function countDeletedJobLines(stdout: string): number {
|
|
269
|
+
return stdout.split('\n').filter((line) => /^job\.batch(?:\/|\s+")/.test(line.trim())).length;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** 문맥 하나의 Pod Job 삭제 — 결과를 넷(deleted·none·unreachable·pods-only)으로 가르고 문맥마다 관측 `harness.stop` `job-delete` 를 남긴다. */
|
|
273
|
+
function deleteRunPodJobs(deps: HarnessStopDeps, runId: string, context: string): HarnessStopJobDelete {
|
|
274
|
+
const unreachable = (stderr: string): HarnessStopJobDelete => {
|
|
275
|
+
const error = stderr.slice(0, 200);
|
|
276
|
+
debug.log('harness.stop', 'job-delete', { runId, context, outcome: 'unreachable', matchedBy: null, error }, { level: 'warn' });
|
|
277
|
+
return { context, outcome: 'unreachable', matchedBy: null, deleted: 0, error };
|
|
278
|
+
};
|
|
279
|
+
// ① `elanous.run=<runId>` — 0 이면 `elanous.child-run=<runId>` 로 한 번 더 고른다(자식 런 id 로 쳤을 때). 지우는 것은 라벨 일치 Job 뿐이다.
|
|
280
|
+
for (const label of POD_JOB_LABELS) {
|
|
281
|
+
// `-o name` → «job.batch/<name>» 한 줄씩. 맨 출력은 «job.batch "<name>" deleted» 라 «job.batch/» 로만 세면
|
|
282
|
+
// 지워도 늘 0 이었다(10-11 · 여섯 번 «0개 지움» 뒤 Pod Terminating). 두 꼴을 다 센다(#26194).
|
|
283
|
+
const r = deps.kubectl(['--context', context, '-n', deps.namespace, 'delete', 'job', '-l', `${label}=${runId}`, '--wait=false', '-o', 'name']);
|
|
284
|
+
if (r.status !== 0) return unreachable(r.stderr);
|
|
285
|
+
const deleted = countDeletedJobLines(r.stdout);
|
|
286
|
+
if (deleted > 0) {
|
|
287
|
+
debug.log('harness.stop', 'job-delete', { runId, context, outcome: 'deleted', matchedBy: label, deleted });
|
|
288
|
+
return { context, outcome: 'deleted', matchedBy: label, deleted };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// ② 두 라벨 다 Job 0 — 같은 라벨 Pod(`get pods -l <라벨>=<runId>`)로 none 과 pods-only 를 가른다. Pod 는 직접 지우지 않는다.
|
|
292
|
+
for (const label of POD_JOB_LABELS) {
|
|
293
|
+
const p = deps.kubectl(['--context', context, '-n', deps.namespace, 'get', 'pods', '-l', `${label}=${runId}`, '-o', 'name']);
|
|
294
|
+
if (p.status !== 0) return unreachable(p.stderr);
|
|
295
|
+
const podsRemaining = countOutputLines(p.stdout, 'pod/');
|
|
296
|
+
if (podsRemaining > 0) {
|
|
297
|
+
debug.log('harness.stop', 'job-delete', { runId, context, outcome: 'pods-only', matchedBy: null, podsRemaining });
|
|
298
|
+
return { context, outcome: 'pods-only', matchedBy: null, deleted: 0, podsRemaining };
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
debug.log('harness.stop', 'job-delete', { runId, context, outcome: 'none', matchedBy: null });
|
|
302
|
+
return { context, outcome: 'none', matchedBy: null, deleted: 0 };
|
|
303
|
+
}
|
|
304
|
+
|
|
234
305
|
export async function stopHarnessRun(runId: string, deps: HarnessStopDeps, contexts?: readonly string[], dryRun = false): Promise<HarnessStopResult> {
|
|
235
306
|
if (!RUN_ID.test(runId)) throw new Error(`invalid run id: ${runId}`);
|
|
236
307
|
const given = runId;
|
|
@@ -297,15 +368,9 @@ export async function stopHarnessRun(runId: string, deps: HarnessStopDeps, conte
|
|
|
297
368
|
}
|
|
298
369
|
// ── ⓑ Pod Job (라벨로만) ───────────────────────────────────
|
|
299
370
|
const targets = dryRun ? [] : contexts && contexts.length > 0 ? [...contexts] : deps.kubeContexts();
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// 지워도 늘 0 이었다(10-11 · 여섯 번 «0개 지움» 뒤 Pod Terminating). 두 꼴을 다 센다.
|
|
304
|
-
const r = deps.kubectl(['--context', context, '-n', deps.namespace, 'delete', 'job', '-l', `elanous.run=${runId}`, '--wait=false', '-o', 'name']);
|
|
305
|
-
if (r.status === 0) jobsDeleted += r.stdout.split('\n').filter((line) => /^job\.batch(?:\/|\s+")/.test(line.trim())).length;
|
|
306
|
-
else debug.log('harness.stop', 'job-delete-failed', { runId, context, error: r.stderr.slice(0, 200) }, { level: 'warn' });
|
|
307
|
-
}
|
|
308
|
-
const result: HarnessStopResult = { runId, ...(given !== runId ? { givenRunId: given } : {}), process: processState, ...(record ? { pid: record.pid } : {}), candidates, scanned: scan.status === 'ok', pidRecordFound: record !== null, dryRun, jobsDeleted, contexts: targets };
|
|
371
|
+
const jobDeletes = targets.map((context) => deleteRunPodJobs(deps, runId, context));
|
|
372
|
+
const jobsDeleted = jobDeletes.reduce((sum, job) => sum + job.deleted, 0);
|
|
373
|
+
const result: HarnessStopResult = { runId, ...(given !== runId ? { givenRunId: given } : {}), process: processState, ...(record ? { pid: record.pid } : {}), candidates, scanned: scan.status === 'ok', pidRecordFound: record !== null, dryRun, jobsDeleted, jobDeletes, contexts: targets };
|
|
309
374
|
debug.log('harness.stop', 'stopped', { runId, process: processState, jobsDeleted, contexts: targets.length });
|
|
310
375
|
return result;
|
|
311
376
|
}
|
|
@@ -326,6 +391,15 @@ export function formatHarnessStop(r: HarnessStopResult): string {
|
|
|
326
391
|
...r.candidates.map(({ pid, startedAt, via }) => ` 후보: pid ${pid} · 시작 ${new Date(startedAt).toISOString()} · ${via}`),
|
|
327
392
|
r.dryRun
|
|
328
393
|
? ` Pod Job: dry-run(조회·삭제하지 않음 · 라벨 elanous.run=${r.runId})`
|
|
329
|
-
: ` Pod Job: ${r.jobsDeleted}개 지움 (문맥 ${r.contexts.length}개 · 라벨 elanous.run=${r.runId})`,
|
|
394
|
+
: ` Pod Job: ${r.jobsDeleted}개 지움 (문맥 ${r.contexts.length}개 · 라벨 elanous.run=${r.runId} · child-run 폴백)`,
|
|
395
|
+
...r.jobDeletes.map(formatHarnessStopJobDelete),
|
|
330
396
|
].join('\n');
|
|
331
397
|
}
|
|
398
|
+
|
|
399
|
+
/** 문맥 하나의 Pod Job 결과 줄 — none·unreachable·pods-only 는 서로 다른 문면으로 갈라 읽힌다. */
|
|
400
|
+
function formatHarnessStopJobDelete(job: HarnessStopJobDelete): string {
|
|
401
|
+
if (job.outcome === 'deleted') return ` ${job.context}: ${job.deleted}개 지움 (라벨 ${job.matchedBy})`;
|
|
402
|
+
if (job.outcome === 'pods-only') return ` ${job.context}: Job 0 · 같은 라벨 Pod ${job.podsRemaining} 남음 (Pod 는 직접 지우지 않는다)`;
|
|
403
|
+
if (job.outcome === 'unreachable') return ` ${job.context}: 못 닿음 (kubectl 실패: ${job.error})`;
|
|
404
|
+
return ` ${job.context}: 없음 (라벨 맞는 Job 0)`;
|
|
405
|
+
}
|