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
|
@@ -18,14 +18,24 @@ export function cliRootVisibleFor(name: string, role: Role, { showAll }: { showA
|
|
|
18
18
|
return grade === 'stable' || (role === 'contributor' && (grade === 'beta' || grade === 'tool'));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/**
|
|
22
|
-
export
|
|
21
|
+
/** Root --help first screen (SETUP-HELP-SLIM): the three stable onboarding commands. */
|
|
22
|
+
export const FIRST_SCREEN_COMMANDS: readonly string[] = ['start', 'setup', 'ask'];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Only help is filtered: Commander still dispatches explicitly typed commands.
|
|
26
|
+
* firstScreen narrows the visible set to FIRST_SCREEN_COMMANDS and showAll wins over it;
|
|
27
|
+
* the caller opts in per role — the wired default (deferred slice) enables it for the
|
|
28
|
+
* general role only, so owner/contributor keep today's list.
|
|
29
|
+
*/
|
|
30
|
+
export function filterCliRootHelp(commands: readonly Command[], role: Role, showAll: boolean, firstScreen: boolean = false): { shown: number; hidden: number } {
|
|
31
|
+
const firstScreenActive = firstScreen && !showAll;
|
|
23
32
|
let shown = 0;
|
|
24
33
|
let hidden = 0;
|
|
25
34
|
for (const command of commands) {
|
|
26
35
|
const grade = cliRootMaturity(command.name(), commands);
|
|
27
36
|
if (!grade) throw new Error(`cliRoot 에 등급 없는 명령: ${command.name()}`);
|
|
28
|
-
const visible = cliRootVisibleFor(command.name(), role, { showAll }, commands)
|
|
37
|
+
const visible = cliRootVisibleFor(command.name(), role, { showAll }, commands)
|
|
38
|
+
&& (!firstScreenActive || FIRST_SCREEN_COMMANDS.includes(command.name()));
|
|
29
39
|
(command as Command & { _hidden: boolean })._hidden = !visible;
|
|
30
40
|
if (visible) shown++;
|
|
31
41
|
else hidden++;
|
|
@@ -64,7 +64,7 @@ export const FEATURE_MATURITY = {
|
|
|
64
64
|
pod: 'beta', browser: 'beta', questions: 'beta', usage: 'stable', live: 'beta',
|
|
65
65
|
research: 'beta', release: 'beta', know: 'beta', freeze: 'beta', flow: 'beta', seat: 'beta', hq: 'beta', steward: 'beta', coord: 'beta', context: 'beta', 'model-watch': 'beta', doctor: 'stable',
|
|
66
66
|
control: 'beta', resources: 'beta', hooks: 'beta', setup: 'stable', start: 'stable',
|
|
67
|
-
grounding: 'beta', graph: 'beta', loop: 'stable', card: 'stable', 'launch-head': 'beta',
|
|
67
|
+
grounding: 'beta', graph: 'beta', loop: 'stable', resource: 'beta', card: 'stable', 'launch-head': 'beta',
|
|
68
68
|
a2a: 'beta', plugin: 'stable', make: 'beta', skills: 'beta', connect: 'beta', import: 'beta',
|
|
69
69
|
persona: 'beta', team: 'beta', 'team-set': 'beta', market: 'beta', directive: 'stable', connector: 'beta', storyboard: 'beta',
|
|
70
70
|
python: 'beta', 'self-update': 'stable', 'measure-fabric-arc-ab': 'beta', mcp: 'beta',
|
package/src/msg/msg-store.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite';
|
|
2
|
-
import { mkdirSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
5
5
|
|
|
@@ -20,7 +20,7 @@ export interface UnreadRecipient {
|
|
|
20
20
|
count: number;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const SEAT_ALIASES: Readonly<Record<string, string>> = {
|
|
23
|
+
export const SEAT_ALIASES: Readonly<Record<string, string>> = {
|
|
24
24
|
S: 'OP', OP: 'OP', COO: 'OP',
|
|
25
25
|
T: 'MK', MK: 'MK', CMO: 'MK',
|
|
26
26
|
O: 'TC', TC: 'TC', CTO: 'TC',
|
|
@@ -41,6 +41,7 @@ export function validateMessageEnvelope(input: unknown): MessageEnvelope {
|
|
|
41
41
|
const record = input as Record<string, unknown>;
|
|
42
42
|
const from = canonicalSeatId(record.from as string);
|
|
43
43
|
const to = canonicalSeatId(record.to as string);
|
|
44
|
+
if (from === 'ALL') throw new Error('ALL cannot send messages');
|
|
44
45
|
if (typeof record.body !== 'string' || !record.body.trim()) throw new Error('message body must be nonempty');
|
|
45
46
|
if (record.kind !== undefined && (typeof record.kind !== 'string' || !/^[a-z][a-z0-9_-]{0,63}$/.test(record.kind))) {
|
|
46
47
|
throw new Error('invalid message kind');
|
|
@@ -54,6 +55,13 @@ function validCursor(cursor: number): number {
|
|
|
54
55
|
return cursor;
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
function unreadCountOn(db: Database, to: string): number {
|
|
59
|
+
return (db.query(`SELECT COUNT(*) AS count FROM msg_messages m
|
|
60
|
+
WHERE m.id > COALESCE((SELECT last_id FROM msg_cursors WHERE recipient = ?), 0)
|
|
61
|
+
AND (m.recipient = ? OR (m.recipient = 'ALL' AND m.sender <> ?))`)
|
|
62
|
+
.get(to, to, to) as { count: number }).count;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
interface MessageRow {
|
|
58
66
|
id: number;
|
|
59
67
|
sender: string;
|
|
@@ -88,10 +96,37 @@ export class MsgStore {
|
|
|
88
96
|
CREATE TABLE IF NOT EXISTS msg_cursors (
|
|
89
97
|
recipient TEXT PRIMARY KEY,
|
|
90
98
|
last_id INTEGER NOT NULL DEFAULT 0 CHECK(last_id >= 0)
|
|
99
|
+
);
|
|
100
|
+
CREATE TABLE IF NOT EXISTS msg_provenance (
|
|
101
|
+
provenance_key TEXT PRIMARY KEY,
|
|
102
|
+
message_id INTEGER NOT NULL REFERENCES msg_messages(id)
|
|
91
103
|
);`);
|
|
92
104
|
}
|
|
93
105
|
|
|
94
106
|
append(input: MessageEnvelope): Message {
|
|
107
|
+
return this.insertMessage(input);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Append once for a provenance key such as coord:<commentId>:<recipient>. */
|
|
111
|
+
appendWithProvenance(input: MessageEnvelope, provenanceKey: string): Message {
|
|
112
|
+
if (typeof provenanceKey !== 'string' || !/^coord:[^:]+:[^:]+$/.test(provenanceKey)) {
|
|
113
|
+
throw new Error('invalid message provenance key');
|
|
114
|
+
}
|
|
115
|
+
const msg = validateMessageEnvelope(input);
|
|
116
|
+
if (provenanceKey.split(':')[2] !== msg.to) throw new Error('provenance recipient does not match message recipient');
|
|
117
|
+
return this.db.transaction(() => {
|
|
118
|
+
const existing = this.db.query(`SELECT m.id, m.sender, m.recipient, m.body, m.kind, m.created_at
|
|
119
|
+
FROM msg_provenance p JOIN msg_messages m ON m.id = p.message_id WHERE p.provenance_key = ?`)
|
|
120
|
+
.get(provenanceKey) as MessageRow | null;
|
|
121
|
+
if (existing) return fromRow(existing);
|
|
122
|
+
const message = this.insertMessage(msg);
|
|
123
|
+
this.db.query('INSERT INTO msg_provenance(provenance_key, message_id) VALUES (?, ?)')
|
|
124
|
+
.run(provenanceKey, message.id);
|
|
125
|
+
return message;
|
|
126
|
+
}).immediate();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private insertMessage(input: MessageEnvelope): Message {
|
|
95
130
|
const msg = validateMessageEnvelope(input);
|
|
96
131
|
const createdAt = new Date().toISOString();
|
|
97
132
|
const result = this.db.query(`INSERT INTO msg_messages(sender, recipient, body, kind, created_at)
|
|
@@ -104,10 +139,12 @@ export class MsgStore {
|
|
|
104
139
|
/** Messages strictly after the supplied cursor, ordered by durable insertion ID. */
|
|
105
140
|
listByRecipient(recipient: string, after: number = 0, limit: number = 100): Message[] {
|
|
106
141
|
const to = canonicalSeatId(recipient);
|
|
142
|
+
if (to === 'ALL') throw new Error('ALL is a topic, not a recipient');
|
|
107
143
|
validCursor(after);
|
|
108
144
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1000) throw new Error('limit must be between 1 and 1000');
|
|
109
145
|
return (this.db.query(`SELECT id, sender, recipient, body, kind, created_at FROM msg_messages
|
|
110
|
-
WHERE
|
|
146
|
+
WHERE id > ? AND (recipient = ? OR (recipient = 'ALL' AND sender <> ?))
|
|
147
|
+
ORDER BY id ASC LIMIT ?`).all(after, to, to, limit) as MessageRow[]).map(fromRow);
|
|
111
148
|
}
|
|
112
149
|
|
|
113
150
|
list(recipient: string, after: number = 0, limit: number = 100): Message[] {
|
|
@@ -116,12 +153,14 @@ export class MsgStore {
|
|
|
116
153
|
|
|
117
154
|
getCursor(recipient: string): number {
|
|
118
155
|
const to = canonicalSeatId(recipient);
|
|
156
|
+
if (to === 'ALL') throw new Error('ALL is a topic, not a recipient');
|
|
119
157
|
return (this.db.query('SELECT last_id FROM msg_cursors WHERE recipient = ?').get(to) as { last_id: number } | null)?.last_id ?? 0;
|
|
120
158
|
}
|
|
121
159
|
|
|
122
160
|
/** Atomically reject future IDs and keep concurrent or stale acknowledgements from rewinding. */
|
|
123
161
|
advanceCursor(recipient: string, cursor: number): number {
|
|
124
162
|
const to = canonicalSeatId(recipient);
|
|
163
|
+
if (to === 'ALL') throw new Error('ALL is a topic, not a recipient');
|
|
125
164
|
validCursor(cursor);
|
|
126
165
|
const result = this.db.query(`INSERT INTO msg_cursors(recipient, last_id)
|
|
127
166
|
SELECT ?, ? WHERE ? <= (SELECT COALESCE(MAX(id), 0) FROM msg_messages)
|
|
@@ -133,11 +172,24 @@ export class MsgStore {
|
|
|
133
172
|
|
|
134
173
|
ack(recipient: string, cursor: number): number { return this.advanceCursor(recipient, cursor); }
|
|
135
174
|
|
|
175
|
+
unreadCount(recipient: string): number {
|
|
176
|
+
const to = canonicalSeatId(recipient);
|
|
177
|
+
if (to === 'ALL') throw new Error('ALL is a topic, not a recipient');
|
|
178
|
+
return unreadCountOn(this.db, to);
|
|
179
|
+
}
|
|
180
|
+
|
|
136
181
|
unreadRecipients(): UnreadRecipient[] {
|
|
137
|
-
return this.db.query(`
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
182
|
+
return this.db.query(`WITH recipients(recipient) AS (
|
|
183
|
+
SELECT 'OP' UNION SELECT 'MK' UNION SELECT 'TC' UNION SELECT 'UX'
|
|
184
|
+
UNION SELECT recipient FROM msg_messages WHERE recipient <> 'ALL'
|
|
185
|
+
UNION SELECT recipient FROM msg_cursors WHERE recipient <> 'ALL'
|
|
186
|
+
)
|
|
187
|
+
SELECT r.recipient AS recipient, COUNT(m.id) AS count
|
|
188
|
+
FROM recipients r
|
|
189
|
+
LEFT JOIN msg_cursors c ON c.recipient = r.recipient
|
|
190
|
+
JOIN msg_messages m ON m.id > COALESCE(c.last_id, 0)
|
|
191
|
+
AND (m.recipient = r.recipient OR (m.recipient = 'ALL' AND m.sender <> r.recipient))
|
|
192
|
+
GROUP BY r.recipient ORDER BY r.recipient ASC`).all() as UnreadRecipient[];
|
|
141
193
|
}
|
|
142
194
|
|
|
143
195
|
unread(): UnreadRecipient[] { return this.unreadRecipients(); }
|
|
@@ -147,3 +199,13 @@ export class MsgStore {
|
|
|
147
199
|
|
|
148
200
|
export function defaultMsgStorePath(): string { return join(elanousStateRoot(), 'msg', 'messages.db'); }
|
|
149
201
|
export function openMsgStore(path?: string): MsgStore { return new MsgStore(path); }
|
|
202
|
+
|
|
203
|
+
/** Observe one recipient without creating a store or advancing its acknowledgement. */
|
|
204
|
+
export function readUnreadCount(recipient: string, path: string = defaultMsgStorePath()): number | null {
|
|
205
|
+
const to = canonicalSeatId(recipient);
|
|
206
|
+
if (to === 'ALL') throw new Error('ALL is a topic, not a recipient');
|
|
207
|
+
if (!existsSync(path)) return null;
|
|
208
|
+
const db = new Database(path, { readonly: true });
|
|
209
|
+
try { return unreadCountOn(db, to); }
|
|
210
|
+
finally { db.close(); }
|
|
211
|
+
}
|
|
@@ -505,6 +505,8 @@ export interface NexusHttpServerOpts {
|
|
|
505
505
|
draftMetrics?: DraftMetricsSource;
|
|
506
506
|
decisions?: Pick<DecisionsRouteDeps, 'ledger'>;
|
|
507
507
|
opsBoard?: Pick<OpsBoardDeps, 'openStore'>;
|
|
508
|
+
/** `GET /api/task-agent/board` 의 원장 경로 — 생략하면 인스턴스의 task-agent-actions.json. */
|
|
509
|
+
taskAgentStatePath?: string;
|
|
508
510
|
cardFollowup?: CardFollowupJobs;
|
|
509
511
|
skillExec?: SkillExecJobs;
|
|
510
512
|
execRequests?: ExecRequestRunner;
|
|
@@ -943,6 +945,8 @@ function defaultCardFollowupJobs(): CardFollowupJobs {
|
|
|
943
945
|
return cardFollowupJobs ??= createCardFollowupJobs();
|
|
944
946
|
}
|
|
945
947
|
|
|
948
|
+
const TASK_AGENT_BOARD_PATH = '/api/task-agent/board';
|
|
949
|
+
|
|
946
950
|
let skillExecJobs: SkillExecJobs | undefined;
|
|
947
951
|
function defaultSkillExecJobs(): SkillExecJobs {
|
|
948
952
|
return skillExecJobs ??= createSkillExecJobs();
|
|
@@ -1521,6 +1525,24 @@ export async function routeRequest(
|
|
|
1521
1525
|
...opts.opsBoard,
|
|
1522
1526
|
});
|
|
1523
1527
|
}
|
|
1528
|
+
// TASKS-ON-TA-LEDGER — 읽기 전용 · 이 경로는 `/v1/` 밖이라 default-deny 관문이 못 덮는다 → 여기서 owner 인증을 직접 건다.
|
|
1529
|
+
if (pathname === TASK_AGENT_BOARD_PATH) {
|
|
1530
|
+
if (!opts.metaApi) return jsonResponse({ error: 'meta-api-runtime-not-wired' }, 503);
|
|
1531
|
+
if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1532
|
+
if (method !== 'GET') return jsonResponse({ error: 'method-not-allowed', method }, 405);
|
|
1533
|
+
// 동적 import — 다른 무거운 라우트(skill-exec · card-followup)와 같은 꼴: task-agent 모듈 트리를 데몬 기동 경로에 싣지 않는다.
|
|
1534
|
+
const [{ taskAgentBoard }, { taskAgentStatePath }] = await Promise.all([import('../../task-agent/board.js'), import('../../task-agent/task-hand.js')]);
|
|
1535
|
+
try {
|
|
1536
|
+
// progress 관측은 동기 수 초라 요청이 명시할 때만(`?progress=1`) — 기본 응답은 progress=null(UX 수확 리뷰 should-fix).
|
|
1537
|
+
const withProgress = new URL(req.url, 'http://local').searchParams.get('progress') === '1';
|
|
1538
|
+
const response = taskAgentBoard(opts.taskAgentStatePath ?? taskAgentStatePath(), { withProgress });
|
|
1539
|
+
debug.log('task-agent', 'board-served', { projects: response.board.length });
|
|
1540
|
+
return jsonResponse(response);
|
|
1541
|
+
} catch (error) {
|
|
1542
|
+
debug.log('task-agent', 'board-read-failed', { error: error instanceof Error ? error.message : String(error) });
|
|
1543
|
+
return jsonResponse({ error: 'task-agent-ledger-unreadable' }, 503);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1524
1546
|
if (method === 'GET' && pathname === DECISIONS_PATH) {
|
|
1525
1547
|
return handleDecisions(req, {
|
|
1526
1548
|
authorize: request => !!opts.metaApi && checkAuth(request, opts.metaApi),
|
|
@@ -74,6 +74,9 @@ interface RotationDecision {
|
|
|
74
74
|
readonly resetCreditAccount?: string;
|
|
75
75
|
/** SUBSCRIPTION-EXHAUST-REROUTE — 크레딧 예비분에 닿아 `no-candidate` 로 넘겼을 때만 있다(잔액은 «알려진» 값). */
|
|
76
76
|
readonly creditReserveHit?: { readonly balance: number; readonly reserve: number };
|
|
77
|
+
/** CREDIT-SPEND-ORDER — 구독·리셋권이 다 없어 «다른 계정의 선불 크레딧»으로 옮긴 `rotated` 일 때만 true.
|
|
78
|
+
* 이 이동도 크레딧 진입이다 — 호출부가 💳 알림 ⊕ `credit-spend-start` 를 낸다(10-12 S2: 이 갈래만 알림 0). */
|
|
79
|
+
readonly creditEntry?: true;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
/** ⛔ 비공개 — 호출자는 객체 리터럴로 준다(구조적 타이핑). */
|
|
@@ -261,7 +264,7 @@ export function decideCodexRotation(input: RotationInput): RotationDecision {
|
|
|
261
264
|
const curHas = input.currentHasCredits ?? self?.hasCredits;
|
|
262
265
|
const currentDry = curHas === false || (typeof cur === 'number' && cur <= floor);
|
|
263
266
|
if (richest && (currentDry || (typeof cur === 'number' && richest.creditBalance! > cur * 1.2))) {
|
|
264
|
-
return { reason: 'rotated', candidateCount, accountThresholds, to: richest };
|
|
267
|
+
return { reason: 'rotated', candidateCount, accountThresholds, to: richest, creditEntry: true };
|
|
265
268
|
}
|
|
266
269
|
// 🩸 10-11: 크레딧이 0 이 돼도 여기 머물러 codex 로 계속 쐈다. 잔액이 «알려져 있고» 예비분 이하이며
|
|
267
270
|
// 예비분을 넘는 다른 계정도 없으면 «갈 곳 없음» — 폴백 체인이 다음 칸을 정한다. 모르면 종전대로 머문다.
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
codexAccountThresholdPercent,
|
|
25
25
|
type RotationCandidate,
|
|
26
26
|
} from './codex-account-rotation.js';
|
|
27
|
-
import { codexPolicyAllowsCredits, codexPolicyAllowsFallback, resolveCodexQuotaPolicy, type CodexQuotaPolicy, type ResolvedCodexQuotaPolicy } from './codex-quota-policy.js';
|
|
27
|
+
import { codexPolicyAllowsCredits, codexPolicyAllowsFallback, resolveCodexQuotaPolicy, type CodexQuotaPolicy, type CodexQuotaPolicyFileValue, type ResolvedCodexQuotaPolicy } from './codex-quota-policy.js';
|
|
28
28
|
import { emitDecision } from '../live/detail-switch.js';
|
|
29
29
|
import { debug } from '../debug/log.js';
|
|
30
30
|
import {
|
|
@@ -238,11 +238,21 @@ function pinnedAccountExhausted(home: string, accountName: string): boolean {
|
|
|
238
238
|
|
|
239
239
|
/** codex 한도 정책(`llm.codexQuotaPolicy` · 옛 `codexCreditsAllowed`) — 못 읽으면 `fallback`(크레딧은 돈이라 fail-closed). */
|
|
240
240
|
export function codexQuotaPolicyFromConfig(): CodexQuotaPolicy {
|
|
241
|
-
try { return resolveCodexQuotaPolicy(configReader().llm).policy; } catch { return 'fallback'; }
|
|
241
|
+
try { return resolveCodexQuotaPolicy(configReader().llm, codexQuotaPolicyFileValue()).policy; } catch { return 'fallback'; }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** `policy/llm.yaml` 의 `credits.codex` — 파일 출처일 때만 값을 낸다(없거나 다른 출처면 undefined). 파일이 깨졌거나 못 읽으면 `unreadable`. */
|
|
245
|
+
function codexQuotaPolicyFileValue(): CodexQuotaPolicyFileValue | undefined {
|
|
246
|
+
try {
|
|
247
|
+
const loaded = loadLlmPolicy({ legacyConfig: {} });
|
|
248
|
+
if (!loaded.filePresent) return undefined;
|
|
249
|
+
if (!loaded.valid) return 'unreadable';
|
|
250
|
+
return loaded.sources['credits.codex'] === 'file' ? loaded.policy.credits.codex : undefined;
|
|
251
|
+
} catch { return 'unreadable'; }
|
|
242
252
|
}
|
|
243
253
|
|
|
244
254
|
function inspectedQuotaPolicy(): ResolvedCodexQuotaPolicy {
|
|
245
|
-
try { return resolveCodexQuotaPolicy(configReader().llm); } catch { return { policy: 'fallback', source: 'default' }; }
|
|
255
|
+
try { return resolveCodexQuotaPolicy(configReader().llm, codexQuotaPolicyFileValue()); } catch { return { policy: 'fallback', source: 'default' }; }
|
|
246
256
|
}
|
|
247
257
|
|
|
248
258
|
/** 지금 계정의 크레딧 신호 — 판정 입력 두 칸. 신호를 이 계정에 귀속할 수 없으면 비운다(모른다). */
|
|
@@ -491,7 +501,7 @@ function acquireCreditSpendAlertLock(path: string, account: string): boolean {
|
|
|
491
501
|
/** UTC 일자별 성공한 계정 알림만 기록한다. 잠근 채 발송하여 동시 런도 중복 발송하지 않는다. */
|
|
492
502
|
function notifyCreditSpendStart(
|
|
493
503
|
account: string,
|
|
494
|
-
reason: 'credits-allowed' | 'credit-pace',
|
|
504
|
+
reason: 'credits-allowed' | 'credit-pace' | 'credits-rotated',
|
|
495
505
|
usage: readonly RotationCandidate[],
|
|
496
506
|
now: number,
|
|
497
507
|
counterPath: string,
|
|
@@ -793,11 +803,14 @@ export function resolveCodexAccountForRun(
|
|
|
793
803
|
});
|
|
794
804
|
observeRotation(decision, current.name);
|
|
795
805
|
// 발송 의무는 이 실행 경로에서 잠금 해제까지 기다린 뒤 하루 카운터에 기록한다.
|
|
796
|
-
|
|
806
|
+
// CREDIT-SPEND-ORDER(10-12) — «다른 계정의 선불 크레딧으로 옮김»(`rotated` ⊕ creditEntry)도 크레딧 진입이다.
|
|
807
|
+
const creditSpendReason = decision.reason === 'credits-allowed' || decision.reason === 'credit-pace' ? decision.reason
|
|
808
|
+
: decision.reason === 'rotated' && decision.creditEntry ? 'credits-rotated' as const : undefined;
|
|
809
|
+
if (creditSpendReason && !deps.counterPath && isUnderTestRunner(process.env)) {
|
|
797
810
|
// 시험 러너 가드(autoConsume 의 test-runtime-guard 와 같은 관용구) — 카운터를 주입 안 한 시험이 실제 카운터·송신기에 닿지 않는다.
|
|
798
811
|
debug.log('oauth.codex-account', 'credit-spend-alert-skipped', { account: decision.to?.name ?? current.name, reason: 'test-runtime-guard' });
|
|
799
|
-
} else if (
|
|
800
|
-
notifyCreditSpendStart(decision.to?.name ?? current.name,
|
|
812
|
+
} else if (creditSpendReason) {
|
|
813
|
+
notifyCreditSpendStart(decision.to?.name ?? current.name, creditSpendReason, candidates, now,
|
|
801
814
|
deps.counterPath ?? join(codexCredentialRoot(), 'budget', 'codex-credit-spend-alert.json'));
|
|
802
815
|
}
|
|
803
816
|
// 순서 ② — 구독 남은 계정이 없고 리셋권이 있으면 «스스로 1개» 쓴다(일일 상한 · 비동기 · 이번 호출은 종전대로 머문다).
|
|
@@ -9,15 +9,20 @@
|
|
|
9
9
|
// credits — 한도 안 ⊕ 크레딧(찬 계정을 선불 크레딧으로 계속). 크레딧도 떨어져 요청이 한도 오류를 내면 폴백 체인.
|
|
10
10
|
//
|
|
11
11
|
// ⛔ 옛 키 `llm.codexCreditsAllowed: true` 는 `credits` 로 읽는다(새 키가 있으면 새 키가 이긴다).
|
|
12
|
+
// ⭐ 새 자리 = `policy/llm.yaml` 의 `credits.codex`(use→credits · fallback→fallback · never→within-quota).
|
|
13
|
+
// 풀이 순서: env → 정책 파일(파일 출처일 때만) → 옛 `llm.codexQuotaPolicy` → 옛 `llm.codexCreditsAllowed` → fallback.
|
|
14
|
+
// 옛 키는 지우지 않고 읽기만 한다(적용·가려짐은 `codex.policy` 관측으로 남는다).
|
|
12
15
|
// ⛔ 못 읽거나 모르는 값이면 `fallback` — 크레딧은 돈이라 fail-closed(종전 기본과 같다).
|
|
13
16
|
|
|
17
|
+
import { debug } from '../debug/log.js';
|
|
18
|
+
|
|
14
19
|
export const CODEX_QUOTA_POLICIES = ['within-quota', 'fallback', 'credits'] as const;
|
|
15
20
|
export type CodexQuotaPolicy = (typeof CODEX_QUOTA_POLICIES)[number];
|
|
16
21
|
|
|
17
22
|
export interface ResolvedCodexQuotaPolicy {
|
|
18
23
|
readonly policy: CodexQuotaPolicy;
|
|
19
|
-
/** 어디서 정해졌나 — `config`(
|
|
20
|
-
readonly source: 'env' | 'config' | 'legacy-credits' | 'default' | 'invalid';
|
|
24
|
+
/** 어디서 정해졌나 — `policy-file`(policy/llm.yaml credits.codex) · `config`(옛 `codexQuotaPolicy`) · `legacy-credits`(옛 `codexCreditsAllowed`) · `default` · `invalid`(모르는 값 → 기본). */
|
|
25
|
+
readonly source: 'env' | 'policy-file' | 'config' | 'legacy-credits' | 'default' | 'invalid';
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export const CODEX_QUOTA_POLICY_LABEL: Readonly<Record<CodexQuotaPolicy, string>> = {
|
|
@@ -30,16 +35,40 @@ export function isCodexQuotaPolicy(value: unknown): value is CodexQuotaPolicy {
|
|
|
30
35
|
return typeof value === 'string' && (CODEX_QUOTA_POLICIES as readonly string[]).includes(value);
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
/** `policy/llm.yaml` 의 `credits.codex` 값. `unreadable` = 파일이 있는데 깨졌거나 못 읽음(fail-closed 로 fallback). */
|
|
39
|
+
export type CodexQuotaPolicyFileValue = 'use' | 'fallback' | 'never' | 'unreadable';
|
|
40
|
+
|
|
41
|
+
const FILE_VALUE_TO_POLICY: Readonly<Record<Exclude<CodexQuotaPolicyFileValue, 'unreadable'>, CodexQuotaPolicy>> = {
|
|
42
|
+
use: 'credits',
|
|
43
|
+
fallback: 'fallback',
|
|
44
|
+
never: 'within-quota',
|
|
45
|
+
};
|
|
46
|
+
|
|
33
47
|
export function resolveCodexQuotaPolicy(
|
|
34
48
|
llm: { readonly codexQuotaPolicy?: unknown; readonly codexCreditsAllowed?: unknown } | undefined,
|
|
49
|
+
file?: CodexQuotaPolicyFileValue,
|
|
35
50
|
): ResolvedCodexQuotaPolicy {
|
|
36
51
|
// A Pod has no copy of the host config; the launcher hands the host's policy down in this variable
|
|
37
52
|
// (09-29: without it every Pod child fell back to grok while all three accounts still had credits).
|
|
38
53
|
const fromEnv = process.env.ELANOUS_CODEX_QUOTA_POLICY?.trim();
|
|
39
54
|
if (fromEnv && isCodexQuotaPolicy(fromEnv)) return { policy: fromEnv, source: 'env' };
|
|
55
|
+
// 정책 파일이 깨졌으면 옛 키가 credits 라 해도 따르지 않는다 — 크레딧은 돈이라 닫는다.
|
|
56
|
+
if (file === 'unreadable') return { policy: 'fallback', source: 'invalid' };
|
|
40
57
|
const raw = llm?.codexQuotaPolicy;
|
|
41
|
-
|
|
42
|
-
|
|
58
|
+
const legacy: { key: string; value: unknown; policy: CodexQuotaPolicy } | undefined = isCodexQuotaPolicy(raw)
|
|
59
|
+
? { key: 'llm.codexQuotaPolicy', value: raw, policy: raw }
|
|
60
|
+
: llm?.codexCreditsAllowed === true ? { key: 'llm.codexCreditsAllowed', value: true, policy: 'credits' } : undefined;
|
|
61
|
+
if (file !== undefined) {
|
|
62
|
+
const policy = FILE_VALUE_TO_POLICY[file];
|
|
63
|
+
if (legacy && legacy.policy !== policy) debug.log('codex.policy', 'legacy-key-shadowed', { key: legacy.key, legacy: legacy.value, file });
|
|
64
|
+
return { policy, source: 'policy-file' };
|
|
65
|
+
}
|
|
66
|
+
if (legacy) {
|
|
67
|
+
debug.log('codex.policy', 'legacy-key-applied', { key: legacy.key, value: legacy.value });
|
|
68
|
+
return legacy.key === 'llm.codexQuotaPolicy'
|
|
69
|
+
? { policy: legacy.policy, source: 'config' }
|
|
70
|
+
: { policy: 'credits', source: 'legacy-credits' };
|
|
71
|
+
}
|
|
43
72
|
if (raw !== undefined) return { policy: 'fallback', source: 'invalid' };
|
|
44
73
|
return { policy: 'fallback', source: 'default' };
|
|
45
74
|
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type OverviewSnapshot, type OwnerTaskRow, type ParentsInfo, type PodMemberRow, type ReleaseRunInfo, type ScheduleInfo,
|
|
17
17
|
} from './overview.js';
|
|
18
18
|
import { SEAT_ERA_SOURCE, readDispatcherBeats, readDispatcherCapacity, readSeatEraHanded, seatEraFeederDir } from './overview-seat-era.js';
|
|
19
|
+
import { matchesOverviewOwner, normalizeOverviewOwner } from './overview-owner.js';
|
|
19
20
|
|
|
20
21
|
const GB = 1024 ** 3;
|
|
21
22
|
/** 하트비트 주기 30 s × 2 (RFC §A2 «낡음»). */
|
|
@@ -77,8 +78,8 @@ export function ownerRows(cards: readonly TaskCard[], sinceIso: string, ownerFil
|
|
|
77
78
|
const rows: Record<string, OwnerTaskRow> = {};
|
|
78
79
|
for (const card of cards) {
|
|
79
80
|
if (!card || typeof card.createdAt !== 'string' || card.createdAt < sinceIso) continue;
|
|
80
|
-
const owner = card.seat
|
|
81
|
-
if (ownerFilter
|
|
81
|
+
const owner = normalizeOverviewOwner(card.seat);
|
|
82
|
+
if (ownerFilter !== undefined && !matchesOverviewOwner(owner, ownerFilter)) continue;
|
|
82
83
|
const row = rows[owner] ??= { handed: 0, launched: 0, prBound: 0, failed: 0, launchFailed: 0 };
|
|
83
84
|
if (card.status === 'handed') row.handed++;
|
|
84
85
|
else if (card.status === 'launched') row.launched++;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Owner labels used by ops overview task rows and the --owner filter. */
|
|
2
|
+
type OverviewOwnerKind = 'seat' | 'steward' | 'orchestrator' | 'external';
|
|
3
|
+
type OverviewOwner = `${OverviewOwnerKind}:${string}` | 'unassigned';
|
|
4
|
+
|
|
5
|
+
const OWNER_KINDS = new Set<OverviewOwnerKind>(['seat', 'steward', 'orchestrator', 'external']);
|
|
6
|
+
|
|
7
|
+
/** Normalize a task-card owner into a stable kind-prefixed overview key. */
|
|
8
|
+
export function normalizeOverviewOwner(value: unknown): OverviewOwner {
|
|
9
|
+
if (typeof value !== 'string' || value.trim() === '') return 'unassigned';
|
|
10
|
+
const normalized = value.trim();
|
|
11
|
+
const separator = normalized.indexOf(':');
|
|
12
|
+
if (separator >= 0) {
|
|
13
|
+
const kind = normalized.slice(0, separator).toLowerCase() as OverviewOwnerKind;
|
|
14
|
+
const name = normalized.slice(separator + 1).trim();
|
|
15
|
+
if (OWNER_KINDS.has(kind) && name) return `${kind}:${name}`;
|
|
16
|
+
}
|
|
17
|
+
const kind = normalized.toLowerCase();
|
|
18
|
+
if (kind === 'steward' || kind === 'orchestrator' || kind === 'external') return `${kind}:default`;
|
|
19
|
+
return `seat:${normalized}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Whether a normalized owner key matches a CLI filter, accepting either the full key or its kind. */
|
|
23
|
+
export function matchesOverviewOwner(owner: OverviewOwner, filter?: string): boolean {
|
|
24
|
+
if (!filter || filter === 'all') return true;
|
|
25
|
+
const normalizedFilter = filter.trim();
|
|
26
|
+
if (!normalizedFilter) return true;
|
|
27
|
+
if (normalizedFilter.toLowerCase() === 'unassigned') return owner === 'unassigned';
|
|
28
|
+
return owner === normalizeOverviewOwner(normalizedFilter) || owner.startsWith(`${normalizedFilter.toLowerCase()}:`);
|
|
29
|
+
}
|
|
@@ -118,6 +118,7 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
118
118
|
let stdout = '';
|
|
119
119
|
let stderrBuffer = '';
|
|
120
120
|
let killed = false;
|
|
121
|
+
let stdinError: string | undefined;
|
|
121
122
|
const onAbort = () => {
|
|
122
123
|
if (!killed) {
|
|
123
124
|
killed = true;
|
|
@@ -132,6 +133,14 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
132
133
|
opts.abortSignal.addEventListener('abort', onAbort, { once: true });
|
|
133
134
|
|
|
134
135
|
child.stdout?.on('data', (chunk) => { stdout += String(chunk); });
|
|
136
|
+
// A short-lived command can close its read end before end() finishes.
|
|
137
|
+
// EPIPE says only that stdin was unread; stdout and exit status still
|
|
138
|
+
// determine the hook result. Other pipe errors are real I/O failures.
|
|
139
|
+
child.stdin?.on('error', (err: NodeJS.ErrnoException) => {
|
|
140
|
+
if (err.code === 'EPIPE') return;
|
|
141
|
+
stdinError = `stdin error: ${err.message}`;
|
|
142
|
+
opts.onStderr(stdinError);
|
|
143
|
+
});
|
|
135
144
|
child.stderr?.on('data', (chunk) => {
|
|
136
145
|
stderrBuffer += String(chunk);
|
|
137
146
|
let idx;
|
|
@@ -145,13 +154,19 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
145
154
|
clearTimeout(timer);
|
|
146
155
|
if (stderrBuffer.trim()) opts.onStderr(stderrBuffer.trim());
|
|
147
156
|
// killed => treat as a non-zero exit so dispatcher abort.
|
|
148
|
-
resolve({ stdout, exitCode: killed ? 124 : (code ?? 1) });
|
|
157
|
+
resolve({ stdout, exitCode: killed ? 124 : stdinError ? 127 : (code ?? 1), error: stdinError });
|
|
149
158
|
});
|
|
150
159
|
child.on('error', (err) => {
|
|
151
160
|
clearTimeout(timer);
|
|
152
161
|
opts.onStderr(`spawn error: ${err.message}`);
|
|
153
162
|
resolve({ stdout, exitCode: 127 });
|
|
154
163
|
});
|
|
155
|
-
try { child.stdin?.end(opts.stdin); }
|
|
164
|
+
try { child.stdin?.end(opts.stdin); }
|
|
165
|
+
catch (err) {
|
|
166
|
+
if ((err as NodeJS.ErrnoException).code !== 'EPIPE') {
|
|
167
|
+
stdinError = `stdin error: ${(err as Error).message}`;
|
|
168
|
+
opts.onStderr(stdinError);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
156
171
|
});
|
|
157
172
|
}
|
|
@@ -137,6 +137,7 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
137
137
|
let stderrBuf = '';
|
|
138
138
|
let killed = false;
|
|
139
139
|
let timedOut = false;
|
|
140
|
+
let stdinError: string | undefined;
|
|
140
141
|
const kill = (timeout: boolean) => {
|
|
141
142
|
if (killed) return;
|
|
142
143
|
killed = true;
|
|
@@ -150,6 +151,14 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
150
151
|
opts.abortSignal.addEventListener('abort', () => kill(false), { once: true });
|
|
151
152
|
|
|
152
153
|
child.stdout?.on('data', (chunk) => { stdout += String(chunk); });
|
|
154
|
+
// Early exit may close stdin before end() finishes. A broken pipe must
|
|
155
|
+
// not replace the child's stdout/exit result; other write errors must
|
|
156
|
+
// surface as evaluator errors.
|
|
157
|
+
child.stdin?.on('error', (err: NodeJS.ErrnoException) => {
|
|
158
|
+
if (err.code === 'EPIPE') return;
|
|
159
|
+
stdinError = `stdin error: ${err.message}`;
|
|
160
|
+
opts.onStderr(stdinError);
|
|
161
|
+
});
|
|
153
162
|
child.stderr?.on('data', (chunk) => {
|
|
154
163
|
stderrBuf += String(chunk);
|
|
155
164
|
let idx;
|
|
@@ -164,8 +173,9 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
164
173
|
if (stderrBuf.trim()) opts.onStderr(stderrBuf.trim());
|
|
165
174
|
resolve({
|
|
166
175
|
stdout,
|
|
167
|
-
exitCode: timedOut ? 124 : (code ?? 1),
|
|
176
|
+
exitCode: timedOut ? 124 : stdinError ? 127 : (code ?? 1),
|
|
168
177
|
timedOut,
|
|
178
|
+
error: stdinError,
|
|
169
179
|
});
|
|
170
180
|
});
|
|
171
181
|
child.on('error', (err) => {
|
|
@@ -173,6 +183,12 @@ function runShell(opts: RunShellOpts): Promise<RunShellResult> {
|
|
|
173
183
|
opts.onStderr(`spawn error: ${err.message}`);
|
|
174
184
|
resolve({ stdout, exitCode: 127, timedOut: false });
|
|
175
185
|
});
|
|
176
|
-
try { child.stdin?.end(opts.stdin); }
|
|
186
|
+
try { child.stdin?.end(opts.stdin); }
|
|
187
|
+
catch (err) {
|
|
188
|
+
if ((err as NodeJS.ErrnoException).code !== 'EPIPE') {
|
|
189
|
+
stdinError = `stdin error: ${(err as Error).message}`;
|
|
190
|
+
opts.onStderr(stdinError);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
177
193
|
});
|
|
178
194
|
}
|
|
@@ -438,6 +438,13 @@ function declaresMain(packageRoot: string): boolean {
|
|
|
438
438
|
return !existsSync(join(packageRoot, 'plugin.json')) && !existsSync(join(packageRoot, '.codex-plugin', 'plugin.json'));
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
/** [wiring] Caller: installPlugin. The PluginManifest normalized by
|
|
442
|
+
* loadPluginManifestFromDir is handed into the install path here — the install
|
|
443
|
+
* destination follows the manifest identity, never the source spec/dir name. */
|
|
444
|
+
export function pluginInstallPath(root: string, market: string, manifest: PluginManifest): string {
|
|
445
|
+
return join(root, 'plugins', market, manifest.id, manifest.version);
|
|
446
|
+
}
|
|
447
|
+
|
|
441
448
|
export async function installPlugin(spec: string, opts: InstallOptions = {}): Promise<InstalledPlugin> {
|
|
442
449
|
const root = resolve(opts.root ?? elanousStateRoot());
|
|
443
450
|
const stageRoot = join(root, 'plugins', '.staging');
|
|
@@ -466,6 +473,10 @@ export async function installPlugin(spec: string, opts: InstallOptions = {}): Pr
|
|
|
466
473
|
const manifest: PluginManifest = loadPluginManifestFromDir(join(stage, 'package'), { id: source.expectedName ?? basename(spec) }).manifest;
|
|
467
474
|
if (!NAME.test(manifest.id) || !VERSION.test(manifest.version)) fail('io', 'invalid plugin name or version');
|
|
468
475
|
if (source.expectedName && (manifest.id !== source.expectedName || manifest.version !== source.expectedVersion)) fail('conflict', 'market name or version differs from manifest');
|
|
476
|
+
// [wiring] installPlugin is the caller: the PluginManifest normalized above by
|
|
477
|
+
// loadPluginManifestFromDir (present manifest or the loader's manifest-absent
|
|
478
|
+
// fallback) is handed into the install path here, past the NAME/VERSION gates.
|
|
479
|
+
const destination = pluginInstallPath(root, source.market, manifest);
|
|
469
480
|
const packageRoot = join(stage, 'package');
|
|
470
481
|
const mainPath = inside(packageRoot, manifest.main);
|
|
471
482
|
// A skills/graphs-only pack (official `elanous-basics`) declares no `main` — the default `./plugin.ts` is not a promise.
|
|
@@ -480,7 +491,6 @@ export async function installPlugin(spec: string, opts: InstallOptions = {}): Pr
|
|
|
480
491
|
const path = inside(packageRoot, asset);
|
|
481
492
|
if (!existsSync(path) || !realpathSync(path).startsWith(`${realpathSync(packageRoot)}${sep}`)) fail('io', `plugin asset not found or unsafe: ${asset}`);
|
|
482
493
|
}
|
|
483
|
-
const destination = join(root, 'plugins', source.market, name, version);
|
|
484
494
|
const emit = (event: InstallEvent) => opts.onEvent?.(event);
|
|
485
495
|
emit({ event: 'resolve', plugin: name, version, sha256: source.sha256 });
|
|
486
496
|
let security: ReturnType<typeof inspectPluginSecurity>;
|
package/src/preview/terminal.ts
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
// just its mental model (active vs alternate buffer, viewport,
|
|
20
20
|
// cursor, cell attrs).
|
|
21
21
|
|
|
22
|
-
import type { IPty } from 'node-pty';
|
|
23
22
|
import * as fs from 'node:fs';
|
|
24
23
|
import { StringDecoder } from 'node:string_decoder';
|
|
25
24
|
import { Terminal } from '@xterm/headless';
|
|
@@ -104,6 +103,17 @@ export interface PreviewTerminalOpts {
|
|
|
104
103
|
onRawOutput?: (chunk: string) => void;
|
|
105
104
|
}
|
|
106
105
|
|
|
106
|
+
// ⛔ `import type { IPty } from 'node-pty'` 도 두지 않는다 — PWA `next build` 가 이 파일까지 타입 검사하는데,
|
|
107
|
+
// node-pty 는 optionalDependency 라 리눅스(WSL)·게이트 Pod 설치에서 빠지면 «Cannot find module 'node-pty'»
|
|
108
|
+
// 로 빌드가 죽고 self-update 가 매번 실패한다(LINUX-SELF-UPDATE-NODEPTY · 10-11). 이 파일이 실제로 쓰는 면만 둔다.
|
|
109
|
+
/** node-pty `IPty` 중 이 파일이 부르는 면(pid · resize · kill · onExit). master fd 는 resolveMasterFd 가 비공개 칸에서 읽는다. */
|
|
110
|
+
export interface NodePtyHandle {
|
|
111
|
+
readonly pid: number;
|
|
112
|
+
resize(cols: number, rows: number): void;
|
|
113
|
+
kill(signal?: string): void;
|
|
114
|
+
onExit(listener: (e: { exitCode: number | null; signal?: number }) => void): unknown;
|
|
115
|
+
}
|
|
116
|
+
|
|
107
117
|
/** Shared so tests can override (fake pty) — the default is node-pty. */
|
|
108
118
|
export type SpawnFn = (shell: string, args: string[], opts: {
|
|
109
119
|
name: string;
|
|
@@ -111,7 +121,7 @@ export type SpawnFn = (shell: string, args: string[], opts: {
|
|
|
111
121
|
rows: number;
|
|
112
122
|
cwd: string;
|
|
113
123
|
env: Record<string, string>;
|
|
114
|
-
}) =>
|
|
124
|
+
}) => NodePtyHandle;
|
|
115
125
|
|
|
116
126
|
// ⛔⭐ `node-pty` 를 «최상위»에서 싣지 않는다 — 이 모듈은 dashboard·shell-runner 등 다섯 곳이
|
|
117
127
|
// 정적으로 끌어오므로, 최상위 import 면 ***PTY 를 안 쓰는 명령(`--version`)까지*** 네이티브 바인딩을
|
|
@@ -124,7 +134,7 @@ export type SpawnFn = (shell: string, args: string[], opts: {
|
|
|
124
134
|
const defaultSpawn: SpawnFn = (shell, args, o) => {
|
|
125
135
|
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
|
|
126
136
|
const pty: any = require('node-pty');
|
|
127
|
-
return pty.spawn(shell, args, o as any) as
|
|
137
|
+
return pty.spawn(shell, args, o as any) as NodePtyHandle;
|
|
128
138
|
};
|
|
129
139
|
|
|
130
140
|
/** node-pty 네이티브 `resize(fd, cols, rows)` 를 임의의 master fd(우리 dup)에 부른다. 'ok' 또는 실패 사유. */
|
|
@@ -163,7 +173,7 @@ export interface PreviewRegistryDeps {
|
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
export class PreviewTerminal {
|
|
166
|
-
private pty:
|
|
176
|
+
private pty: NodePtyHandle | null = null;
|
|
167
177
|
private dupFd: number = -1;
|
|
168
178
|
/** ★ P0b-2 — useRegistry 모드일 때 공유 버스 핸들(dup-fd 대신). null=dup-fd 경로(기본). */
|
|
169
179
|
private registryHandle: PtyHandle | null = null;
|
|
@@ -470,7 +480,7 @@ export class PreviewTerminal {
|
|
|
470
480
|
/** node-pty doesn't publish its master fd as a stable field; dig
|
|
471
481
|
* through the plausible private slots in order of most-to-least
|
|
472
482
|
* likely so a minor library revision doesn't bite us. */
|
|
473
|
-
private resolveMasterFd(p:
|
|
483
|
+
private resolveMasterFd(p: NodePtyHandle): number | null {
|
|
474
484
|
const any = p as any;
|
|
475
485
|
const fd = any._fd
|
|
476
486
|
?? any._socket?._handle?.fd
|