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
|
@@ -10,9 +10,11 @@ export interface Project {
|
|
|
10
10
|
name: string;
|
|
11
11
|
primaryFolder?: string;
|
|
12
12
|
createdAt: string;
|
|
13
|
+
relations?: Array<{ type: 'dependsOn' | 'derivedFrom' | 'partOf' | 'deploysTo'; target: string }>;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const PROJECT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
17
|
+
const RELATION_TYPES = new Set(['dependsOn', 'derivedFrom', 'partOf', 'deploysTo']);
|
|
16
18
|
|
|
17
19
|
function validId(id: unknown): id is string {
|
|
18
20
|
return typeof id === 'string' && PROJECT_ID.test(id);
|
|
@@ -26,9 +28,27 @@ function validateProject(value: unknown): Project {
|
|
|
26
28
|
|| (item.primaryFolder !== undefined && (typeof item.primaryFolder !== 'string' || !isAbsolute(item.primaryFolder)))) {
|
|
27
29
|
throw new Error('invalid project record');
|
|
28
30
|
}
|
|
31
|
+
if (item.relations !== undefined) {
|
|
32
|
+
if (!Array.isArray(item.relations)) throw new Error('invalid project record');
|
|
33
|
+
const seen = new Set<string>();
|
|
34
|
+
for (const rel of item.relations) {
|
|
35
|
+
if (!rel || typeof rel !== 'object' || Array.isArray(rel)) throw new Error('invalid project record');
|
|
36
|
+
const edge = rel as Record<string, unknown>;
|
|
37
|
+
if (!RELATION_TYPES.has(edge.type as string) || !validId(edge.target) || edge.target === item.id) {
|
|
38
|
+
throw new Error('invalid project record');
|
|
39
|
+
}
|
|
40
|
+
const key = `${edge.type}\0${edge.target}`;
|
|
41
|
+
if (seen.has(key)) throw new Error('invalid project record');
|
|
42
|
+
seen.add(key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
29
45
|
return value as Project;
|
|
30
46
|
}
|
|
31
47
|
|
|
48
|
+
export function relationsOf(project: Project): Array<{ type: 'dependsOn' | 'derivedFrom' | 'partOf' | 'deploysTo'; target: string }> {
|
|
49
|
+
return project.relations ?? [];
|
|
50
|
+
}
|
|
51
|
+
|
|
32
52
|
export class ProjectStore {
|
|
33
53
|
readonly dir: string;
|
|
34
54
|
|
|
@@ -393,6 +393,8 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
393
393
|
let complication: string | undefined;
|
|
394
394
|
let decisionSignal: EnhanceResult['decisionSignal'];
|
|
395
395
|
let enhancedBy: 'llm' | 'fallback' = 'llm';
|
|
396
|
+
let fallbackReason: 'llm-error' | 'empty-reply' | 'unparsed' | 'none' = 'none';
|
|
397
|
+
let replyChars = 0;
|
|
396
398
|
const groundedFacts = opts.groundedFacts ?? [];
|
|
397
399
|
const wantsScqa = groundedFacts.length > 0;
|
|
398
400
|
|
|
@@ -439,6 +441,10 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
439
441
|
try { opts.onUsage?.(usage); } catch { /* usage observation must not change enhancement */ }
|
|
440
442
|
},
|
|
441
443
|
});
|
|
444
|
+
replyChars = rawOut.length;
|
|
445
|
+
if (rawOut.trim().length === 0) {
|
|
446
|
+
fallbackReason = 'empty-reply';
|
|
447
|
+
}
|
|
442
448
|
const parsed = parseEnhanceJson(rawOut);
|
|
443
449
|
if (parsed) {
|
|
444
450
|
goal = parsed.goal;
|
|
@@ -449,9 +455,11 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
449
455
|
complication = parsed.complication;
|
|
450
456
|
decisionSignal = parsed.decisionSignal;
|
|
451
457
|
} else {
|
|
458
|
+
fallbackReason = fallbackReason === 'empty-reply' ? 'empty-reply' : 'unparsed';
|
|
452
459
|
enhancedBy = 'fallback';
|
|
453
460
|
}
|
|
454
461
|
} catch (e) {
|
|
462
|
+
fallbackReason = 'llm-error';
|
|
455
463
|
debug.log('prompt-enhance', 'llm-error', { error: String((e as { message?: string })?.message ?? e).slice(0, 160) }, { level: 'error' });
|
|
456
464
|
enhancedBy = 'fallback';
|
|
457
465
|
}
|
|
@@ -461,6 +469,7 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
461
469
|
checklist = extractChecklistFallback(original);
|
|
462
470
|
checklistProvenance = checklist.map(() => 'unknown');
|
|
463
471
|
enhancedBy = 'fallback';
|
|
472
|
+
if (fallbackReason === 'none') fallbackReason = 'unparsed';
|
|
464
473
|
}
|
|
465
474
|
if (!constraints.length) {
|
|
466
475
|
constraints = [
|
|
@@ -515,6 +524,8 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
|
|
|
515
524
|
enhancedChars: enhanced.length,
|
|
516
525
|
checklist: checklist.length,
|
|
517
526
|
enhancedBy,
|
|
527
|
+
fallbackReason,
|
|
528
|
+
replyChars,
|
|
518
529
|
model,
|
|
519
530
|
verbatimPreserved,
|
|
520
531
|
// ⭐ 관측 — 「요약을 요구했나 / 받았나 / 옮겨 적어 버렸나」를 «다른 값»으로 남긴다.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
1
2
|
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
2
3
|
import { releaseReadiness, type ReleaseReadiness } from '../../scripts/release-loop/release-readiness.js';
|
|
3
4
|
import { listSchedules, type ReleaseSchedule } from './release-schedule.js';
|
|
@@ -21,7 +22,7 @@ export type AutoStartResult =
|
|
|
21
22
|
| { status: 'no-cut' }
|
|
22
23
|
| { status: 'planned'; version: string; cutAt: string }
|
|
23
24
|
| { status: 'skipped'; version: string; reason: AutoStartDeferral['reason'] }
|
|
24
|
-
| { status: 'started'; version: string; cutAt: string };
|
|
25
|
+
| { status: 'started'; version: string; cutAt: string; publishAt?: string };
|
|
25
26
|
|
|
26
27
|
export interface AutoStartOptions {
|
|
27
28
|
windowMinutes: number;
|
|
@@ -30,7 +31,7 @@ export interface AutoStartOptions {
|
|
|
30
31
|
ledgerRoot?: string;
|
|
31
32
|
schedules?: (root: string) => ReleaseSchedule[];
|
|
32
33
|
readiness?: (version: string, ledgerRoot: string, now: Date) => ReleaseReadiness;
|
|
33
|
-
launch?: (version: string) => void | AutoStartDeferral | Promise<void | AutoStartDeferral>;
|
|
34
|
+
launch?: (version: string, launchOptions?: { publishAt?: string }) => void | AutoStartDeferral | Promise<void | AutoStartDeferral>;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/** Select from the release schedule; the existing `release run --if-ready` owns the launch-time lock and guards. */
|
|
@@ -40,12 +41,13 @@ export async function autoStartScheduledRelease(options: AutoStartOptions): Prom
|
|
|
40
41
|
// Validate the window even when the ledger has no rows.
|
|
41
42
|
const schedule = selectScheduledCut((options.schedules ?? listSchedules)(root), now, options.windowMinutes);
|
|
42
43
|
if (!schedule) return { status: 'no-cut' };
|
|
43
|
-
const { version, cutAt } = schedule;
|
|
44
|
+
const { version, cutAt, publishAt } = schedule;
|
|
44
45
|
if (!options.apply) return { status: 'planned', version, cutAt };
|
|
45
46
|
const readiness = (options.readiness ?? ((v, ledgerRoot, at) => releaseReadiness(v, { ledgerRoot, now: () => at })))(version, root, now);
|
|
46
47
|
if (!readiness.ready) return { status: 'skipped', version, reason: readiness.reason };
|
|
47
48
|
if (!options.launch) throw new Error('auto-start apply requires a launch callback');
|
|
48
|
-
const launched = await options.launch(version);
|
|
49
|
+
const launched = await options.launch(version, publishAt != null ? { publishAt: publishAt } : {});
|
|
49
50
|
if (launched?.deferred) return { status: 'skipped', version, reason: launched.reason };
|
|
50
|
-
|
|
51
|
+
debug.log('release.schedule', 'auto-start', { version, cutAt, publishAt: publishAt ?? null });
|
|
52
|
+
return { status: 'started', version, cutAt, ...(publishAt != null ? { publishAt: publishAt } : {}) };
|
|
51
53
|
}
|
|
@@ -10,6 +10,8 @@ export type ChecklistDisposition = 'move' | 'known-issue' | 'block';
|
|
|
10
10
|
/** `screen` = a five-surface feature cell — its evidence carries a `짝:` line (MANUAL-five-surface-parity §A). `postpub` = measured after publication, outside the pre-publication gate. */
|
|
11
11
|
export type ChecklistKind = 'screen' | 'postpub';
|
|
12
12
|
const CHECKLIST_KINDS: readonly ChecklistKind[] = ['screen', 'postpub'];
|
|
13
|
+
export type ChecklistDispatchKind = 'code' | 'ops' | 'measure' | 'decision' | 'umbrella';
|
|
14
|
+
const CHECKLIST_DISPATCH_KINDS: readonly ChecklistDispatchKind[] = ['code', 'ops', 'measure', 'decision', 'umbrella'];
|
|
13
15
|
export interface ChecklistItem {
|
|
14
16
|
id: string;
|
|
15
17
|
title: string;
|
|
@@ -27,6 +29,8 @@ export interface ChecklistItem {
|
|
|
27
29
|
evidence?: string;
|
|
28
30
|
disposition?: ChecklistDisposition;
|
|
29
31
|
kind?: ChecklistKind;
|
|
32
|
+
/** Whether the seat dispatcher should launch a coding task. Missing in old rows means code. */
|
|
33
|
+
dispatchKind?: ChecklistDispatchKind;
|
|
30
34
|
updatedAt: string;
|
|
31
35
|
updatedBy: string;
|
|
32
36
|
}
|
|
@@ -102,6 +106,14 @@ export function statusChangesSince(history: readonly ChecklistHistory[], sinceIs
|
|
|
102
106
|
return history.filter((entry) => entry.field === 'status' && Date.parse(entry.at) >= since);
|
|
103
107
|
}
|
|
104
108
|
|
|
109
|
+
/** CELL-DEPENDS-ID: a predecessor must name a cell that exists in SOME version — this one (data.items) or any other (otherItems). */
|
|
110
|
+
function assertPredecessorsExist(predecessors: readonly string[] | undefined, data: Checklist, otherItems: (id: string) => store.ChecklistCollision[]): void {
|
|
111
|
+
for (const id of predecessors ?? []) {
|
|
112
|
+
if (data.items.some((item) => item.id === id) || otherItems(id).length) continue;
|
|
113
|
+
throw new CliUserError(`없는 선행 칸: ${JSON.stringify(id).slice(1, -1)}`, '어느 판에도 없는 id 다 — release checklist status --json 으로 칸 id 를 확인한다');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
function mutate(v: string, apply: (data: Checklist, otherItems: (id: string) => store.ChecklistCollision[]) => boolean): Checklist {
|
|
106
118
|
// addItem/setItem/claimItem/removeItem/seedFromRoadmap reach the generation-fenced ledger write here.
|
|
107
119
|
return decodeClaimHistory(store.mutate(v, store.releasedVersion(), devVersion(), apply));
|
|
@@ -114,6 +126,37 @@ function change(data: Checklist, id: string, field: string, from: unknown, to: u
|
|
|
114
126
|
|
|
115
127
|
const REPO_ROOT = join(import.meta.dir, '..', '..');
|
|
116
128
|
|
|
129
|
+
const PATH_TOKEN = /(?:^|[^A-Za-z0-9_.\/-])((?:(?:[A-Za-z0-9_.-]+\/)+)?[A-Za-z0-9_.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|json|md|yaml|yml|sh|py|css|html|toml|sql|rs|swift))(?![A-Za-z0-9_.\/-])/g;
|
|
130
|
+
function mentionedPaths(text: string): string[] {
|
|
131
|
+
return [...text.matchAll(PATH_TOKEN)].map((match) => match[1]!).filter((path) => !path.split('/').includes('..'));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Shadow check at checklist authorship. Callers supply the origin/main file probe and merged-PR file reader. */
|
|
135
|
+
export function inspectChecklistTargetPaths(input: {
|
|
136
|
+
title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind;
|
|
137
|
+
}, deps: { existsAtMain: (path: string) => boolean; mergedPrFiles?: (number: number) => readonly string[] }): {
|
|
138
|
+
targets: string[]; warnings: string[]; candidates: string[];
|
|
139
|
+
} {
|
|
140
|
+
const lines = input.title.split(/\r?\n/);
|
|
141
|
+
const first = /^대상 경로:\s*(.*)$/.exec(lines[0] ?? '');
|
|
142
|
+
const targets = first ? [...new Set(mentionedPaths(first[1]!))] : [];
|
|
143
|
+
const newFileDeclared = /^신설:\s*/.test(lines[1] ?? '');
|
|
144
|
+
const warnings: string[] = [];
|
|
145
|
+
if ((input.dispatchKind ?? 'code') === 'code') {
|
|
146
|
+
if (!first || !first[1]!.trim() || targets.length === 0) warnings.push('첫 줄 대상 경로가 없다');
|
|
147
|
+
for (const path of targets) if (!deps.existsAtMain(path) && !newFileDeclared) warnings.push(`${path}: origin/main에 없는 파일 · 신설: 둘째 줄 선언 필요`);
|
|
148
|
+
}
|
|
149
|
+
if (!warnings.length) return { targets, warnings, candidates: [] };
|
|
150
|
+
const sources = [input.title, input.evidence ?? '', ...(input.refs ?? [])].join('\n');
|
|
151
|
+
const candidates = [...new Set(mentionedPaths(sources).filter(deps.existsAtMain))];
|
|
152
|
+
for (const match of sources.matchAll(/(?:^|[^\d])#(\d{2,8})\b/g)) {
|
|
153
|
+
for (const path of deps.mergedPrFiles?.(Number(match[1])) ?? []) {
|
|
154
|
+
if (deps.existsAtMain(path) && !candidates.includes(path)) candidates.push(path);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { targets, warnings, candidates };
|
|
158
|
+
}
|
|
159
|
+
|
|
117
160
|
/** `--ref` 문서를 찾는 뿌리들 — 이 코드의 트리 ⊕ 지금 작업 디렉토리의 git 뿌리.
|
|
118
161
|
* ⭐ 설치본(`~/.local/share/elanous/current`)에는 `docs/` 가 없다 — 저장소 안에서 부른 설치본도 저장소 문서를 인용할 수 있게. */
|
|
119
162
|
export function refRoots(cwd = process.cwd()): string[] {
|
|
@@ -225,10 +268,11 @@ export function validateCeoLoad(input: { ceoMinutes?: number; ceoDate?: string }
|
|
|
225
268
|
if (input.ceoDate !== undefined && (!/^\d{4}-\d{2}-\d{2}$/.test(input.ceoDate) || !Number.isFinite(Date.parse(`${input.ceoDate}T00:00:00Z`)) || new Date(`${input.ceoDate}T00:00:00Z`).toISOString().slice(0, 10) !== input.ceoDate)) throw new CliUserError('대표 손 날짜는 YYYY-MM-DD 이어야 한다');
|
|
226
269
|
}
|
|
227
270
|
|
|
228
|
-
export function addItem(v: string, input: { id: string; title: string; refs?: string[]; owner?: string; kind?: ChecklistKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean }, options: { allowDuplicateId?: boolean } = {}): Checklist {
|
|
271
|
+
export function addItem(v: string, input: { id: string; title: string; refs?: string[]; owner?: string; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean }, options: { allowDuplicateId?: boolean } = {}): Checklist {
|
|
229
272
|
if (!input.id.trim()) throw new CliUserError('칸 id 가 비었다');
|
|
230
273
|
if (!input.title.trim()) throw new CliUserError('칸 제목이 비었다');
|
|
231
274
|
if (input.kind !== undefined && !CHECKLIST_KINDS.includes(input.kind)) throw new CliUserError(`잘못된 종류: ${input.kind}`, 'screen|postpub');
|
|
275
|
+
if (input.dispatchKind !== undefined && !CHECKLIST_DISPATCH_KINDS.includes(input.dispatchKind)) throw new CliUserError(`잘못된 발사 종류: ${input.dispatchKind}`, 'code|ops|measure|decision|umbrella');
|
|
232
276
|
if (input.owner !== undefined) parseOwner(input.owner);
|
|
233
277
|
if (input.priority !== undefined && !['P0', 'P1', 'P2'].includes(input.priority)) throw new CliUserError(`잘못된 우선순위: ${input.priority}`);
|
|
234
278
|
if (input.predecessors !== undefined && (!Array.isArray(input.predecessors) || input.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === input.id))) throw new CliUserError('잘못된 선행 칸');
|
|
@@ -244,24 +288,27 @@ export function addItem(v: string, input: { id: string; title: string; refs?: st
|
|
|
244
288
|
console.error(`⚠ 중복 id: ${displayedId} — ${collisions.map((item) => `${item.version} · 담당 ${JSON.stringify(item.owner ?? '-').slice(1, -1)} · ${item.title.replace(/\s+/g, ' ').slice(0, 40)}`).join(' / ')}`);
|
|
245
289
|
if (!options.allowDuplicateId) throw new CliUserError(`다른 판에 이미 있는 칸: ${displayedId}`, '--allow-duplicate-id 로 허용');
|
|
246
290
|
}
|
|
291
|
+
assertPredecessorsExist(input.predecessors, data, otherItems);
|
|
247
292
|
const by = process.env.ELANOUS_TRACK || 'cli';
|
|
248
293
|
const at = new Date().toISOString();
|
|
249
|
-
const item: ChecklistItem = { id: input.id, title: input.title, status: 'yellow', ...(input.owner !== undefined ? { owner: input.owner } : {}), ...(input.kind !== undefined ? { kind: input.kind } : {}), ...(input.priority !== undefined ? { priority: input.priority } : {}), ...(input.predecessors !== undefined ? { predecessors: input.predecessors } : {}), ...(input.deadlineVersion !== undefined ? { deadlineVersion: input.deadlineVersion } : {}), ...(input.ceoMinutes !== undefined ? { ceoMinutes: input.ceoMinutes } : {}), ...(input.ceoDate !== undefined ? { ceoDate: input.ceoDate } : {}), ...(input.accelerator === true ? { accelerator: true as const } : {}), ...(refs ? { refs } : {}), updatedAt: at, updatedBy: by };
|
|
294
|
+
const item: ChecklistItem = { id: input.id, title: input.title, status: 'yellow', ...(input.owner !== undefined ? { owner: input.owner } : {}), ...(input.kind !== undefined ? { kind: input.kind } : {}), ...(input.dispatchKind !== undefined ? { dispatchKind: input.dispatchKind } : {}), ...(input.priority !== undefined ? { priority: input.priority } : {}), ...(input.predecessors !== undefined ? { predecessors: input.predecessors } : {}), ...(input.deadlineVersion !== undefined ? { deadlineVersion: input.deadlineVersion } : {}), ...(input.ceoMinutes !== undefined ? { ceoMinutes: input.ceoMinutes } : {}), ...(input.ceoDate !== undefined ? { ceoDate: input.ceoDate } : {}), ...(input.accelerator === true ? { accelerator: true as const } : {}), ...(refs ? { refs } : {}), updatedAt: at, updatedBy: by };
|
|
250
295
|
data.items.push(item);
|
|
251
296
|
change(data, item.id, 'add', null, item, by, at);
|
|
252
297
|
return true;
|
|
253
298
|
});
|
|
254
299
|
}
|
|
255
300
|
|
|
256
|
-
export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
|
|
257
|
-
return mutate(v, (data) => {
|
|
301
|
+
export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
|
|
302
|
+
return mutate(v, (data, otherItems) => {
|
|
258
303
|
const item = data.items.find((i) => i.id === id);
|
|
259
304
|
if (!item) throw new CliUserError(`없는 칸: ${id}`, 'list 로 칸 목록을 본다');
|
|
260
305
|
if (patch.status !== undefined && !['green', 'yellow', 'red', 'done'].includes(patch.status)) throw new CliUserError(`잘못된 상태: ${patch.status}`);
|
|
261
306
|
if (patch.disposition !== undefined && !['move', 'known-issue', 'block'].includes(patch.disposition)) throw new CliUserError(`잘못된 처분: ${patch.disposition}`);
|
|
262
307
|
if (patch.kind !== undefined && !CHECKLIST_KINDS.includes(patch.kind)) throw new CliUserError(`잘못된 종류: ${patch.kind}`, 'screen|postpub');
|
|
308
|
+
if (patch.dispatchKind !== undefined && !CHECKLIST_DISPATCH_KINDS.includes(patch.dispatchKind)) throw new CliUserError(`잘못된 발사 종류: ${patch.dispatchKind}`, 'code|ops|measure|decision|umbrella');
|
|
263
309
|
if (patch.priority !== undefined && !['P0', 'P1', 'P2'].includes(patch.priority)) throw new CliUserError(`잘못된 우선순위: ${patch.priority}`);
|
|
264
310
|
if (patch.predecessors !== undefined && (!Array.isArray(patch.predecessors) || patch.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === id))) throw new CliUserError('잘못된 선행 칸');
|
|
311
|
+
assertPredecessorsExist(patch.predecessors, data, otherItems);
|
|
265
312
|
if (patch.deadlineVersion !== undefined) store.validateVersion(patch.deadlineVersion);
|
|
266
313
|
if (patch.accelerator !== undefined && patch.accelerator !== true && patch.accelerator !== null) throw new CliUserError('가속 등급은 true(부여) 또는 null(해제)이다');
|
|
267
314
|
validateCeoLoad(patch);
|
|
@@ -273,7 +320,7 @@ export function setItem(v: string, id: string, patch: { status?: ChecklistStatus
|
|
|
273
320
|
throw new CliUserError(`지금 주인: ${item.owner} — --force 로만 바꾼다`, 'release checklist claim <id> --by <자리> --force');
|
|
274
321
|
}
|
|
275
322
|
}
|
|
276
|
-
const fields = (['evidence', 'owner', 'status', 'disposition', 'kind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
|
|
323
|
+
const fields = (['evidence', 'owner', 'status', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
|
|
277
324
|
if (fields.length === 0) return false;
|
|
278
325
|
const at = new Date().toISOString();
|
|
279
326
|
for (const field of fields) {
|
|
@@ -36,7 +36,7 @@ const walWait = new Int32Array(new SharedArrayBuffer(4));
|
|
|
36
36
|
const SCHEMA_COLUMNS: Record<string, readonly string[]> = {
|
|
37
37
|
imported_versions: ['json_hash', 'imported_at'],
|
|
38
38
|
events: ['reason', 'generation'],
|
|
39
|
-
assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs'],
|
|
39
|
+
assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs', 'dispatch_kind'],
|
|
40
40
|
release_schedules: ['freeze_from', 'freeze_until', 'publish_at'],
|
|
41
41
|
};
|
|
42
42
|
function schemaCurrent(db: Database): boolean {
|
|
@@ -81,7 +81,7 @@ function open(root = releaseLedgerRoot()): Database {
|
|
|
81
81
|
if (!eventColumns.some((column) => column.name === 'generation')) db.exec('ALTER TABLE events ADD COLUMN generation INTEGER');
|
|
82
82
|
db.exec('CREATE TABLE IF NOT EXISTS release_schedules (version TEXT PRIMARY KEY, cut_at TEXT NOT NULL, land_by TEXT, updated_at TEXT NOT NULL, updated_by TEXT NOT NULL)');
|
|
83
83
|
const assignmentColumns = db.query('PRAGMA table_info(assignments)').all() as Array<{ name: string }>;
|
|
84
|
-
for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT']] as const) {
|
|
84
|
+
for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT'], ['dispatch_kind', 'TEXT']] as const) {
|
|
85
85
|
if (!assignmentColumns.some((column) => column.name === name)) db.exec(`ALTER TABLE assignments ADD COLUMN ${name} ${sql}`);
|
|
86
86
|
}
|
|
87
87
|
const scheduleColumns = db.query('PRAGMA table_info(release_schedules)').all() as Array<{ name: string }>;
|
|
@@ -178,12 +178,13 @@ function evidenceRefs(db: Database, version: string, id: string): string[] {
|
|
|
178
178
|
return (db.query('SELECT ref FROM evidence WHERE feature_id = ? AND version = ? ORDER BY rowid').all(id, version) as Array<{ ref: string }>).map((row) => row.ref);
|
|
179
179
|
}
|
|
180
180
|
function items(db: Database, version: string): ChecklistItem[] {
|
|
181
|
-
const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.updated_at, a.updated_by
|
|
181
|
+
const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.dispatch_kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.updated_at, a.updated_by
|
|
182
182
|
FROM assignments a JOIN features f ON f.id = a.feature_id WHERE a.version = ? ORDER BY a.rowid`).all(version) as Array<Record<string, string | number | null>>;
|
|
183
183
|
return rows.map((r) => {
|
|
184
184
|
const evidence = [r.evidence, ...evidenceRefs(db, version, r.id as string)].filter((value) => value !== null).join('\n');
|
|
185
185
|
return { id: r.id as string, title: r.title as string, status: r.status as ChecklistItem['status'],
|
|
186
186
|
...(r.owner !== null ? { owner: r.owner as string } : {}), ...(r.kind !== null ? { kind: r.kind as ChecklistItem['kind'] } : {}),
|
|
187
|
+
...(r.dispatch_kind !== null ? { dispatchKind: r.dispatch_kind as ChecklistItem['dispatchKind'] } : {}),
|
|
187
188
|
...(r.priority !== null ? { priority: r.priority as ChecklistItem['priority'] } : {}), ...(r.predecessors !== null ? { predecessors: JSON.parse(r.predecessors as string) as string[] } : {}),
|
|
188
189
|
...(r.deadline_version !== null ? { deadlineVersion: r.deadline_version as string } : {}),
|
|
189
190
|
...(r.ceo_minutes !== null ? { ceoMinutes: r.ceo_minutes as number } : {}), ...(r.ceo_date !== null ? { ceoDate: r.ceo_date as string } : {}),
|
|
@@ -202,9 +203,9 @@ function putItem(db: Database, version: string, item: ChecklistItem): void {
|
|
|
202
203
|
if (!feature) db.query('INSERT INTO features (id, title, owner, kind, created_at) VALUES (?, ?, ?, ?, ?)').run(item.id, item.title, item.owner ?? null, item.kind ?? null, item.updatedAt);
|
|
203
204
|
// features.owner/kind follow the latest assignment so details() and the checklist never disagree after a set.
|
|
204
205
|
else if (item.owner !== undefined || item.kind !== undefined) db.query('UPDATE features SET owner = COALESCE(?, owner), kind = COALESCE(?, kind) WHERE id = ?').run(item.owner ?? null, item.kind ?? null, item.id);
|
|
205
|
-
db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
206
|
-
ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
|
|
207
|
-
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
|
|
206
|
+
db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
207
|
+
ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, dispatch_kind=excluded.dispatch_kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
|
|
208
|
+
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
|
|
208
209
|
}
|
|
209
210
|
function jsonHash(contents: string | Buffer): string { return createHash('sha256').update(contents).digest('hex'); }
|
|
210
211
|
|
|
@@ -245,8 +246,8 @@ function importOnDb(db: Database, version: string): boolean {
|
|
|
245
246
|
// Keep a legacy per-version title until an explicit retitle unifies the feature identity.
|
|
246
247
|
if (!existing) putItem(db, version, item);
|
|
247
248
|
else {
|
|
248
|
-
db.query('INSERT OR IGNORE INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
|
|
249
|
-
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, item.title === existing.title ? null : item.title, item.owner ?? null, item.kind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
|
|
249
|
+
db.query('INSERT OR IGNORE INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
|
|
250
|
+
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, item.title === existing.title ? null : item.title, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
for (const entry of data.history) record(db, version, entry);
|
|
@@ -273,7 +274,7 @@ function importOnDb(db: Database, version: string): boolean {
|
|
|
273
274
|
record(db, version, { at: new Date().toISOString(), by: item.updatedBy, id: item.id, field: 'reimport', from: null, to: item, released: data.released, dev: data.dev });
|
|
274
275
|
continue;
|
|
275
276
|
}
|
|
276
|
-
const fields = ['title', 'status', 'evidence', 'owner', 'disposition', 'kind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
|
|
277
|
+
const fields = ['title', 'status', 'evidence', 'owner', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
|
|
277
278
|
const baseEvidence = (db.query('SELECT evidence FROM assignments WHERE feature_id = ? AND version = ?').get(item.id, version) as { evidence: string | null }).evidence ?? undefined;
|
|
278
279
|
const preserveRefs = item.evidence === baseEvidence || item.evidence === current.evidence;
|
|
279
280
|
const differs = fields.some((field) => field === 'evidence'
|
|
@@ -21,6 +21,8 @@ export interface GateShard {
|
|
|
21
21
|
waitReason?: string;
|
|
22
22
|
/** 계획 분 — 남은 시간 추정의 재료. */
|
|
23
23
|
plannedMin?: number;
|
|
24
|
+
/** GATE-MULTI-HOST — 이 조각(가장 최근 시도)이 놓인 풀 멤버(kubectl 컨텍스트). 놓이기 전엔 없다. */
|
|
25
|
+
host?: string;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/** 게이트 노드의 판정 결과 — 끝난 조각의 rc≠0 을 «새로 생긴 실패»와 «기존 실패»로 가른 수. */
|
|
@@ -58,11 +60,13 @@ function shardOf(value: unknown): GateShard | null {
|
|
|
58
60
|
const rc = num(raw.rc);
|
|
59
61
|
const waitReason = str(raw.waitReason);
|
|
60
62
|
const plannedMin = num(raw.plannedMin);
|
|
63
|
+
const host = str(raw.host, 120);
|
|
61
64
|
return {
|
|
62
65
|
id, state,
|
|
63
66
|
...(startedAt ? { startedAt } : {}), ...(endedAt ? { endedAt } : {}),
|
|
64
67
|
...(installSec !== undefined ? { installSec } : {}), ...(rc !== undefined ? { rc } : {}),
|
|
65
68
|
...(waitReason ? { waitReason } : {}), ...(plannedMin !== undefined ? { plannedMin } : {}),
|
|
69
|
+
...(host ? { host } : {}),
|
|
66
70
|
};
|
|
67
71
|
}
|
|
68
72
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* gate host (GATE-REMOTE). Read-only for the release ledger: it reads the previous published version and never writes.
|
|
4
4
|
* It does not touch the landing freeze or launch Pods. */
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
|
6
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
6
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
7
8
|
import { join } from 'node:path';
|
|
8
9
|
import { debug } from '../debug/log.js';
|
|
9
10
|
import { runSelfGateCli, type SelfGateCliOptions, type SelfGateCliResult } from '../self-implement/gate-cli.js';
|
|
@@ -14,9 +15,14 @@ import { baseVersion, isReleaseVersion } from '../../scripts/release-loop/releas
|
|
|
14
15
|
export const LIGHT_RC_ALWAYS_FILE = 'release/light-rc-always.txt';
|
|
15
16
|
export const LIGHT_RC_DEFAULT_SHARDS = 4;
|
|
16
17
|
export const LIGHT_RC_NO_PREVIOUS_CUT = '직전 판 컷을 못 찾았다 — --base 로 준다';
|
|
18
|
+
/** RELEASE-DAILY-LIGHT-RC ① — what light-rc measures by default: main as it is on origin, not the tree it started in
|
|
19
|
+
* (10-12: the seat tree measured changed=2, a main worktree 52). */
|
|
20
|
+
export const LIGHT_RC_DEFAULT_HEAD = 'origin/main';
|
|
17
21
|
|
|
18
22
|
export interface LightRcOptions {
|
|
19
23
|
base?: string;
|
|
24
|
+
/** Commit to measure (RELEASE-DAILY-LIGHT-RC ①). Absent = `origin/main` after `git fetch origin main`. */
|
|
25
|
+
head?: string;
|
|
20
26
|
/** Gate host; absent = config gateRemote.host (the dispatch's own default). */
|
|
21
27
|
remote?: string;
|
|
22
28
|
/** Run on this machine (the remote child is re-invoked with it). */
|
|
@@ -30,6 +36,12 @@ export interface LightRcOptions {
|
|
|
30
36
|
export interface LightRcResult {
|
|
31
37
|
version: string;
|
|
32
38
|
base: string;
|
|
39
|
+
/** The commit the gate measured (RELEASE-DAILY-LIGHT-RC ①) — origin/main unless --head was given. */
|
|
40
|
+
measuredCommit: string;
|
|
41
|
+
/** HEAD of the tree light-rc was started from; differs from measuredCommit when it ran from a seat/work tree. */
|
|
42
|
+
worktreeHead: string | null;
|
|
43
|
+
/** RELEASE-DAILY-LIGHT-RC ② — tests added because they import a changed source; null = not reported. */
|
|
44
|
+
importerTests: number | null;
|
|
33
45
|
/** New failures vs. the base; null = the gate produced no measurement (never read as green). */
|
|
34
46
|
introduced: number | null;
|
|
35
47
|
preexisting: number | null;
|
|
@@ -56,6 +68,9 @@ export interface LightRcDeps {
|
|
|
56
68
|
dispatch?: (opts: DispatchOptions, deps?: DispatchDeps) => Promise<number>;
|
|
57
69
|
/** Extra dispatch deps (runner · settings) — tests drive the real dispatch with a fake host. */
|
|
58
70
|
dispatchDeps?: Omit<DispatchDeps, 'write'>;
|
|
71
|
+
/** Detached checkout of `sha` for a local run whose tree is not at the measured commit (default: git worktree add
|
|
72
|
+
* --detach in a temp dir ⊕ bun install); `cleanup` removes it. */
|
|
73
|
+
checkout?: (sha: string, repo: string, log: (line: string) => void) => { dir: string; cleanup: () => void };
|
|
59
74
|
}
|
|
60
75
|
|
|
61
76
|
/** Shown when the gate ran remotely but the host name did not come back. */
|
|
@@ -87,6 +102,51 @@ export function previousCutBase(version: string, deps: LightRcDeps & { cwd: stri
|
|
|
87
102
|
return sha;
|
|
88
103
|
}
|
|
89
104
|
|
|
105
|
+
const SHA_RE = /^[0-9a-f]{40}$/;
|
|
106
|
+
|
|
107
|
+
/** RELEASE-DAILY-LIGHT-RC ① — the commit to measure. Default: fetch origin main, then origin/main (a failed fetch is
|
|
108
|
+
* said, and the local origin/main is measured — never silently the tree's HEAD). */
|
|
109
|
+
export function resolveMeasuredCommit(cwd: string, head: string | undefined, deps: LightRcDeps, log: (line: string) => void): { measuredCommit: string; worktreeHead: string | null } {
|
|
110
|
+
const git = deps.git ?? defaultGit;
|
|
111
|
+
const ref = head ?? LIGHT_RC_DEFAULT_HEAD;
|
|
112
|
+
if (head === undefined) {
|
|
113
|
+
const fetch = git(['fetch', '--quiet', 'origin', 'main'], cwd);
|
|
114
|
+
if (fetch.rc !== 0) {
|
|
115
|
+
log(`⚠️ light-rc: git fetch origin main rc=${fetch.rc} — measuring the local ${LIGHT_RC_DEFAULT_HEAD} (may be stale)`);
|
|
116
|
+
debug.log('release.light-rc', 'fetch-failed', { rc: fetch.rc });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const parsed = git(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], cwd);
|
|
120
|
+
const measuredCommit = parsed.stdout.trim();
|
|
121
|
+
if (parsed.rc !== 0 || !SHA_RE.test(measuredCommit)) throw new Error(`release light-rc: cannot resolve ${ref} to a commit (rc=${parsed.rc})`);
|
|
122
|
+
const top = git(['rev-parse', 'HEAD'], cwd);
|
|
123
|
+
const worktreeHead = top.rc === 0 && SHA_RE.test(top.stdout.trim()) ? top.stdout.trim() : null;
|
|
124
|
+
if (worktreeHead !== measuredCommit) {
|
|
125
|
+
log(`ⓘ light-rc measures ${measuredCommit.slice(0, 12)} (${ref}) — this tree's HEAD ${worktreeHead?.slice(0, 12) ?? '(unresolved)'} is not what is measured`);
|
|
126
|
+
debug.log('release.light-rc', 'measured-commit-differs', { ref, measuredCommit, worktreeHead, cwd });
|
|
127
|
+
}
|
|
128
|
+
return { measuredCommit, worktreeHead };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function defaultCheckout(sha: string, repo: string, log: (line: string) => void): { dir: string; cleanup: () => void } {
|
|
132
|
+
const dir = mkdtempSync(join(tmpdir(), 'elanous-light-rc-'));
|
|
133
|
+
const run = (cmd: string, args: string[], cwd: string) => spawnSync(cmd, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
134
|
+
const cleanup = () => {
|
|
135
|
+
run('git', ['worktree', 'remove', '--force', dir], repo);
|
|
136
|
+
rmSync(dir, { recursive: true, force: true });
|
|
137
|
+
run('git', ['worktree', 'prune'], repo);
|
|
138
|
+
};
|
|
139
|
+
const add = run('git', ['worktree', 'add', '--detach', dir, sha], repo);
|
|
140
|
+
if (add.status !== 0) { cleanup(); throw new Error(`release light-rc: git worktree add ${sha.slice(0, 12)} failed: ${(add.stderr ?? '').trim()}`); }
|
|
141
|
+
log(`light-rc: detached checkout of ${sha.slice(0, 12)} at ${dir} — installing dependencies`);
|
|
142
|
+
for (const sub of ['.', 'apps/pwa']) {
|
|
143
|
+
if (!existsSync(join(dir, sub, 'package.json'))) continue;
|
|
144
|
+
const install = run('bun', ['install', '--frozen-lockfile'], join(dir, sub));
|
|
145
|
+
if (install.status !== 0) { cleanup(); throw new Error(`release light-rc: bun install (${sub}) failed in the checkout: ${(install.stderr ?? '').trim().slice(-400)}`); }
|
|
146
|
+
}
|
|
147
|
+
return { dir, cleanup };
|
|
148
|
+
}
|
|
149
|
+
|
|
90
150
|
function repoRoot(deps: LightRcDeps): string {
|
|
91
151
|
if (deps.cwd) return deps.cwd;
|
|
92
152
|
const top = defaultGit(['rev-parse', '--show-toplevel'], process.cwd());
|
|
@@ -110,23 +170,32 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
110
170
|
if (opts.remote !== undefined && !isValidGateHost(opts.remote)) throw new Error(`invalid --remote host: ${opts.remote}`);
|
|
111
171
|
const log = opts.log ?? ((line: string) => process.stderr.write(`${line}\n`));
|
|
112
172
|
const cwd = repoRoot(deps);
|
|
173
|
+
const { measuredCommit, worktreeHead } = resolveMeasuredCommit(cwd, opts.head, deps, log);
|
|
113
174
|
const base = opts.base ?? previousCutBase(version, { ...deps, cwd, ledgerRoot: opts.ledgerRoot });
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
175
|
+
const readList = (dir: string) => {
|
|
176
|
+
const text = (deps.readFile ?? ((path: string) => existsSync(path) ? readFileSync(path, 'utf8') : undefined))(join(dir, LIGHT_RC_ALWAYS_FILE));
|
|
177
|
+
if (text === undefined) throw new Error(`release light-rc: ${LIGHT_RC_ALWAYS_FILE} not found`);
|
|
178
|
+
return parseAlwaysIncludeList(text);
|
|
179
|
+
};
|
|
180
|
+
let alwaysInclude = readList(cwd);
|
|
118
181
|
|
|
119
182
|
let local: SelfGateCliResult | undefined;
|
|
120
183
|
const runLocal = () => {
|
|
121
|
-
|
|
184
|
+
// ① The gate scopes by its tree's HEAD — so a tree that is not at the measured commit runs in a detached checkout of it.
|
|
185
|
+
const checkout = worktreeHead === measuredCommit ? undefined : (deps.checkout ?? defaultCheckout)(measuredCommit, cwd, log);
|
|
186
|
+
try {
|
|
187
|
+
const dir = checkout?.dir ?? cwd;
|
|
188
|
+
if (checkout) alwaysInclude = readList(dir);
|
|
189
|
+
local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, alwaysInclude, includeImporterTests: true });
|
|
190
|
+
} finally { checkout?.cleanup(); }
|
|
122
191
|
for (const line of local.lines) log(line);
|
|
123
192
|
return local.exitCode;
|
|
124
193
|
};
|
|
125
194
|
const captured: Buffer[] = [];
|
|
126
195
|
const rc = await (deps.dispatch ?? dispatchHeavyCheck)({
|
|
127
|
-
tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true,
|
|
196
|
+
tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
|
|
128
197
|
// The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
|
|
129
|
-
remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--shards', String(shards), '--local', '--json'],
|
|
198
|
+
remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), '--local', '--json'],
|
|
130
199
|
flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
|
|
131
200
|
runLocal,
|
|
132
201
|
}, {
|
|
@@ -140,7 +209,8 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
140
209
|
let result: LightRcResult;
|
|
141
210
|
if (local) {
|
|
142
211
|
result = {
|
|
143
|
-
version, base,
|
|
212
|
+
version, base, measuredCommit, worktreeHead,
|
|
213
|
+
importerTests: local.importerTestsAdded ? local.importerTestsAdded.length : null,
|
|
144
214
|
introduced: local.baseline?.introduced ?? null,
|
|
145
215
|
preexisting: local.baseline?.preexisting ?? null,
|
|
146
216
|
unclassified: local.baseline ? local.baseline.unknown + local.baseline.preconditionUnmet : null,
|
|
@@ -154,7 +224,8 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
154
224
|
if (!remote) throw new Error(`release light-rc: remote gate returned no result (rc=${rc})`);
|
|
155
225
|
const host = (remote as { host?: unknown }).host;
|
|
156
226
|
result = {
|
|
157
|
-
version, base,
|
|
227
|
+
version, base, measuredCommit, worktreeHead,
|
|
228
|
+
importerTests: typeof remote.importerTests === 'number' ? remote.importerTests : null,
|
|
158
229
|
introduced: typeof remote.introduced === 'number' ? remote.introduced : null,
|
|
159
230
|
preexisting: typeof remote.preexisting === 'number' ? remote.preexisting : null,
|
|
160
231
|
unclassified: typeof remote.unclassified === 'number' ? remote.unclassified : null,
|
|
@@ -170,14 +241,14 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
|
|
|
170
241
|
// Unmeasured (null) or unclassified failures are never green; policy-gate findings in the gate output are reported
|
|
171
242
|
// (gate rc), not a regression.
|
|
172
243
|
result.ok = result.introduced === 0 && result.unclassified === 0;
|
|
173
|
-
debug.log('release.light-rc', 'done', { version, base, introduced: result.introduced, preexisting: result.preexisting, unclassified: result.unclassified, shards, remote: result.remote, unmeasured: result.unmeasured });
|
|
244
|
+
debug.log('release.light-rc', 'done', { version, base, measuredCommit, worktreeHead, importerTests: result.importerTests, introduced: result.introduced, preexisting: result.preexisting, unclassified: result.unclassified, shards, remote: result.remote, unmeasured: result.unmeasured });
|
|
174
245
|
return result;
|
|
175
246
|
}
|
|
176
247
|
|
|
177
248
|
export function formatLightRc(result: LightRcResult): string[] {
|
|
178
249
|
return [
|
|
179
|
-
`${result.ok ? '✅' : '⛔'} light-rc ${result.version} · base ${result.base.slice(0, 12)} · ${result.remote ? `host ${result.remote}` : 'local'} · shards ${result.shards}`,
|
|
180
|
-
` introduced ${result.introduced ?? '못 쟀다'} · preexisting ${result.preexisting ?? '못 쟀다'} · unclassified ${result.unclassified ?? '못 쟀다'} · always-include ${result.alwaysInclude}${result.alwaysIncludeMissing.length ? ` (missing: ${result.alwaysIncludeMissing.join(', ')})` : ''} · gate rc ${result.gateExitCode}`,
|
|
250
|
+
`${result.ok ? '✅' : '⛔'} light-rc ${result.version} · base ${result.base.slice(0, 12)} · measured ${result.measuredCommit.slice(0, 12)} · ${result.remote ? `host ${result.remote}` : 'local'} · shards ${result.shards}`,
|
|
251
|
+
` introduced ${result.introduced ?? '못 쟀다'} · preexisting ${result.preexisting ?? '못 쟀다'} · unclassified ${result.unclassified ?? '못 쟀다'} · importer tests ${result.importerTests ?? '못 쟀다'} · always-include ${result.alwaysInclude}${result.alwaysIncludeMissing.length ? ` (missing: ${result.alwaysIncludeMissing.join(', ')})` : ''} · gate rc ${result.gateExitCode}`,
|
|
181
252
|
...(result.unmeasured !== null ? [` shards: unmeasured (${result.unmeasured})`] : []),
|
|
182
253
|
];
|
|
183
254
|
}
|
|
@@ -38,7 +38,18 @@ export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: st
|
|
|
38
38
|
// The audit matcher owns explicit-label and evidence decisions on both PR surfaces.
|
|
39
39
|
// The shared matcher only accepts a whole `칸: X` line. A designated label in the body (`칸: X — …` at a line head)
|
|
40
40
|
// or in the title is restated as such a line; prose mentions are not (the audit command's contract is unchanged).
|
|
41
|
-
|
|
41
|
+
// Goal-file ids join that set: `칸: X` lines plus `- 칸 id: A · B` declarations (not-declared excluded).
|
|
42
|
+
const fromBody = goalCells(pr.body ?? '');
|
|
43
|
+
const fromTitle = titleCells(pr.title);
|
|
44
|
+
const fromGoal = goal ? goalFileCells(goal) : new Set<string>();
|
|
45
|
+
const designated = [...new Set([...fromBody, ...fromTitle, ...fromGoal])];
|
|
46
|
+
for (const id of designated) {
|
|
47
|
+
log('release.checklist', 'merged-pr-cell-source', {
|
|
48
|
+
pr: number,
|
|
49
|
+
id,
|
|
50
|
+
source: fromBody.has(id) ? 'body' : fromTitle.has(id) ? 'title' : 'goal',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
42
53
|
// Only the restated labels go to the matcher — raw body text (quotes, fences, indented code) never does.
|
|
43
54
|
const prForMatch = { ...merged, title: '', body: designated.map((id) => `칸: ${id}`).join('\n') };
|
|
44
55
|
const matches = [...new Set(versions)].flatMap((version) => {
|
|
@@ -86,10 +97,14 @@ export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: st
|
|
|
86
97
|
for (const id of missing) log('release.checklist', 'merged-pr-cell-not-found', { pr: number, id });
|
|
87
98
|
}
|
|
88
99
|
|
|
89
|
-
const LABEL_IDS = '([A-Za-z0-9_-]+(?:[ \\t]
|
|
100
|
+
const LABEL_IDS = '([A-Za-z0-9_-]+(?:[ \\t]*(?:,|·)[ \\t]*[A-Za-z0-9_-]+)*)';
|
|
90
101
|
const LABEL_END = '(?=[ \\t]*$|[ \\t]+[—–·(-])';
|
|
91
102
|
const DESIGNATION = new RegExp(`^ {0,3}(?:#{1,6}[ \\t]+|[-*][ \\t]+)?칸[ \\t]*:[ \\t]*${LABEL_IDS}${LABEL_END}`);
|
|
92
103
|
|
|
104
|
+
function idsInLabel(captured: string): string[] {
|
|
105
|
+
return captured.split(/[,·]/).map((id) => id.trim()).filter(Boolean);
|
|
106
|
+
}
|
|
107
|
+
|
|
93
108
|
/** Lines of a Markdown document outside fenced code (closed only by the same marker, at least as long), 4-space
|
|
94
109
|
* indented code and `>` quotes — the only lines that may designate a cell or declare completion. */
|
|
95
110
|
function proseLines(text: string): string[] {
|
|
@@ -109,13 +124,28 @@ function proseLines(text: string): string[] {
|
|
|
109
124
|
return lines;
|
|
110
125
|
}
|
|
111
126
|
|
|
112
|
-
/** Cell ids a document designates on a line head: `칸: X[, Y]`, optionally after a heading or list marker. */
|
|
127
|
+
/** Cell ids a document designates on a line head: `칸: X[, Y]` or `칸: X · Y`, optionally after a heading or list marker. */
|
|
113
128
|
export function goalCells(goal: string): Set<string> {
|
|
114
129
|
const ids = new Set<string>();
|
|
115
130
|
for (const line of proseLines(goal)) {
|
|
116
131
|
const label = DESIGNATION.exec(line);
|
|
117
132
|
if (!label) continue;
|
|
118
|
-
for (const id of label[1]
|
|
133
|
+
for (const id of idsInLabel(label[1]!)) ids.add(id);
|
|
134
|
+
}
|
|
135
|
+
return ids;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Goal-file designations: `칸:` lines plus `- 칸 id: A · B` declarations (same shape as goalChecklistIds). */
|
|
139
|
+
function goalFileCells(goal: string): Set<string> {
|
|
140
|
+
const ids = goalCells(goal);
|
|
141
|
+
for (const line of proseLines(goal)) {
|
|
142
|
+
if (!line.startsWith('- 칸 id: ')) continue;
|
|
143
|
+
const declared = line.slice('- 칸 id: '.length).trim();
|
|
144
|
+
if (!declared || declared === 'not declared') continue;
|
|
145
|
+
for (const id of declared.split(' · ')) {
|
|
146
|
+
const trimmed = id.trim();
|
|
147
|
+
if (trimmed) ids.add(trimmed);
|
|
148
|
+
}
|
|
119
149
|
}
|
|
120
150
|
return ids;
|
|
121
151
|
}
|
|
@@ -129,7 +159,7 @@ export function declaresCompletion(goal: string): boolean {
|
|
|
129
159
|
export function titleCells(title: string): Set<string> {
|
|
130
160
|
const ids = new Set<string>();
|
|
131
161
|
for (const label of title.matchAll(new RegExp(`(?<![A-Za-z0-9가-힣])칸[ \\t]*:[ \\t]*${LABEL_IDS}${LABEL_END}`, 'g'))) {
|
|
132
|
-
for (const id of label[1]
|
|
162
|
+
for (const id of idsInLabel(label[1]!)) ids.add(id);
|
|
133
163
|
}
|
|
134
164
|
return ids;
|
|
135
165
|
}
|
|
@@ -290,7 +290,7 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
|
|
|
290
290
|
stamp.sha = gitResult(git, ['rev-parse', 'HEAD'], checkout);
|
|
291
291
|
if (!stamp.sha) throw new Error('git rev-parse HEAD returned no sha');
|
|
292
292
|
const regressionFiles: string[] = [];
|
|
293
|
-
const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, log: (line) => {
|
|
293
|
+
const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, log: (line) => {
|
|
294
294
|
for (const entry of line.split(/\r?\n/)) {
|
|
295
295
|
const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
|
|
296
296
|
if (file && regressionFiles.length < 3) regressionFiles.push(file);
|