elanous 0.2.24 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
- package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
- package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/release-loop.yaml +5 -5
- package/graphs/steward/recipes.yaml +4 -0
- package/graphs/steward/steward.yaml +10 -1
- package/package.json +1 -1
- package/scripts/bench-report.ts +46 -1
- package/scripts/ci-typecheck-changed.ts +88 -7
- package/scripts/coord-msg-bridge.ts +209 -0
- package/scripts/coord-post.sh +40 -7
- package/scripts/coord-requests-bridge.ts +10 -5
- package/scripts/expose-rubric-suggest.ts +1 -1
- package/scripts/measure-tsc-affected-roots.ts +10 -1
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- package/scripts/release-loop/export-check-node.ts +8 -5
- package/scripts/release-loop/gate-closure.ts +286 -0
- package/scripts/release-loop/gate-node.ts +73 -13
- package/scripts/release-loop/gate-partial.ts +34 -6
- package/scripts/release-loop/node-verdict.ts +7 -2
- package/scripts/release-loop/ops-upgrade-node.ts +63 -42
- package/scripts/release-loop/publish-node.ts +6 -0
- package/scripts/release-loop/resume-release.ts +37 -10
- package/scripts/release-loop/resume.ts +69 -4
- package/scripts/tsc-baseline-cache.ts +28 -3
- package/scripts/usage-rollup.ts +27 -13
- package/scripts/ux-sim.ts +30 -1
- package/skills/youtube-master/scripts/main.ts +4 -1
- package/skills/youtube-master/src/obsidian.ts +9 -0
- package/src/agent/task-notification.ts +30 -1
- package/src/agent-substrate/acp-implementer.ts +14 -7
- package/src/agent-substrate/pr-reviewer.ts +30 -10
- package/src/agent-substrate/review-observation.ts +9 -2
- package/src/agent-substrate/self-review-cli.ts +154 -16
- package/src/boot/daemon-tools/self-implement.ts +72 -4
- package/src/budget/cost-tier-advisor.ts +91 -0
- package/src/budget/llm-cost.ts +5 -1
- package/src/budget/shadow-arms.ts +77 -0
- package/src/budget/types.ts +5 -3
- package/src/budget/unified-usage.ts +172 -8
- package/src/cli/control-cli.ts +29 -0
- package/src/cli/doctor-cli.ts +106 -3
- package/src/cli/friendly-errors.ts +113 -0
- package/src/cli/intake-cli.ts +3 -1
- package/src/cli/memory-cli.ts +182 -0
- package/src/cli/model-watch-cli.ts +4 -1
- package/src/cli/msg-cli.ts +15 -5
- package/src/cli/pr-cli.ts +53 -0
- package/src/cli/pr-land-overlap-evidence.ts +18 -10
- package/src/cli/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +41 -12
- package/src/cli/release-run-if-ready.ts +11 -0
- package/src/cli/resource-cli.ts +48 -0
- package/src/cli/retro-cli.ts +12 -3
- package/src/cli/seat-cli.ts +121 -0
- package/src/cli/seat-requests-cli.ts +25 -0
- package/src/cli/self-utterances-cli.ts +140 -0
- package/src/cli/tasks-cli.ts +168 -14
- package/src/cli/usage-cli.ts +3 -1
- package/src/compact/verify-probe.ts +23 -3
- package/src/context-card/cell.ts +40 -0
- package/src/context-card/index.ts +50 -0
- package/src/control/control-status.ts +30 -1
- package/src/dashboard/boot-timing.ts +35 -0
- package/src/dashboard/index.ts +86 -24
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/debug/log-diet.ts +16 -4
- package/src/debug/log.ts +1 -1
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +29 -8
- package/src/domains/surface-events.ts +16 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +446 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/runner.ts +12 -6
- package/src/graph-wizard/archetypes.ts +14 -8
- package/src/graph-wizard/generate.ts +77 -1
- package/src/grok.ts +13 -7
- package/src/harness/harness-cli-command.ts +102 -51
- package/src/harness/harness-stop.ts +93 -19
- package/src/index.ts +52 -179
- package/src/instance/current.ts +2 -6
- package/src/instance/resolve.ts +5 -6
- package/src/intake-plane/collect-github.ts +7 -2
- package/src/intake-plane/lens.ts +46 -4
- package/src/intake-plane/requirement-funnel.ts +53 -1
- package/src/intelligence-map/catalog-feed.ts +119 -0
- package/src/intelligence-map/model-watch-intake.ts +40 -0
- package/src/intelligence-map/model-watch-mission.ts +14 -1
- package/src/llm/open-weight-discipline.ts +21 -0
- package/src/llm/openai-sampling-fields.ts +89 -0
- package/src/llm/runtime-model-family.ts +61 -0
- package/src/llm/zai-coding-plan.ts +27 -1
- package/src/llm.ts +17 -97
- package/src/machines/machine-ledger.ts +31 -3
- package/src/maturity/cli-maturity.ts +13 -3
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/msg/msg-store.ts +69 -7
- package/src/nexus/api/http-server.ts +22 -0
- package/src/oauth/codex-account-rotation.ts +4 -1
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-quota-policy.ts +33 -4
- package/src/ops/overview-collect.ts +3 -2
- package/src/ops/overview-owner.ts +29 -0
- package/src/plugin-hooks/shell-hook.ts +17 -2
- package/src/plugin-missions/evaluator-runner.ts +18 -2
- package/src/plugins/install/plugin-install.ts +11 -1
- package/src/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/prompt-enhance/enhance.ts +11 -0
- package/src/release-loop/auto-start.ts +7 -5
- package/src/release-loop/checklist.ts +52 -5
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/gate-shards.ts +4 -0
- package/src/release-loop/light-rc.ts +84 -13
- package/src/release-loop/merged-pr-checklist.ts +35 -5
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/seat-loop/duty-ledger.ts +64 -0
- package/src/seat-loop/seat-loop.ts +5 -1
- package/src/self-dev/decompose.ts +37 -3
- package/src/self-dev/dev-pipeline.ts +32 -7
- package/src/self-dev/draft-residue.ts +16 -6
- package/src/self-dev/draft-sweep.ts +75 -18
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/orchestrate.ts +6 -2
- package/src/self-dev/run-supervisor.ts +72 -8
- package/src/self-implement/gate-cli.ts +29 -10
- package/src/self-implement/gate-remote.ts +4 -1
- package/src/self-implement/goal-author.ts +15 -29
- package/src/self-implement/goal-command-execution.ts +26 -0
- package/src/self-implement/goal-new-paths.ts +42 -0
- package/src/self-implement/host-regate.ts +124 -30
- package/src/self-implement/importer-test-index.ts +3 -1
- package/src/self-implement/l8-merge-queue.ts +80 -2
- package/src/self-implement/merge-train.ts +19 -0
- package/src/self-implement/off-diff-evidence.ts +40 -1
- package/src/self-implement/orchestrator.ts +90 -20
- package/src/self-implement/premise-review.ts +159 -0
- package/src/self-implement/pwa-import-graph.ts +194 -7
- package/src/self-implement/regate-detail.ts +79 -0
- package/src/self-implement/review-deferred-to-host.ts +21 -0
- package/src/self-implement/rework-budget-judgment.ts +23 -3
- package/src/self-implement/running-runs.ts +2 -2
- package/src/self-implement/scope-adjacency.ts +23 -0
- package/src/self-implement/seams.ts +42 -7
- package/src/self-implement/self-implement-runtime.ts +126 -21
- package/src/session/index.ts +14 -4
- package/src/session-runtime/index.ts +55 -11
- package/src/skills/tools/agent.ts +16 -1
- package/src/skills/tools/persistent-grounding.ts +11 -1
- package/src/skills/tools/shell.ts +33 -1
- package/src/steward/rejudge-tick.ts +142 -0
- package/src/task-agent/board.ts +92 -3
- package/src/task-agent/card-evidence.ts +88 -1
- package/src/task-agent/cover.ts +85 -1
- package/src/task-agent/live-moves.ts +14 -6
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +370 -29
- package/src/task-agent/review-result-capture.ts +67 -2
- package/src/task-agent/shadow.ts +148 -21
- package/src/task-agent/task-hand.ts +22 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
- package/src/tool-runtime/tool-search-runtime.ts +25 -0
- package/src/tui.ts +20 -1
- package/src/user-config.ts +21 -63
- package/src/ux-sim/fault-cred-expiry.ts +100 -0
- package/src/ux-sim/fault-pod-death.ts +74 -0
- package/src/ux-sim/fault-pool-cap.ts +81 -0
- package/src/version/packed-revision.json +1 -1
- package/src/webclone/qa-table.ts +22 -0
- package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
- /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
package/src/cli/release-cli.ts
CHANGED
|
@@ -28,7 +28,7 @@ import { effectiveInstanceRoot, releaseLedgerRoot } from '../instance/resolve.js
|
|
|
28
28
|
import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
|
|
29
29
|
import { envLiteral } from '../platform/env-literal.js';
|
|
30
30
|
import { getUserConfig, userConfigPath } from '../user-config.js';
|
|
31
|
-
import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, devVersion, lintDocRefs, listChecklist, normalizeRefs, ownerMatches, parseOwner, parityGap, refRoots, removeItem, renderRefsStatus, seedFromRoadmap, setItem, summarizeChecklist, type ChecklistStatus, type ChecklistDisposition, type ChecklistKind } from '../release-loop/checklist.js';
|
|
31
|
+
import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, devVersion, inspectChecklistTargetPaths, lintDocRefs, listChecklist, normalizeRefs, ownerMatches, parseOwner, parityGap, refRoots, removeItem, renderRefsStatus, seedFromRoadmap, setItem, summarizeChecklist, type ChecklistStatus, type ChecklistDisposition, type ChecklistKind, type ChecklistDispatchKind } from '../release-loop/checklist.js';
|
|
32
32
|
import * as features from '../release-loop/feature-store.js';
|
|
33
33
|
import { evidencePlan, landedButYellow, type MergedChecklistPr } from '../release-loop/landed-but-yellow.js';
|
|
34
34
|
import { formatSchedule, getSchedule, listSchedules, setSchedule } from '../release-loop/release-schedule.js';
|
|
@@ -488,6 +488,28 @@ async function jsonAction<T>(json: boolean | undefined, body: (log: (l: string)
|
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
function warnChecklistTargetPaths(input: { title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind }): void {
|
|
492
|
+
const cwd = process.cwd();
|
|
493
|
+
const existsAtMain = (path: string): boolean => {
|
|
494
|
+
if (path.startsWith('/') || path.split('/').includes('..')) return false;
|
|
495
|
+
const result = spawnSync('git', ['cat-file', '-e', `origin/main:${path}`], { cwd, timeout: 5_000, stdio: 'ignore' });
|
|
496
|
+
return result.status === 0;
|
|
497
|
+
};
|
|
498
|
+
const mergedPrFiles = (number: number): string[] => {
|
|
499
|
+
const result = spawnSync('gh', ['pr', 'view', String(number), '--json', 'state,files'], { cwd, encoding: 'utf8', timeout: 10_000 });
|
|
500
|
+
if (result.status !== 0) return [];
|
|
501
|
+
try {
|
|
502
|
+
const pr = JSON.parse(result.stdout) as { state?: string; files?: Array<{ path?: string }> };
|
|
503
|
+
return pr.state === 'MERGED' ? (pr.files ?? []).map((file) => file.path).filter((path): path is string => typeof path === 'string') : [];
|
|
504
|
+
} catch { return []; }
|
|
505
|
+
};
|
|
506
|
+
const report = inspectChecklistTargetPaths(input, { existsAtMain, mergedPrFiles });
|
|
507
|
+
for (const warning of report.warnings) {
|
|
508
|
+
console.error(`⚠ 대상 경로: ${warning}${report.candidates.length ? ` · 후보: ${report.candidates.join(' · ')}` : ''}`);
|
|
509
|
+
debug.log('release.checklist', 'target-path-warning', { warning, candidates: report.candidates });
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
491
513
|
function checklistCodenames(): Record<string, string> {
|
|
492
514
|
const path = getElanousConfigDirOverride() ? join(effectiveInstanceRoot(), 'config.json') : userConfigPath();
|
|
493
515
|
if (!existsSync(path)) return {};
|
|
@@ -815,7 +837,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
815
837
|
process.exitCode = 1;
|
|
816
838
|
}
|
|
817
839
|
});
|
|
818
|
-
withContext(checklist.command('add <id> <title>').description('칸 추가')).option('--owner <owner>', '담당').option('--kind <kind>', 'screen = 다섯 화면 짝 칸 · 근거에 짝: PWA … · 데스크톱 … · 폴드 … · 아이폰 … · 아이패드 … 한 줄 · postpub = 발행 뒤 실측 칸 — 판 관문이 발행 전 판정에서 빼고 따로 센다')
|
|
840
|
+
withContext(checklist.command('add <id> <title>').description('칸 추가')).option('--owner <owner>', '담당').option('--kind <kind>', 'screen = 다섯 화면 짝 칸 · 근거에 짝: PWA … · 데스크톱 … · 폴드 … · 아이폰 … · 아이패드 … 한 줄 · postpub = 발행 뒤 실측 칸 — 판 관문이 발행 전 판정에서 빼고 따로 센다 · code|ops|measure|decision|umbrella = 발사 분류')
|
|
819
841
|
.option('--priority <priority>', 'P0|P1|P2').option('--deadline-version <v>', '마감 판').option('--predecessor <id...>', '선행 칸 id')
|
|
820
842
|
.option('--ceo-minutes <minutes>', '대표 손 분량(분)').option('--ceo-date <date>', '대표 손 날짜 YYYY-MM-DD (없으면 판 착지일 KST)')
|
|
821
843
|
.option('--accelerator', '가속 등급 — 다른 칸의 처리량을 올리는 칸(자율성·효율성·동시성). 생략하면 등급 없음')
|
|
@@ -824,12 +846,14 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
824
846
|
.action((id: string, title: string, opts: { ref?: string[]; owner?: string; kind?: string; priority?: string; deadlineVersion?: string; predecessor?: string[]; ceoMinutes?: string; ceoDate?: string; accelerator?: boolean; allowDuplicateId?: boolean }, cmd: Command) => {
|
|
825
847
|
const { version, json } = context(cmd);
|
|
826
848
|
if (!mayWrite(cmd)) return;
|
|
827
|
-
const
|
|
849
|
+
const dispatchKind = opts.kind && !['screen', 'postpub'].includes(opts.kind) ? opts.kind as ChecklistDispatchKind : undefined;
|
|
850
|
+
const data = addItem(version, { id, title, ...(opts.ref !== undefined ? { refs: opts.ref } : {}), ...(opts.owner !== undefined ? { owner: opts.owner } : {}), ...(opts.kind !== undefined && !dispatchKind ? { kind: opts.kind as ChecklistKind } : {}), ...(dispatchKind ? { dispatchKind } : {}), ...(opts.priority !== undefined ? { priority: opts.priority as PlacementPriority } : {}), ...(opts.deadlineVersion !== undefined ? { deadlineVersion: opts.deadlineVersion } : {}), ...(opts.predecessor !== undefined ? { predecessors: opts.predecessor } : {}), ...(opts.ceoMinutes !== undefined ? { ceoMinutes: ceoMinutes(opts.ceoMinutes) } : {}), ...(opts.ceoDate !== undefined ? { ceoDate: opts.ceoDate } : {}), ...(opts.accelerator ? { accelerator: true } : {}) }, { allowDuplicateId: opts.allowDuplicateId });
|
|
851
|
+
warnChecklistTargetPaths({ title, refs: opts.ref, dispatchKind });
|
|
828
852
|
if (json) console.log(JSON.stringify(data)); else console.log(`✅ ${id} 추가`);
|
|
829
853
|
});
|
|
830
854
|
withContext(checklist.command('set <id>').description('칸 상태·근거·담당·처분 갱신'))
|
|
831
855
|
.option('--status <status>', 'green|yellow|red|done').option('--evidence <evidence>', '근거').option('--owner <owner>', '담당')
|
|
832
|
-
.option('--disposition <disposition>', 'move|known-issue|block').option('--kind <kind>', 'screen = 다섯 화면 짝 칸 · 근거에 짝: PWA … · 데스크톱 … · 폴드 … · 아이폰 … · 아이패드 … 한 줄 · postpub = 발행 뒤 실측 칸 — 판 관문이 발행 전 판정에서 빼고 따로 센다')
|
|
856
|
+
.option('--disposition <disposition>', 'move|known-issue|block').option('--kind <kind>', 'screen = 다섯 화면 짝 칸 · 근거에 짝: PWA … · 데스크톱 … · 폴드 … · 아이폰 … · 아이패드 … 한 줄 · postpub = 발행 뒤 실측 칸 — 판 관문이 발행 전 판정에서 빼고 따로 센다 · code|ops|measure|decision|umbrella = 발사 분류')
|
|
833
857
|
.option('--priority <priority>', 'P0|P1|P2').option('--deadline-version <v>', '마감 판').option('--predecessor <id...>', '선행 칸 id').option('--no-predecessor', '선행 칸 비우기(진짜 의존이 아니면 · CHECKLIST-PRED-CLEAR)')
|
|
834
858
|
.option('--ceo-minutes <minutes>', '대표 손 분량(분)').option('--ceo-date <date>', '대표 손 날짜 YYYY-MM-DD')
|
|
835
859
|
.option('--accelerator', '가속 등급 부여').option('--no-accelerator', '가속 등급 해제(기본은 없음)')
|
|
@@ -840,7 +864,8 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
840
864
|
if (opts.disposition !== undefined && !['move', 'known-issue', 'block'].includes(opts.disposition)) throw new CliUserError(`잘못된 처분: ${opts.disposition}`, 'move|known-issue|block');
|
|
841
865
|
if (opts.status === undefined && opts.evidence === undefined && opts.owner === undefined && opts.disposition === undefined && opts.kind === undefined && opts.priority === undefined && opts.deadlineVersion === undefined && opts.predecessor === undefined && opts.ceoMinutes === undefined && opts.ceoDate === undefined && opts.accelerator === undefined && opts.ref === undefined) throw new CliUserError('갱신할 칸을 지정하라', '--ref · --status · --evidence · --owner · --disposition · --kind · --priority · --deadline-version · --predecessor · --ceo-minutes · --ceo-date · --accelerator · --no-accelerator 중 하나');
|
|
842
866
|
if (!mayWrite(cmd)) return;
|
|
843
|
-
const
|
|
867
|
+
const dispatchKind = opts.kind && !['screen', 'postpub'].includes(opts.kind) ? opts.kind as ChecklistDispatchKind : undefined;
|
|
868
|
+
const data = setItem(version, id, { ...(opts.ref !== undefined ? { refs: opts.ref } : {}), ...(opts.status !== undefined ? { status: opts.status as ChecklistStatus } : {}), ...(opts.evidence !== undefined ? { evidence: opts.evidence } : {}), ...(opts.owner !== undefined ? { owner: opts.owner } : {}), ...(opts.disposition !== undefined ? { disposition: opts.disposition as ChecklistDisposition } : {}), ...(opts.kind !== undefined && !dispatchKind ? { kind: opts.kind as ChecklistKind } : {}), ...(dispatchKind ? { dispatchKind } : {}), ...(opts.priority !== undefined ? { priority: opts.priority as PlacementPriority } : {}), ...(opts.deadlineVersion !== undefined ? { deadlineVersion: opts.deadlineVersion } : {}), ...(opts.predecessor !== undefined ? { predecessors: opts.predecessor === false ? [] : opts.predecessor } : {}), ...(opts.ceoMinutes !== undefined ? { ceoMinutes: ceoMinutes(opts.ceoMinutes) } : {}), ...(opts.ceoDate !== undefined ? { ceoDate: opts.ceoDate } : {}), ...(opts.accelerator !== undefined ? { accelerator: opts.accelerator ? true : null } : {}) }, process.env.ELANOUS_TRACK || 'cli');
|
|
844
869
|
const item = data.items.find((entry) => entry.id === id);
|
|
845
870
|
const why = item?.kind === 'screen' && item.status === 'green' ? parityGap(item.evidence) : null;
|
|
846
871
|
if (why) {
|
|
@@ -891,6 +916,8 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
891
916
|
if (!mayWrite(cmd)) return;
|
|
892
917
|
const snapshot = listChecklist(version);
|
|
893
918
|
features.retitle(id, title, actor(), snapshot.released, snapshot.dev);
|
|
919
|
+
const item = snapshot.items.find((entry) => entry.id === id);
|
|
920
|
+
warnChecklistTargetPaths({ title, evidence: item?.evidence, refs: item?.refs, dispatchKind: item?.dispatchKind });
|
|
894
921
|
if (json) console.log(JSON.stringify(listChecklist(version))); else console.log(`✅ ${id} 제목 수정`);
|
|
895
922
|
});
|
|
896
923
|
const evidence = checklist.command('evidence').description('칸의 PR·커밋 근거');
|
|
@@ -1107,17 +1134,18 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1107
1134
|
.description('가벼운 RC 점검 — 직전 판 컷(또는 --base) 이후 변경 범위 self gate ⊕ 상시 목록(release/light-rc-always.txt)을 원격 게이트 호스트에서 · 새 회귀(introduced>0)면 exit 1')
|
|
1108
1135
|
.requiredOption('--version <v>', '점검할 판(x.y.z)')
|
|
1109
1136
|
.option('--base <ref>', '비교 기준(기본: git merge-base origin/main origin/release/<원장 직전 판>)')
|
|
1137
|
+
.option('--head <ref>', '잴 커밋(기본: git fetch origin main 뒤 origin/main — 작업 트리 HEAD 가 아니다 · 다르면 분리 체크아웃에서 잰다)')
|
|
1110
1138
|
.option('--remote <host>', '게이트 호스트(기본 config gateRemote.host)')
|
|
1111
1139
|
.option('--local', '원격 대신 이 기계에서 돌린다(원격 자식이 이것으로 다시 불린다)')
|
|
1112
1140
|
.option('--shards <n>', '시험 분할 수', '4')
|
|
1113
1141
|
.option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
|
|
1114
|
-
.action(async (o: { version: string; base?: string; remote?: string; local?: boolean; shards: string; json?: boolean }) => {
|
|
1142
|
+
.action(async (o: { version: string; base?: string; head?: string; remote?: string; local?: boolean; shards: string; json?: boolean }) => {
|
|
1115
1143
|
// The root strips `--local` from argv (remote-bookmark attach) before Commander sees it — same read as `self gate`.
|
|
1116
1144
|
const local = !!o.local || process.argv.slice(2).includes('--local');
|
|
1117
1145
|
await jsonAction(o.json, async (log) => {
|
|
1118
1146
|
if (o.remote !== undefined && local) throw new Error('release light-rc: --remote and --local cannot be combined');
|
|
1119
1147
|
const shards = Number(o.shards);
|
|
1120
|
-
const result = await runLightRc(o.version, { base: o.base, remote: o.remote, local, shards, ledgerRoot: releaseRunDeps.ledgerRoot, log: (l) => console.error(l) }, lightRcDeps);
|
|
1148
|
+
const result = await runLightRc(o.version, { base: o.base, head: o.head, remote: o.remote, local, shards, ledgerRoot: releaseRunDeps.ledgerRoot, log: (l) => console.error(l) }, lightRcDeps);
|
|
1121
1149
|
for (const line of formatLightRc(result)) log(line);
|
|
1122
1150
|
return result;
|
|
1123
1151
|
}, (r) => r.ok);
|
|
@@ -1126,7 +1154,8 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1126
1154
|
.description('실패한 릴리스 런을 이어 달린다 — cut-branch --append 로 고친 release/<v> 새 끝을 version-release 기록에 반영(빨리감기만·상태 백업) 뒤 --from 노드부터')
|
|
1127
1155
|
.requiredOption('--run <runId>', '실패한 release-loop 런 ID')
|
|
1128
1156
|
.requiredOption('--from <node>', '다시 시작할 노드(예: gate)')
|
|
1129
|
-
.option('--partial', 'GATE-PARTIAL — --from gate 에서 앞
|
|
1157
|
+
.option('--partial', 'GATE-PARTIAL — --from gate 에서 바뀐 시험 ⊕ 앞 실패 ⊕ 바뀐 코드에 import 로 닿는 시험만 다시 돈다(끝이 움직인 --from gate 는 기본 · 의심이면 전체 게이트)')
|
|
1158
|
+
.option('--no-partial', 'GATE-REUSE-BY-DIFF 기본 부분 재검을 끄고 전체 게이트')
|
|
1130
1159
|
.option('--waive <node>', '저장된 실패 노드 한 개를 면제(--from 은 그 노드 그대로)')
|
|
1131
1160
|
.option('--reason <text>', '면제 사유 — 공개 알려진 문제에 들어갈 사용자 영향 설명')
|
|
1132
1161
|
.option('--accepted-regressions <json>', '알려진 문제 추가 입력 JSON 배열 [{"id":"…","note":"…"}]')
|
|
@@ -1153,7 +1182,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1153
1182
|
const override = result.state.inputOverrides?.at(-1);
|
|
1154
1183
|
if (o.gateExecutor !== undefined && override) log(`⇄ gate 실행기 ${override.set.gateExecutor}${override.set.gateRemote ? ` @ ${override.set.gateRemote}` : ''} (런 입력에 기록 · 면제 아님)`);
|
|
1155
1184
|
if (result.partial.requested) log(result.partial.applied
|
|
1156
|
-
? `◐ 부분
|
|
1185
|
+
? `◐ 부분 재검${result.partial.auto ? '(기본)' : ''}: ${result.partial.files}파일${result.partial.closure ? ` (코드 닿음 ${result.partial.closure.reached} · 닫힘 불투명 ${result.partial.closure.opaque})` : ''} · 나머지는 앞 게이트(${result.partial.priorCommit.slice(0, 12)}) 결과를 잇는다`
|
|
1157
1186
|
: `● 전체 게이트로: ${result.partial.reason}`);
|
|
1158
1187
|
log(`${result.tip.changed ? `↻ ${result.tip.branch} ${result.tip.from.slice(0, 12)} → ${result.tip.to.slice(0, 12)} (백업 ${result.tip.backup})` : `· ${result.tip.branch} 끝 그대로 ${result.tip.to.slice(0, 12)}`} · ${o.from} 부터 → ${result.state.status}`);
|
|
1159
1188
|
return { tip: result.tip, partial: result.partial, status: result.state.status, runId: result.state.runId,
|
|
@@ -1184,14 +1213,14 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1184
1213
|
const result = await autoStartScheduledRelease({
|
|
1185
1214
|
windowMinutes: Number(o.windowMinutes), apply: o.apply, ledgerRoot: scheduleLedgerRoot(),
|
|
1186
1215
|
readiness: (version, ledgerRoot, now) => releaseReadiness(version, { ledgerRoot, now: () => now, checklist: releaseRunDeps.checklist }),
|
|
1187
|
-
launch: async (version) => {
|
|
1188
|
-
const ran = await runAction({ version, ifReady: true, json: false }, log);
|
|
1216
|
+
launch: async (version, launchOptions) => {
|
|
1217
|
+
const ran = await runAction({ version, ifReady: true, publishAt: launchOptions?.publishAt, json: false }, log);
|
|
1189
1218
|
if (ran && typeof ran === 'object' && ran.deferred) return ran;
|
|
1190
1219
|
if (ran !== true) throw new Error(`release run 미시작 또는 실패: ${version}`);
|
|
1191
1220
|
},
|
|
1192
1221
|
});
|
|
1193
1222
|
if (result.status === 'planned') log(`· 미리 보기 ${result.version} · 컷 ${result.cutAt} · 실행하려면 --apply`);
|
|
1194
|
-
else if (result.status === 'started') log(`▶ 릴리스 시작 ${result.version} · 컷 ${result.cutAt}`);
|
|
1223
|
+
else if (result.status === 'started') log(`▶ 릴리스 시작 ${result.version} · 컷 ${result.cutAt}${result.publishAt ? ` · 발행 ${result.publishAt}` : ''}`);
|
|
1195
1224
|
else if (result.status === 'skipped') log(`· 릴리스 연기 ${result.version} · ${result.reason}`);
|
|
1196
1225
|
else log('· 선택할 컷 없음');
|
|
1197
1226
|
return result;
|
|
@@ -2,6 +2,8 @@ import { closeSync, mkdirSync, openSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { debug } from '../debug/log.js';
|
|
4
4
|
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
5
|
+
import { adviseLaunch, compareLaunchAdvice } from '../harness/launch-advice.js';
|
|
6
|
+
import type { QueuePool } from '../harness/harness-queue.js';
|
|
5
7
|
import type { ReleaseReadiness } from '../../scripts/release-loop/release-readiness.js';
|
|
6
8
|
|
|
7
9
|
export type ReleaseIfReadySkip = { skipped: true; reason: Exclude<ReleaseReadiness, { ready: true }>['reason']; detail: string };
|
|
@@ -12,6 +14,8 @@ export async function runReleaseIfReady<T>(version: string, deps: {
|
|
|
12
14
|
ledgerRoot?: string;
|
|
13
15
|
pid?: number;
|
|
14
16
|
now?: () => Date;
|
|
17
|
+
advice?: typeof adviseLaunch;
|
|
18
|
+
pool?: () => QueuePool | undefined;
|
|
15
19
|
}): Promise<ReleaseIfReadySkip | { skipped: false; result: T }> {
|
|
16
20
|
const skip = (readiness: Exclude<ReleaseReadiness, { ready: true }>): ReleaseIfReadySkip => {
|
|
17
21
|
const detail = readiness.reason === 'checklist-blocked'
|
|
@@ -40,6 +44,13 @@ export async function runReleaseIfReady<T>(version: string, deps: {
|
|
|
40
44
|
const insideLock = await deps.readiness(version, { isPidAlive: () => false });
|
|
41
45
|
if (!insideLock.ready) return skip(insideLock);
|
|
42
46
|
debug.log('release-loop.readiness', 'ready', { version });
|
|
47
|
+
try {
|
|
48
|
+
const advice = (deps.advice ?? adviseLaunch)({ pool: deps.pool?.(), caller: 'release-run' });
|
|
49
|
+
const { kind } = compareLaunchAdvice(advice, 'launched');
|
|
50
|
+
debug.log('resource.advice', 'launch-advice', { caller: 'release-run', verdict: advice.verdict, why: advice.why, actual: 'launched', kind, version });
|
|
51
|
+
} catch {
|
|
52
|
+
// Shadow only: a throwing advice seam must never affect the launch decision or result.
|
|
53
|
+
}
|
|
43
54
|
return { skipped: false, result: await deps.run() };
|
|
44
55
|
} finally {
|
|
45
56
|
closeSync(fd);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
import { TRAFFIC_SEATS, type TrafficResult } from '../loops/orchestrator/traffic.js';
|
|
4
|
+
import { observeLoopResources } from '../nexus/api/loop-resources.js';
|
|
5
|
+
import { writeStdoutJson } from './stdout-json.js';
|
|
6
|
+
|
|
7
|
+
/** 칸 제목은 여러 줄(«대상 경로:»·«신설:» …)이다 — 표의 한 칸에는 첫 줄만, 상한을 넘으면 «…» 로 자른 것을 표시한다. */
|
|
8
|
+
export const RESOURCE_TITLE_MAX_CHARS = 60;
|
|
9
|
+
export function oneLineTitle(title: string): string {
|
|
10
|
+
const first = (title.split(/\r?\n/).find((line) => line.trim()) ?? '').replace(/\s+/g, ' ').trim();
|
|
11
|
+
return first.length > RESOURCE_TITLE_MAX_CHARS ? `${first.slice(0, RESOURCE_TITLE_MAX_CHARS - 1)}…` : first;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Read-only CLI view of the same traffic snapshot returned by the Nexus resource GET. */
|
|
15
|
+
export function registerResourceCommands(program: Command, observe: () => TrafficResult = observeLoopResources): void {
|
|
16
|
+
program.command('resource').description('자리별 루프 자원 관측 (읽기 전용)')
|
|
17
|
+
.command('status').description('자리별 공급·다음 칸·임대 상태')
|
|
18
|
+
.option('--json', '관측 스냅샷 JSON 출력')
|
|
19
|
+
.action(async (opts: { json?: boolean }) => {
|
|
20
|
+
let resource: TrafficResult;
|
|
21
|
+
try { resource = observe(); }
|
|
22
|
+
catch (error) {
|
|
23
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
24
|
+
debug.log('resource.loop', 'status-read', { readStatus: 'unreadable', seats: null, cells: null });
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
if (opts.json) await writeStdoutJson(JSON.stringify({ readStatus: 'unreadable', reason }) + '\n');
|
|
27
|
+
else console.error(`resource status: 못 읽음 — ${reason}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
debug.log('resource.loop', 'status-read', {
|
|
31
|
+
readStatus: 'ok', seats: resource.seats.length,
|
|
32
|
+
cells: resource.seats.filter(row => row.nextCell !== null).length,
|
|
33
|
+
});
|
|
34
|
+
if (opts.json) {
|
|
35
|
+
await writeStdoutJson(JSON.stringify({ resource, readStatus: 'ok' }) + '\n');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
console.log('자리\t쓰는 자리/공급\t다음 칸\t임대(빌림/빌려줌)\t대기 이유');
|
|
39
|
+
for (const seat of TRAFFIC_SEATS) {
|
|
40
|
+
const row = resource.seats.find(item => item.seat === seat);
|
|
41
|
+
if (!row) { console.log(`${seat}\t못 읽음\t못 읽음\t못 읽음\t자리 관측 없음`); continue; }
|
|
42
|
+
const cell = row.nextCell;
|
|
43
|
+
const reason = !cell ? '다음 칸 없음' : row.launchCap <= row.running ? '발사 자리 없음' : '다음 칸 대기';
|
|
44
|
+
console.log(`${seat}\t${row.running}/${row.cap}\t${cell ? `1 · ${cell.id} ${oneLineTitle(cell.title)}` : '0'}\t${row.borrowed}/${row.lent}\t${reason}`);
|
|
45
|
+
}
|
|
46
|
+
if (resource.unassigned > 0) console.log(`미배정\t${resource.unassigned}`);
|
|
47
|
+
});
|
|
48
|
+
}
|
package/src/cli/retro-cli.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import type { Command } from 'commander';
|
|
3
|
+
import { readRunExits } from '../harness/harness-incidents.js';
|
|
4
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
3
5
|
import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
|
|
4
6
|
|
|
5
|
-
type RetroFact = { store: string; at: string; category: string; event: string; kind: 'draft-birth' | 'draft-death' | 'stop-reason' | 'ta-outcome'; data: unknown };
|
|
7
|
+
type RetroFact = { store: string; at: string; category: string; event: string; kind: 'draft-birth' | 'draft-death' | 'stop-reason' | 'ta-outcome' | 'incident'; data: unknown };
|
|
6
8
|
|
|
7
9
|
const FACT_EVENTS = new Map<string, RetroFact['kind']>([
|
|
8
10
|
['rework-blocked-draft-pr', 'draft-birth'],
|
|
@@ -21,7 +23,7 @@ export function parseRetroSince(value: string, now = Date.now()): number {
|
|
|
21
23
|
return now - duration;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
export function collectRetroFacts(sinceMs: number, targets: readonly { name: string; dbPath: string }[] = [{ name: 'current', dbPath: logsDbPath() }]): { facts: RetroFact[]; unavailable: string[] } {
|
|
26
|
+
export function collectRetroFacts(sinceMs: number, targets: readonly { name: string; dbPath: string }[] = [{ name: 'current', dbPath: logsDbPath() }], incidentRoot?: string): { facts: RetroFact[]; unavailable: string[] } {
|
|
25
27
|
const facts: RetroFact[] = [];
|
|
26
28
|
const unavailable: string[] = [];
|
|
27
29
|
const untilMs = Date.now();
|
|
@@ -53,13 +55,20 @@ export function collectRetroFacts(sinceMs: number, targets: readonly { name: str
|
|
|
53
55
|
} finally { store.close(); }
|
|
54
56
|
} catch { unavailable.push(target.name); }
|
|
55
57
|
}
|
|
58
|
+
try {
|
|
59
|
+
for (const row of readRunExits(incidentRoot ?? effectiveInstanceRoot())) {
|
|
60
|
+
if (Date.parse(row.at) < sinceMs) continue;
|
|
61
|
+
facts.push({ store: 'incidents', at: row.at, category: 'harness.incident', event: row.reason, kind: 'incident',
|
|
62
|
+
data: { runId: row.runId, seat: row.seat, entrance: row.entrance } });
|
|
63
|
+
}
|
|
64
|
+
} catch { unavailable.push('incidents'); }
|
|
56
65
|
facts.sort((a, b) => b.at.localeCompare(a.at));
|
|
57
66
|
return { facts, unavailable };
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
export function registerRetroCommands(program: Command): void {
|
|
61
70
|
program.command('retro').description('Read-only retrospective facts from existing logs')
|
|
62
|
-
.command('facts').description('Draft births/deaths, stop reasons
|
|
71
|
+
.command('facts').description('Draft births/deaths, stop reasons, task-agent outcomes and run incidents')
|
|
63
72
|
.option('--since <duration>', 'Lookback duration', '24h')
|
|
64
73
|
.option('--json', 'JSON output')
|
|
65
74
|
.action((opts: { since: string; json?: boolean }) => {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
5
|
+
import { redactSecretText } from '../debug/log.js';
|
|
6
|
+
import { defaultMsgStorePath, readUnreadCount } from '../msg/msg-store.js';
|
|
7
|
+
|
|
8
|
+
export const SEAT_ROLES = ['OP', 'TC', 'MK', 'UX'] as const;
|
|
9
|
+
export type SeatRole = typeof SEAT_ROLES[number];
|
|
10
|
+
|
|
11
|
+
const MAX_FIELD = 160;
|
|
12
|
+
const MAX_ROWS = 12;
|
|
13
|
+
const clean = (value: unknown): string => redactSecretText(String(value ?? '').replace(/[\r\n\t]+/g, ' ').trim()).slice(0, MAX_FIELD);
|
|
14
|
+
const safeObject = (value: unknown, keys: readonly string[]): Record<string, string> => {
|
|
15
|
+
const source = value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
16
|
+
return Object.fromEntries(keys.filter(key => source[key] !== undefined && source[key] !== null).map(key => [key, clean(source[key])]));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function isRegularSeatPath(home: string, root: string, path: string): boolean {
|
|
20
|
+
const suffix = relative(root, path);
|
|
21
|
+
if (!suffix || suffix === '..' || suffix.startsWith(`..${sep}`) || suffix.startsWith(sep)) return false;
|
|
22
|
+
if (!lstatSync(home).isDirectory()) return false;
|
|
23
|
+
let parent = home;
|
|
24
|
+
for (const part of relative(home, dirname(path)).split(sep).filter(Boolean)) {
|
|
25
|
+
parent = join(parent, part);
|
|
26
|
+
if (!lstatSync(parent).isDirectory()) return false;
|
|
27
|
+
}
|
|
28
|
+
return lstatSync(path).isFile();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function metadata(home: string, root: string, path: string, kind: 'markdown' | 'tsv' | 'memory'): { source: string; updated: string; rows: string[]; reason?: string } {
|
|
32
|
+
if (!existsSync(path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 파일 없음' };
|
|
33
|
+
try {
|
|
34
|
+
if (!isRegularSeatPath(home, root, path)) return { source: path, updated: '미상', rows: [], reason: '미관측: 일반 경로가 아님' };
|
|
35
|
+
const updated = statSync(path).mtime.toISOString();
|
|
36
|
+
const text = readFileSync(path, 'utf8').slice(0, 256_000);
|
|
37
|
+
let rows: string[] = [];
|
|
38
|
+
if (kind === 'tsv') {
|
|
39
|
+
const headers = (text.split(/\r?\n/, 1)[0] ?? '').split('\t');
|
|
40
|
+
const allowed = kind === 'tsv' && path.endsWith('harvest-claims.tsv') ? ['pr', 'claimer', 'at', 'status'] : ['at', 'what', 'then'];
|
|
41
|
+
const indexes = allowed.map(key => headers.indexOf(key));
|
|
42
|
+
rows = text.split(/\r?\n/).slice(1).filter(Boolean).slice(0, MAX_ROWS).map(line => {
|
|
43
|
+
const cells = line.split('\t');
|
|
44
|
+
return allowed.map((key, i) => indexes[i] < 0 ? '' : `${key}=${clean(cells[indexes[i]])}`).filter(Boolean).join(' · ');
|
|
45
|
+
}).filter(Boolean);
|
|
46
|
+
} else if (kind === 'memory') {
|
|
47
|
+
rows = text.split(/\r?\n/).filter(line => /^#{1,6}\s/.test(line)).slice(0, MAX_ROWS).map(line => clean(line.replace(/^#+\s*/, '')));
|
|
48
|
+
} else {
|
|
49
|
+
rows = text.split(/\r?\n/).filter(line => (/^#{1,6}\s/.test(line) || /^(?:[-*]\s*)?(?:from|발신|시각|at)\s*[::]/i.test(line)) && !/[`$;|<>]/.test(line)).slice(0, MAX_ROWS).map(line => {
|
|
50
|
+
const from = line.match(/^(?:[-*]\s*)?(?:from|발신)\s*[::]\s*(OP|TC|MK|UX)\b/i);
|
|
51
|
+
if (/^(?:[-*]\s*)?(?:from|발신)\s*[::]/i.test(line)) return from ? `From: ${from[1]!.toUpperCase()}` : '';
|
|
52
|
+
return clean(line.replace(/^#{1,6}\s*/, ''));
|
|
53
|
+
}).filter(Boolean);
|
|
54
|
+
}
|
|
55
|
+
return { source: path, updated, rows, ...(rows.length ? {} : { reason: '미관측: 허용된 메타데이터 없음' }) };
|
|
56
|
+
} catch {
|
|
57
|
+
return { source: path, updated: '미상', rows: [], reason: '미관측: 읽기 실패' };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function contextFacts(snapshot: unknown): string[] {
|
|
62
|
+
const root = snapshot !== null && typeof snapshot === 'object' && !Array.isArray(snapshot) ? snapshot as Record<string, unknown> : {};
|
|
63
|
+
const facts: string[] = [];
|
|
64
|
+
const sourceFacts = Array.isArray(root.facts) ? root.facts as unknown[] : [];
|
|
65
|
+
for (const item of sourceFacts.slice(0, MAX_ROWS)) {
|
|
66
|
+
const value = item !== null && typeof item === 'object' && !Array.isArray(item) ? item as Record<string, unknown> : {};
|
|
67
|
+
const keys = value.kind === 'cell' ? ['id', 'status', 'owner', 'version', 'source']
|
|
68
|
+
: value.kind === 'seat' ? ['seat', 'at', 'status', 'id', 'source']
|
|
69
|
+
: value.kind === 'run' ? ['phase', 'elapsed', 'source'] : [];
|
|
70
|
+
const values = safeObject(value, keys);
|
|
71
|
+
if (Object.keys(values).length) facts.push(`${clean(value.kind)}: ${Object.entries(values).map(([k, v]) => `${k}=${v}`).join(' · ')}`);
|
|
72
|
+
}
|
|
73
|
+
const sourceEvents = Array.isArray(root.events) ? root.events as unknown[] : [];
|
|
74
|
+
for (const item of sourceEvents.slice(0, MAX_ROWS)) {
|
|
75
|
+
const values = safeObject(item, ['at', 'kind', 'source', 'summary']);
|
|
76
|
+
if (Object.keys(values).length) facts.push(`event: ${Object.entries(values).map(([k, v]) => `${k}=${v}`).join(' · ')}`);
|
|
77
|
+
}
|
|
78
|
+
return facts.slice(0, MAX_ROWS);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function renderSeatBootCard(seat: SeatRole, sections: ReadonlyArray<{ title: string; source: string; updated: string; rows: readonly string[]; reason?: string }>, facts: readonly string[], contextUpdated = '미상'): string {
|
|
82
|
+
const out = [`# ${seat} 자리 부팅 카드`, '', '## 현재 구조화 관측', '출처: elanous://context-now', `갱신: ${clean(contextUpdated)}`, ...(facts.length ? facts.map(row => `- ${clean(row)}`) : ['- 미관측: contextNow 구조화 facts/events 없음'])];
|
|
83
|
+
for (const section of sections) out.push('', `## ${section.title}`, `출처: ${clean(section.source)}`, `갱신: ${clean(section.updated)}`, ...(section.rows.length ? section.rows.map(row => `- ${clean(row)}`) : [`- ${clean(section.reason ?? '미관측')}`]));
|
|
84
|
+
return out.join('\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function registerSeatBootCommands(command: Command, options: { home?: () => string; contextNow?: () => unknown; msgPath?: () => string } = {}): void {
|
|
88
|
+
command.command('boot <seat>').description('현재 자리 카드 — 허용된 메타데이터만 읽기 전용 표시')
|
|
89
|
+
.action(async (rawSeat: string) => {
|
|
90
|
+
const seat = rawSeat.toUpperCase();
|
|
91
|
+
if (!(SEAT_ROLES as readonly string[]).includes(seat)) { console.error(`seat boot: unknown seat ${rawSeat} (OP|TC|MK|UX)`); process.exitCode = 2; return; }
|
|
92
|
+
const home = options.home?.() ?? homedir();
|
|
93
|
+
const root = join(home, 'elanous-hq', 'seat-state');
|
|
94
|
+
let facts: string[] = [];
|
|
95
|
+
let contextUpdated = '미상';
|
|
96
|
+
try {
|
|
97
|
+
const snapshot = options.contextNow ? options.contextNow() : await (async () => {
|
|
98
|
+
const mod = await import('../context-bus/context-now.js');
|
|
99
|
+
return (mod.contextNow as unknown as (options: { audience: string }) => unknown)({ audience: 'operator' });
|
|
100
|
+
})();
|
|
101
|
+
const context = snapshot !== null && typeof snapshot === 'object' ? snapshot as Record<string, unknown> : {};
|
|
102
|
+
contextUpdated = typeof context.at === 'string' ? clean(context.at) : '시각 미관측';
|
|
103
|
+
facts = contextFacts(snapshot);
|
|
104
|
+
} catch { facts = []; contextUpdated = '미관측: contextNow 조회 실패'; }
|
|
105
|
+
const seatDir = join(root, seat);
|
|
106
|
+
const msgPath = options.msgPath?.() ?? defaultMsgStorePath();
|
|
107
|
+
let unread: number | null = null;
|
|
108
|
+
try { unread = readUnreadCount(seat, msgPath); }
|
|
109
|
+
catch { /* unavailable is not a measured zero */ }
|
|
110
|
+
const sections = [
|
|
111
|
+
{ title: 'msg 원장', source: msgPath, updated: unread === null ? '미상' : new Date().toISOString(), rows: [`안 읽은 msg ${unread ?? '미관측'} (${seat})`] },
|
|
112
|
+
{ title: 'HANDOFF', ...metadata(home, root, join(seatDir, 'HANDOFF.md'), 'markdown') },
|
|
113
|
+
{ title: 'inbox', ...metadata(home, root, join(seatDir, 'inbox.md'), 'markdown') },
|
|
114
|
+
{ title: '수확 주장', ...metadata(home, root, join(seatDir, 'harvest-claims.tsv'), 'tsv') },
|
|
115
|
+
{ title: '예약', ...metadata(home, root, join(seatDir, 'scheduled.tsv'), 'tsv') },
|
|
116
|
+
{ title: '공통 메모리 색인', ...metadata(home, root, join(root, 'memory', 'MEMORY.md'), 'memory') },
|
|
117
|
+
];
|
|
118
|
+
console.log(renderSeatBootCard(seat as SeatRole, sections, facts, contextUpdated));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
@@ -2,6 +2,7 @@ import type { Command } from 'commander';
|
|
|
2
2
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
3
3
|
import { hqCliWriteAllowed, type HqDeps } from '../hq/hq.js';
|
|
4
4
|
import { isIsolatedLedgerWriteRoot } from '../hq/ledger-write-target.js';
|
|
5
|
+
import { appendDuty, listDuties, type DutyStatus } from '../seat-loop/duty-ledger.js';
|
|
5
6
|
import { closeSeatRequests, listSeatRequests, type SeatRequestStatus } from '../seat-dispatch/seat-request-ledger.js';
|
|
6
7
|
|
|
7
8
|
function duration(value: string): number {
|
|
@@ -49,4 +50,28 @@ export function registerSeatRequestsCommands(seat: Command, deps: { root?: () =>
|
|
|
49
50
|
for (const row of rows) console.log(`${opts.dryRun ? 'would close' : 'closed'} ${row.key} ${row.status}: ${row.reason}`);
|
|
50
51
|
} catch (error) { console.error(`seat requests close: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
51
52
|
});
|
|
53
|
+
const duty = seat.command('duty').description('자리 임무 원장 기록·조회');
|
|
54
|
+
duty.command('add <seat> <duty>').description('임무 한 줄을 원장에 덧붙임')
|
|
55
|
+
.requiredOption('--source <source>', '임무의 출처')
|
|
56
|
+
.option('--ref <ref>', '근거 참조')
|
|
57
|
+
.option('--status <status>', 'standing|done|missed', 'standing')
|
|
58
|
+
.action((seatId: string, dutyText: string, opts: { source: string; ref?: string; status: string }) => {
|
|
59
|
+
try {
|
|
60
|
+
const row = appendDuty((deps.root ?? effectiveInstanceRoot)(), {
|
|
61
|
+
seat: seatId, duty: dutyText, source: opts.source, status: opts.status as DutyStatus,
|
|
62
|
+
...(opts.ref === undefined ? {} : { ref: opts.ref }),
|
|
63
|
+
}, deps.now);
|
|
64
|
+
console.log(`added ${row.seat} ${row.status}: ${row.duty}`);
|
|
65
|
+
} catch (error) { console.error(`seat duty add: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
66
|
+
});
|
|
67
|
+
duty.command('ls').description('임무 원장 조회 (at 순서)')
|
|
68
|
+
.option('--seat <seat>', '자리 ID')
|
|
69
|
+
.option('--json', 'JSON 출력')
|
|
70
|
+
.action((opts: { seat?: string; json?: boolean }) => {
|
|
71
|
+
try {
|
|
72
|
+
const rows = listDuties((deps.root ?? effectiveInstanceRoot)(), { seat: opts.seat });
|
|
73
|
+
if (opts.json) console.log(JSON.stringify(rows));
|
|
74
|
+
else for (const row of rows) console.log(`${row.at} ${row.seat} ${row.status} ${row.duty} (${row.source}${row.ref ? ` ${row.ref}` : ''})`);
|
|
75
|
+
} catch (error) { console.error(`seat duty ls: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
76
|
+
});
|
|
52
77
|
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { Database } from 'bun:sqlite';
|
|
3
|
+
import { redactSecretText } from '../debug/log.js';
|
|
4
|
+
import { openSurfaceEventsDb, querySurfaceUtterances, surfaceEventsDbPath, type SurfaceEventRow } from '../domains/surface-events.js';
|
|
5
|
+
import { injectUtterance, type UtteranceInput } from '../domains/self-awareness.js';
|
|
6
|
+
import { writeStdoutJson } from './stdout-json.js';
|
|
7
|
+
|
|
8
|
+
const PAGE_SIZE = 50;
|
|
9
|
+
type UtteranceOrigin = 'human' | 'agent' | 'unknown';
|
|
10
|
+
|
|
11
|
+
function refsOf(raw: string | null): Record<string, unknown> {
|
|
12
|
+
if (!raw) return {};
|
|
13
|
+
try {
|
|
14
|
+
const value: unknown = JSON.parse(raw);
|
|
15
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
16
|
+
} catch { return {}; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function redact(value: string): string {
|
|
20
|
+
return redactSecretText(value)
|
|
21
|
+
.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '[REDACTED_EMAIL]')
|
|
22
|
+
.replace(/(https?:\/\/[^\s?#]+)\?[^\s#]*/gi, '$1?[REDACTED_QUERY]');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isAutomatic(row: SurfaceEventRow): boolean {
|
|
26
|
+
const refs = refsOf(row.refs);
|
|
27
|
+
if (row.surface === 'coord:channel' || row.surface === 'coord:seat' || refs.origin === 'coord:channel') return true;
|
|
28
|
+
const seatSource = typeof refs.origin === 'string' && /^(?:seat|seat-notice|notification|wake|coord:seat)$/i.test(refs.origin);
|
|
29
|
+
if (seatSource) return true;
|
|
30
|
+
if (refs.origin === 'observer' || refs.origin === 'observer-generated' || /observer-generated/i.test(row.tags ?? '')) return true;
|
|
31
|
+
if (row.kind === 'qna' && /^(?:telegram|discord)$/i.test(row.surface)) return false;
|
|
32
|
+
if (refs.origin === 'human' || refs.origin === 'user') return false;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function originOf(row: SurfaceEventRow): UtteranceOrigin {
|
|
37
|
+
if (row.direction !== 'inbound') return 'unknown';
|
|
38
|
+
const refs = refsOf(row.refs);
|
|
39
|
+
if (refs.utteranceOrigin === 'human' || refs.utteranceOrigin === 'agent') return refs.utteranceOrigin;
|
|
40
|
+
const explicit = refs.origin;
|
|
41
|
+
if (typeof explicit === 'string') {
|
|
42
|
+
if (/^(?:human|user|tui|pwa|telegram|discord|cli)$/i.test(explicit)) return 'human';
|
|
43
|
+
if (/^(?:claude-code|codex|gemini|agent|external:)/i.test(explicit)) return 'agent';
|
|
44
|
+
}
|
|
45
|
+
// recordInboundTurn marks its recorder as elanous-self; on chat Q&A the speaker is the human.
|
|
46
|
+
if (row.kind === 'qna' && /^(?:telegram|discord)$/i.test(row.surface)) return 'human';
|
|
47
|
+
if (explicit === 'elanous-self') return 'agent';
|
|
48
|
+
if (/^ext:/i.test(row.surface)) return 'agent';
|
|
49
|
+
if (/^(?:cli|tui|pwa|telegram|discord|ipad|watch)$/i.test(row.surface)) return 'human';
|
|
50
|
+
return 'unknown';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function utteranceText(row: SurfaceEventRow): { text: string; extract: 'direct' | 'qna' | 'ambiguous' | 'summary'; truncated: boolean; truncationEvidence: 'cap-reached' | 'over-cap' | null; possibleLoss: boolean } {
|
|
54
|
+
if (row.kind !== 'qna') return { text: row.text, extract: 'direct', truncated: false, truncationEvidence: null, possibleLoss: false };
|
|
55
|
+
const firstAnswer = row.text.startsWith('Q: ') ? row.text.indexOf('\nA: ', 3) : -1;
|
|
56
|
+
if (firstAnswer >= 0) {
|
|
57
|
+
const ambiguous = row.text.indexOf('\nQ: ', 3) >= 0 || row.text.indexOf('\nA: ', firstAnswer + 4) >= 0;
|
|
58
|
+
return { text: row.text.slice(3, firstAnswer), extract: ambiguous ? 'ambiguous' : 'qna', truncated: false, truncationEvidence: null, possibleLoss: ambiguous };
|
|
59
|
+
}
|
|
60
|
+
const summary = row.summary ?? '';
|
|
61
|
+
return { text: summary.slice(0, 150), extract: 'summary', truncated: summary.length > 150, truncationEvidence: summary.length > 150 ? 'over-cap' : summary.length === 150 ? 'cap-reached' : null, possibleLoss: false };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function validDate(value: string, name: string): string {
|
|
65
|
+
const date = new Date(value);
|
|
66
|
+
if (!value || !Number.isFinite(date.getTime()) || !/^\d{4}-\d\d-\d\d(?:T.*)?$/.test(value)) throw new Error(`--${name} must be a valid ISO date/time`);
|
|
67
|
+
return date.toISOString();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface SelfUtterancesOptions {
|
|
71
|
+
from: string; to: string; surface?: string; origin?: UtteranceOrigin; page?: string; json?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function collectSelfUtterances(opts: SelfUtterancesOptions, db: ReturnType<typeof openSurfaceEventsDb>) {
|
|
75
|
+
const from = validDate(opts.from, 'from');
|
|
76
|
+
const to = validDate(opts.to, 'to');
|
|
77
|
+
if (from >= to) throw new Error('--from must be earlier than --to');
|
|
78
|
+
const page = opts.page === undefined ? 1 : Number(opts.page);
|
|
79
|
+
if (!Number.isSafeInteger(page) || page < 1) throw new Error('--page must be a positive integer');
|
|
80
|
+
const rows = querySurfaceUtterances(db, { from, to, ...(opts.surface ? { surface: opts.surface } : {}) });
|
|
81
|
+
let excludedAutomatic = 0;
|
|
82
|
+
let excludedByOrigin = 0;
|
|
83
|
+
let ambiguous = 0;
|
|
84
|
+
let truncated = 0;
|
|
85
|
+
let capReached = 0;
|
|
86
|
+
let possibleLoss = 0;
|
|
87
|
+
let excludedUnextractable = 0;
|
|
88
|
+
const utterances = rows.flatMap((row) => {
|
|
89
|
+
if (isAutomatic(row)) { excludedAutomatic += 1; return []; }
|
|
90
|
+
const origin = originOf(row);
|
|
91
|
+
if (opts.origin && origin !== opts.origin) { excludedByOrigin += 1; return []; }
|
|
92
|
+
const refs = refsOf(row.refs);
|
|
93
|
+
const cwd = typeof refs.cwd === 'string' && refs.cwd.length > 0 && !/[\u0000-\u001f\u007f]/.test(refs.cwd) ? redact(refs.cwd) : null;
|
|
94
|
+
const extracted = utteranceText(row);
|
|
95
|
+
if (row.kind === 'qna' && extracted.text.trim() === '') { excludedUnextractable += 1; return []; }
|
|
96
|
+
if (extracted.extract === 'ambiguous') ambiguous += 1;
|
|
97
|
+
if (extracted.truncated) truncated += 1;
|
|
98
|
+
if (extracted.truncationEvidence === 'cap-reached') capReached += 1;
|
|
99
|
+
if (extracted.possibleLoss) possibleLoss += 1;
|
|
100
|
+
return [{ id: redact(row.id), ts: redact(row.ts), surface: redact(row.surface), session: row.session_id ? redact(row.session_id) : null, cwd, origin, source: typeof refs.origin === 'string' ? redact(refs.origin) : 'unrecorded', text: redact(extracted.text), extract: extracted.extract, truncated: extracted.truncated, truncationEvidence: extracted.truncationEvidence, possibleLoss: extracted.possibleLoss }];
|
|
101
|
+
});
|
|
102
|
+
const total = utterances.length;
|
|
103
|
+
const start = (page - 1) * PAGE_SIZE;
|
|
104
|
+
return { source: 'surface_events.events (read-only)', filters: { from, to, surface: opts.surface ?? null, origin: opts.origin ?? null, automatic: 'excluded' }, counts: { matched: total, excludedAutomatic, excludedByOrigin, excludedUnextractable, ambiguous, truncated, capReached, possibleLoss }, page: { number: page, size: PAGE_SIZE, total, hasNext: start + PAGE_SIZE < total }, utterances: utterances.slice(start, start + PAGE_SIZE) };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function recordSelfUtterance(input: UtteranceInput & { utteranceOrigin?: 'human' | 'agent' }, db?: Database): { eventId: string } {
|
|
108
|
+
const store = db ?? openSurfaceEventsDb();
|
|
109
|
+
try {
|
|
110
|
+
const result = injectUtterance(input, store);
|
|
111
|
+
if (input.utteranceOrigin === 'human') {
|
|
112
|
+
store.prepare("UPDATE events SET refs = json_set(refs, '$.utteranceOrigin', 'human') WHERE id = ?").run(result.eventId);
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
} finally { if (!db) store.close(); }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function registerSelfUtterancesCommand(selfCmd: Command): void {
|
|
119
|
+
selfCmd.command('utterances').description('Read paginated original utterances from surface_events (read-only)')
|
|
120
|
+
.requiredOption('--from <ISO>', 'Inclusive ISO date/time')
|
|
121
|
+
.requiredOption('--to <ISO>', 'Exclusive ISO date/time')
|
|
122
|
+
.option('--surface <surface>', 'Filter by surface')
|
|
123
|
+
.option('--origin <origin>', 'Filter by known origin: human|agent')
|
|
124
|
+
.option('--page <page>', 'One-based page number', '1')
|
|
125
|
+
.option('--json', 'Emit JSON')
|
|
126
|
+
.action(async (opts: SelfUtterancesOptions) => {
|
|
127
|
+
if (opts.origin && opts.origin !== 'human' && opts.origin !== 'agent') throw new Error('--origin must be human or agent');
|
|
128
|
+
const db = new Database(surfaceEventsDbPath(), { readonly: true });
|
|
129
|
+
try {
|
|
130
|
+
const result = collectSelfUtterances(opts, db);
|
|
131
|
+
if (opts.json) { await writeStdoutJson(JSON.stringify(result, null, 2) + '\n'); return; }
|
|
132
|
+
console.log(`source=${result.source} matched=${result.counts.matched} excludedAutomatic=${result.counts.excludedAutomatic} excludedByOrigin=${result.counts.excludedByOrigin} excludedUnextractable=${result.counts.excludedUnextractable} page=${result.page.number} size=${result.page.size} hasNext=${result.page.hasNext}`);
|
|
133
|
+
console.log(`filters=${JSON.stringify(result.filters)}`);
|
|
134
|
+
for (const item of result.utterances) console.log(JSON.stringify(item));
|
|
135
|
+
console.log(`ambiguous=${result.counts.ambiguous} truncated=${result.counts.truncated} cap-reached=${result.counts.capReached} possibleLoss=${result.counts.possibleLoss}`);
|
|
136
|
+
} finally { db.close(); }
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export { PAGE_SIZE };
|