elanous 0.2.20 → 0.2.22
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/aBi6EyMtLsrl7J8eH4kF7/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/088d8e8a.8069543d082bec12.js +160 -0
- package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +148 -0
- package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +32 -0
- package/apps/pwa/out/_next/static/chunks/119fc678.6f591cdb84ca5791.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +309 -0
- package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +122 -0
- package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +79 -0
- package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1948.5f35b39eef222a94.js +5 -0
- package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +36 -0
- package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{2489-ff55a35b202c0f94.js → 2489-d238d3e2eb5b2bf5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522-1de1319d028ac89c.js +25 -0
- package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +115 -0
- package/apps/pwa/out/_next/static/chunks/4588.ad3364cb7fb97ada.js +86 -0
- package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +77 -0
- package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +90 -0
- package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +1 -0
- package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{6158.af2e93b7adff709b.js → 6158.566c890adc06a459.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +287 -0
- package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +226 -0
- package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6767.8e6c5f6e744fcd9f.js +38 -0
- package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7175-350f4ce2873bc038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7630.2b9a68659053ff4e.js +193 -0
- package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7899.597af4a9996c907f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79b78388.663188133449d707.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8194.484f51e273d9abd2.js +217 -0
- package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/88729267.9c6c000157c83f2f.js +62 -0
- package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +23 -0
- package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/9832.2ab2e818013574c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-40c16bd0efdb04b8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/{page-c855c24de7db74fe.js → page-88459e0903da2803.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-85b316bb4235980b.js → page-d85c43f46f58716b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-9b2b26a33cb2cd42.js → page-4e645600579ae952.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-c9955fde67b1bcb5.js → page-87edbfd19117823b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-4ba4abe096b6c2a8.js → page-cbaf66b1e1804adf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-575d4a8b4f7becb2.js → page-80ed511e02c81412.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/{page-f5d56ff5f45ad164.js → page-9f5610caaa06178c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/{page-2260e9eef0357421.js → page-ec8f3575e339de74.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-466bf0ee16ad1432.js → page-2a19c5cd3b562580.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-a23bc71713bcc08f.js → page-b6a09cde2e07521a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-35bfec2e631d3eae.js → page-abd86cd832aaa011.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-f9ccb1b1adbea14d.js → page-8c3f168fc3f91939.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-ec102c9b8b691e37.js → page-786fb4504d0f2fa9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-db03ae3589a81c9e.js → page-7ec8e289b4c14df6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-4a6463b97f0ad94f.js → page-8c8ac17d52be2a79.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-75bffecc9aa1004e.js → page-d359ab048d63a9d9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-31d5b875760bb62d.js → page-f151cc10ad026940.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-46d5201d2207a511.js → page-bf495a1e284f4e00.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-cf0a4b4abead71ea.js → page-9abcfac07e02a542.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-0acc8e198f7b0dfb.js → page-69cb93d1a2e57e0e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-34882c84f84021c5.js → page-72ec543928d67c3e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/d70879db.c66c56a95a91efc6.js +66 -0
- package/apps/pwa/out/_next/static/chunks/f8626309.a4e5d362b1d55e59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +1 -0
- package/apps/pwa/out/_next/static/css/{d3427996da11e480.css → b9d8151e48998417.css} +1 -1
- package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +14 -14
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +14 -14
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +14 -14
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +14 -14
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +14 -14
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +14 -14
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +14 -14
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +14 -14
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +14 -14
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +14 -14
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +14 -14
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +15 -15
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +14 -14
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +14 -14
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +14 -14
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +15 -15
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +14 -14
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +14 -14
- package/apps/pwa/out/live-run/index.html +1 -0
- package/apps/pwa/out/live-run/index.txt +35 -0
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +14 -14
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +14 -14
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +14 -14
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +14 -14
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +14 -14
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +14 -14
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +14 -14
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +14 -14
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +14 -14
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +15 -15
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +14 -14
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +14 -14
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +14 -14
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +14 -14
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +14 -14
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +14 -14
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +14 -14
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +14 -14
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +14 -14
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +14 -14
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +14 -14
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +14 -14
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +14 -14
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +14 -14
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +14 -14
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +14 -14
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +14 -14
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/drafts/recipes.yaml +6 -6
- package/graphs/implement-loop.yaml +277 -5
- package/graphs/test-diet/recipes.yaml +3 -0
- package/graphs/test-diet/test-diet.yaml +3 -1
- package/package.json +1 -1
- package/scripts/coord-channel-watch.sh +31 -4
- package/scripts/docs-lint.ts +4 -1
- package/scripts/f-session-monitor.ts +69 -0
- package/scripts/hq/standby-snapshot.ts +7 -3
- package/scripts/knowledge-compress.ts +11 -0
- package/scripts/marketing/generate-ax-brief.ts +18 -1
- package/scripts/measure-nl-routing-corpus.ts +11 -3
- package/scripts/nightly-docops.ts +90 -3
- package/scripts/release-loop/gate-node.ts +5 -5
- package/scripts/release-loop/shard-plan.ts +50 -5
- package/scripts/research-coo-admin-dates.ts +39 -0
- package/scripts/rhythm/daily.ts +2 -1
- package/scripts/skills/public-check.ts +7 -2
- package/scripts/smart-merge/resync-shadow.ts +5 -3
- package/scripts/test-diet/lib.ts +81 -1
- package/scripts/test-diet/node.ts +48 -2
- package/scripts/verify-coo-admin-evidence.ts +83 -0
- package/src/acp/client.ts +4 -2
- package/src/agent/run-context.ts +4 -0
- package/src/agent-env/profile.ts +25 -5
- package/src/agent-mission/driver.ts +26 -12
- package/src/agent-mission/supervisor-metrics.ts +17 -2
- package/src/agent-substrate/acp-reviewer.ts +12 -5
- package/src/agent-substrate/pr-reviewer.ts +11 -4
- package/src/agent-substrate/review-intent.ts +102 -3
- package/src/autopilot/build/llm-conflict-merge.ts +22 -8
- package/src/autopilot/pr-manager.ts +18 -8
- package/src/away/release-watch.ts +47 -8
- package/src/briefing/brief-items.ts +104 -11
- package/src/browser-cdp/client.ts +10 -5
- package/src/chat/index.ts +1 -0
- package/src/cli/brief-cli.ts +20 -2
- package/src/cli/config-classify.ts +83 -0
- package/src/cli/control-cli.ts +14 -0
- package/src/cli/decisions-cli.ts +26 -16
- package/src/cli/logs-model-input.ts +1 -1
- package/src/cli/ops-cli.ts +11 -0
- package/src/cli/ops-overview-cli.ts +50 -0
- package/src/cli/pod-cli.ts +1 -0
- package/src/cli/pr-cli.ts +65 -8
- package/src/cli/release-cli.ts +21 -4
- package/src/cli/tasks-cli.ts +214 -1
- package/src/connectors/types.ts +6 -6
- package/src/context-bus/context-now-surfaces.ts +18 -0
- package/src/context-bus/coord-events.ts +32 -4
- package/src/context-bus/long-term-memory.ts +23 -6
- package/src/context-bus/nightly-condense.ts +169 -21
- package/src/control/control-status.ts +87 -0
- package/src/control-plane/light-member.ts +5 -3
- package/src/control-plane/member.ts +172 -7
- package/src/core-turn/run-goal-loop.ts +22 -1
- package/src/dashboard/index.ts +40 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +9 -0
- package/src/decisions/decision-cards.ts +20 -1
- package/src/decisions/decision-ledger.ts +11 -8
- package/src/decisions/web-push-decision-cards.ts +19 -3
- package/src/discord-self-message.ts +2 -2
- package/src/domains/coo-admin-dates.evidence.json +876 -0
- package/src/domains/coo-admin-tool.ts +48 -14
- package/src/domains/ops-status.ts +53 -0
- package/src/domains/outbound-alert.ts +24 -1
- package/src/esc-abort-gate.ts +3 -1
- package/src/exec-requests/planner.ts +6 -0
- package/src/graph-kinds/registry.ts +6 -6
- package/src/graph-runner/graph-cli.ts +91 -2
- package/src/graph-runner/graph-run-api.ts +20 -0
- package/src/graph-runner/graph-tick.ts +73 -12
- package/src/graph-runner/runner.ts +43 -11
- package/src/graph-unify/wf-to-graph.ts +79 -0
- package/src/graph-wizard/archetypes.ts +88 -0
- package/src/graph-wizard/generate.ts +577 -0
- package/src/graph-wizard/saved-steps.ts +120 -0
- package/src/graph-wizard/steps.ts +206 -0
- package/src/harness/harness-cli-command.ts +186 -32
- package/src/harness/harness-queue.ts +58 -14
- package/src/harness/launch-advice.ts +23 -0
- package/src/index.ts +43 -11
- package/src/intake-plane/digest.ts +18 -11
- package/src/knowledge/conclusion-compress.ts +93 -0
- package/src/knowledge/know-find.ts +9 -2
- package/src/knowledge/query.ts +20 -0
- package/src/llm.ts +26 -16
- package/src/loops/neighbor-runtime.ts +88 -0
- package/src/loops/orchestrator/author-depth.ts +29 -11
- package/src/loops/orchestrator/overlap.ts +7 -1
- package/src/loops/orchestrator/resync-shadow.ts +1 -1
- package/src/loops/orchestrator/tick.ts +35 -2
- package/src/loops/orchestrator/traffic.ts +2 -0
- package/src/loops/registry.ts +5 -0
- package/src/market/publish.ts +17 -1
- package/src/maturity/feature-maturity.ts +4 -2
- package/src/mss/logging/redaction.ts +17 -0
- package/src/nexus/api/draft-metrics.ts +128 -0
- package/src/nexus/api/graph-peer-edit.ts +77 -0
- package/src/nexus/api/graph-wizard-api.ts +61 -0
- package/src/nexus/api/graphs-api.ts +193 -17
- package/src/nexus/api/harness-traversal.ts +205 -0
- package/src/nexus/api/http-server.ts +122 -6
- package/src/nexus/api/plugins-market.ts +24 -0
- package/src/nexus/index.ts +3 -2
- package/src/nexus/outbound/router.ts +28 -8
- package/src/oauth/claude-pty-maturity.ts +24 -0
- package/src/oauth/fallback-chain.ts +27 -14
- package/src/onboarding/first-run.ts +3 -0
- package/src/ops/overview-collect.ts +345 -0
- package/src/ops/overview-seat-era.ts +90 -0
- package/src/ops/overview.ts +223 -0
- package/src/plugins/maker/market-bundle.ts +9 -0
- package/src/plugins/maker/plugin-maker.ts +9 -3
- package/src/plugins/maker/wizard-generate.ts +73 -9
- package/src/policy/llm-policy.ts +11 -6
- package/src/release-loop/checklist-board.ts +27 -0
- package/src/release-loop/checklist.ts +38 -0
- package/src/release-loop/gate-shards.ts +7 -2
- package/src/seat-address/seat-address.ts +1 -0
- package/src/seat-loop/seat-loop.ts +174 -20
- package/src/seat-loop/seat-report.ts +29 -1
- package/src/self-dev/ask-launch-flow.ts +4 -2
- package/src/self-dev/ask-launch-io.ts +3 -1
- package/src/self-dev/dev-cli.ts +90 -8
- package/src/self-dev/dev-pipeline.ts +20 -1
- package/src/self-dev/draft-sweep.ts +45 -8
- package/src/self-dev/graph-journey-nodes.ts +157 -0
- package/src/self-dev/graph-journey-route.ts +105 -0
- package/src/self-dev/launch-preflight.ts +43 -3
- package/src/self-dev/orchestrate.ts +3 -0
- package/src/self-dev/release-path-guard.ts +7 -4
- package/src/self-dev/review-provider-fallback.ts +83 -0
- package/src/self-dev/run-supervisor.ts +5 -1
- package/src/self-implement/frozen-merges.ts +23 -0
- package/src/self-implement/goal-author.ts +14 -0
- package/src/self-implement/harness-policy-gates.ts +7 -5
- package/src/self-implement/heal-intake.ts +3 -0
- package/src/self-implement/host-regate.ts +28 -14
- package/src/self-implement/l8-merge-queue.ts +80 -8
- package/src/self-implement/orchestrator.ts +84 -28
- package/src/self-implement/seams.ts +8 -3
- package/src/self-implement/self-implement-cli.ts +4 -0
- package/src/self-implement/self-implement-runtime.ts +12 -0
- package/src/session-runtime/index.ts +5 -3
- package/src/shell-env-bootstrap.ts +35 -6
- package/src/steward/triage.ts +25 -8
- package/src/storage/file-lock.ts +33 -4
- package/src/task-agent/card-evidence.ts +6 -0
- package/src/task-agent/completion-evidence.ts +31 -3
- package/src/task-agent/cover.ts +61 -0
- package/src/task-agent/live-moves.ts +126 -3
- package/src/task-agent/parent-host.ts +315 -0
- package/src/task-agent/shadow.ts +19 -4
- package/src/task-agent/task-hand.ts +11 -2
- package/src/task-orchestrator/surfaces/pod-command-job.ts +41 -6
- package/src/task-orchestrator/surfaces/pod-gate-deps.ts +123 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +138 -15
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +39 -6
- package/src/task-orchestrator/surfaces/self-implement.ts +7 -0
- package/src/telegram-commands.ts +8 -0
- package/src/telegram-project-command.ts +6 -0
- package/src/telegram.ts +2 -2
- package/src/tool-runtime/browser-runtime.ts +87 -3
- package/src/tool-runtime/index.ts +1 -0
- package/src/typecheck-ratchet.ts +2 -1
- package/src/user-config.ts +55 -8
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/executor.ts +24 -2
- package/src/workflow-runtime/triggers/registry.ts +27 -0
- package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
- package/apps/pwa/out/_next/static/Bam1YziK2iH9bN4K0utGk/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1307-77fad80cf54477c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1612-f60c0c93ec773f81.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1844-9ec4b1d12f6e80eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1948.15f356b15a625597.js +0 -5
- package/apps/pwa/out/_next/static/chunks/2116-6429c188eb846ab8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/224-e7be8f762fe74986.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2549-89c518a4c8ed4d00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5755-ea7ed88eb956f47b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-94ed6f78e9814b2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7748-6e51bfe927019f5c.js +0 -25
- package/apps/pwa/out/_next/static/chunks/9247-c1753a059e7bac08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-33c0689b70ed8cf3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7a852956c74015a3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c5a5c621be0e04ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-7c058069c5e7fa63.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-dc5da0b8a2edb8a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ed4a6f799f005d09.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-9cd565005b93aca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-55f0f40c6db95f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-474cb5888ea0e8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ca21f9ad3208a61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-a9c2cfa8dda922a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6da35144878feb6d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-f6055495e9ed7ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-25204694fa9984a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a60e035f151d84d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-189c587f36874538.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c56634bde705a65d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a8d2fe0c669e0de4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c26fa10aac6c21c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-68793c6e10331d66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d81c07a7b4f618ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-be1c4e8697f22360.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-a4717e2c4bf7a28f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-0fd895fab9b62c1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8b6c1454a8e8f306.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c6e4364d9de8f717.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-0506a1e0e4bdb2f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-c260571513bf43c2.js +0 -1
- package/apps/pwa/out/_next/static/css/c23d959d3ee15e57.css +0 -1
- /package/apps/pwa/out/_next/static/{Bam1YziK2iH9bN4K0utGk → aBi6EyMtLsrl7J8eH4kF7}/_ssgManifest.js +0 -0
- /package/skills/project-onboarding/{skill.md → SKILL.md} +0 -0
package/src/cli/decisions-cli.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { getUserConfig } from '../user-config.js';
|
|
|
11
11
|
import { projectDecisionsToLinear } from '../decisions/decision-linear-projection.js';
|
|
12
12
|
import { DecisionLedger, importDecisionMarkdown, type DecisionCategory, type DecisionLedgerOptions, type DecisionOption, type DecisionTrack, type DecisionEntry, type Seat, type SeatDecisionRecord } from '../decisions/decision-ledger.js';
|
|
13
13
|
import { formatProactMeter, readProactMeter } from '../decisions/proact-meter.js';
|
|
14
|
+
import { writeStdoutFully } from './stdout-flush.js';
|
|
14
15
|
|
|
15
16
|
const repeat = (value: string, values: string[]) => [...values, value];
|
|
16
17
|
function date(raw?: string): string | undefined {
|
|
@@ -75,14 +76,24 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
75
76
|
return hqCliWriteAllowed(`decisions ${command}`, Boolean(override || root.opts().hqOverride),
|
|
76
77
|
(getElanousConfigDirOverride() || config.stateDir) && !hqDeps.store && !getUserConfig().hq?.arbiter ? { ...hqDeps, store: fileLeaseStore(join(config.stateDir ?? effectiveInstanceRoot(), 'hq', 'lease.json')), seenPath: join(config.stateDir ?? effectiveInstanceRoot(), 'hq', 'seen-generation'), localPath: join(config.stateDir ?? effectiveInstanceRoot(), 'hq', 'local.json') } : hqDeps);
|
|
77
78
|
};
|
|
78
|
-
const emit = (value: unknown, json?: boolean, text?: string)
|
|
79
|
-
|
|
79
|
+
const emit = (value: unknown, json?: boolean, text?: string): void | Promise<void> => {
|
|
80
|
+
const line = json ? JSON.stringify(value) : text ?? JSON.stringify(value);
|
|
81
|
+
if (json && out === console) return writeStdoutFully(line);
|
|
82
|
+
out.log(line);
|
|
83
|
+
};
|
|
84
|
+
const fail = (action: () => void | Promise<void>): void | Promise<void> => {
|
|
85
|
+
const wrap = (e: unknown) => new Error(`decisions: ${e instanceof Error ? e.message : String(e)}`);
|
|
86
|
+
try {
|
|
87
|
+
const result = action();
|
|
88
|
+
return result instanceof Promise ? result.catch(e => { throw wrap(e); }) : result;
|
|
89
|
+
} catch (e) { throw wrap(e); }
|
|
90
|
+
};
|
|
80
91
|
root.command('linear-sync').description('열린 결정을 COO Linear 프로젝트에 투영하고 닫힌 결정을 동기화한다')
|
|
81
92
|
.option('--dry-run').option('--json').option('--hq-override')
|
|
82
93
|
.action(async (o: { dryRun?: boolean; json?: boolean; hqOverride?: boolean }) => {
|
|
83
94
|
if (!o.dryRun && !mayWrite('linear-sync', o.hqOverride)) return;
|
|
84
95
|
const result = await projectDecisionsToLinear({ stateDir: config.stateDir, dryRun: o.dryRun });
|
|
85
|
-
emit(result, o.json, result.reason ?? `생성 ${result.created} · 닫음 ${result.closed} · 건너뜀 ${result.skipped} · 실패 ${result.failed}${result.plan?.length ? `\n${result.plan.map(p => `${p.action} ${p.decisionId}${p.issue ? ` ${p.issue}` : ''}`).join('\n')}` : ''}`);
|
|
96
|
+
await emit(result, o.json, result.reason ?? `생성 ${result.created} · 닫음 ${result.closed} · 건너뜀 ${result.skipped} · 실패 ${result.failed}${result.plan?.length ? `\n${result.plan.map(p => `${p.action} ${p.decisionId}${p.issue ? ` ${p.issue}` : ''}`).join('\n')}` : ''}`);
|
|
86
97
|
});
|
|
87
98
|
root.command('raise').description('SCQA·선택지와 권고로 결정 항목을 올린다')
|
|
88
99
|
.requiredOption('--title <text>').requiredOption('--category <category>')
|
|
@@ -121,7 +132,7 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
121
132
|
...(o.resumeQuestion !== undefined ? { resume: { questionId: o.resumeQuestion, ...(o.run !== undefined ? { runId: o.run } : {}) } } : {}),
|
|
122
133
|
...(o.due ? { dueAt: dueAt(o.due) } : {}) });
|
|
123
134
|
if (entry.crossCheckSkipped === 'missing') console.error('교차 확인 없음 — --xcheck SEAT:메모 또는 --no-xcheck 이유');
|
|
124
|
-
emit(entry, o.json, `올림: ${formatDecisionRow(entry)}`);
|
|
135
|
+
return emit(entry, o.json, `올림: ${formatDecisionRow(entry)}`);
|
|
125
136
|
}));
|
|
126
137
|
root.command('record-seat').description('위임 범위에서 이미 내린 자리 결정을 사후 보고로 원장에 기록 (대표 카드 아님)')
|
|
127
138
|
.requiredOption('--seat <OP|MK|TC|UX>').requiredOption('--title <text>')
|
|
@@ -133,13 +144,13 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
133
144
|
if (!mayWrite('record-seat', o.hqOverride)) return;
|
|
134
145
|
const entry = new DecisionLedger(config).recordSeatDecision({ seat: o.seat, title: o.title, decision: o.decision,
|
|
135
146
|
delegation: o.delegation, ...(o.at ? { decidedAt: o.at } : {}), ...(o.ref.length ? { refs: o.ref } : {}) });
|
|
136
|
-
emit(entry, o.json, formatSeatDecisionRow(entry));
|
|
147
|
+
return emit(entry, o.json, formatSeatDecisionRow(entry));
|
|
137
148
|
}));
|
|
138
149
|
root.command('seat-report').description('밤사이 자리들의 사후 결정을 한 번에 조회 (기본 최근 24시간)')
|
|
139
150
|
.option('--since <date>', '조회 시작 UTC ISO 또는 Nd', '1d').option('--seat <OP|MK|TC|UX>').option('--json')
|
|
140
151
|
.action((o: { since: string; seat?: Seat; json?: boolean }) => fail(() => {
|
|
141
152
|
const rows = new DecisionLedger(config).seatReport({ since: date(o.since), seat: o.seat });
|
|
142
|
-
emit(rows, o.json, rows.length ? rows.map(formatSeatDecisionRow).join('\n') : '자리 결정 0건');
|
|
153
|
+
return emit(rows, o.json, rows.length ? rows.map(formatSeatDecisionRow).join('\n') : '자리 결정 0건');
|
|
143
154
|
}));
|
|
144
155
|
root.command('proact').description('선제성 기준선 — 지난 7일, 먼저 낸 수·채택 수·물어서야 드러난 수')
|
|
145
156
|
.option('--days <n>', 'KST 일수 (기본 7)', '7').option('--json')
|
|
@@ -147,17 +158,17 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
147
158
|
const days = Number(o.days);
|
|
148
159
|
if (!Number.isInteger(days) || days < 1) throw new Error('invalid days');
|
|
149
160
|
const meter = readProactMeter({ ...(config.stateDir ? { stateDir: config.stateDir, instanceRoot: config.stateDir } : {}), ...(config.now ? { now: config.now() } : {}), days });
|
|
150
|
-
emit(meter, o.json, formatProactMeter(meter));
|
|
161
|
+
return emit(meter, o.json, formatProactMeter(meter));
|
|
151
162
|
}));
|
|
152
163
|
root.command('list').description('결정 목록 (기본 열린 것)')
|
|
153
164
|
.option('--status <open|decided|all>', '기본 open', 'open').option('--since <date>').option('--version <version>')
|
|
154
165
|
.option('--decided-by <human|auto>').option('--category <category>').option('--json')
|
|
155
166
|
.action((o: { status: 'open' | 'decided' | 'all'; since?: string; version?: string; decidedBy?: 'human' | 'auto'; category?: DecisionCategory; json?: boolean }) => fail(() => {
|
|
156
167
|
const rows = new DecisionLedger(config).list({ status: o.status, since: date(o.since), version: o.version, decidedBy: o.decidedBy, category: o.category });
|
|
157
|
-
emit(rows, o.json, rows.length ? rows.map(formatDecisionRow).join('\n') : '결정 0건');
|
|
168
|
+
return emit(rows, o.json, rows.length ? rows.map(formatDecisionRow).join('\n') : '결정 0건');
|
|
158
169
|
}));
|
|
159
170
|
root.command('show <id>').description('SCQA · 선택지 · 권고 · 이력 · 판').option('--json')
|
|
160
|
-
.action((id: string, o: { json?: boolean }) => fail(() => { const entry = new DecisionLedger(config).show(id); emit(entry, o.json, formatDecisionDetail(entry)); }));
|
|
171
|
+
.action((id: string, o: { json?: boolean }) => fail(() => { const entry = new DecisionLedger(config).show(id); return emit(entry, o.json, formatDecisionDetail(entry)); }));
|
|
161
172
|
root.command('decide <id> <option>').description('사람 또는 AUTO 위임 결정 기록')
|
|
162
173
|
.option('--note <text>').option('--auto').option('--delegation <reason>').option('--track <track>').option('--agent <agent>').option('--json').option('--hq-override')
|
|
163
174
|
.action((id: string, choice: string, o: { note?: string; auto?: boolean; delegation?: string; track?: DecisionTrack; agent?: string; json?: boolean; hqOverride?: boolean }) => fail(() => {
|
|
@@ -169,17 +180,16 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
169
180
|
if (delivery && !delivery.ok) {
|
|
170
181
|
// The decision is recorded; only the answer to the waiting run failed — say so and how to retry, never «success».
|
|
171
182
|
const hint = `⚠ 답 전달 실패(${delivery.questionId} · ${delivery.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-answer ${entry.id}`;
|
|
172
|
-
emit({ ...entry, delivery }, o.json, `결정: ${formatDecisionDetail(entry)}\n${hint}`);
|
|
173
183
|
process.exitCode = 3;
|
|
174
|
-
return;
|
|
184
|
+
return emit({ ...entry, delivery }, o.json, `결정: ${formatDecisionDetail(entry)}\n${hint}`);
|
|
175
185
|
}
|
|
176
|
-
emit(delivery ? { ...entry, delivery } : entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
|
|
186
|
+
return emit(delivery ? { ...entry, delivery } : entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
|
|
177
187
|
}));
|
|
178
188
|
root.command('retry-answer <id>').description('기록된 결정의 대기 질문 답 전달만 재시도한다').option('--json').option('--hq-override')
|
|
179
189
|
.action((id: string, o: { json?: boolean; hqOverride?: boolean }) => fail(() => {
|
|
180
190
|
if (!mayWrite('retry-answer', o.hqOverride)) return;
|
|
181
191
|
const entry = new DecisionLedger(config).retryAnswer(id);
|
|
182
|
-
emit(entry, o.json, `답 전달: ${entry.id} → ${entry.resume?.questionId}`);
|
|
192
|
+
return emit(entry, o.json, `답 전달: ${entry.id} → ${entry.resume?.questionId}`);
|
|
183
193
|
}));
|
|
184
194
|
root.command('add-options <id>').description('선택지가 미기재된 과거 항목에 확인된 선택지를 추가')
|
|
185
195
|
.requiredOption('--option <key=label:consequence>', '선택지 (두 번 이상)', repeat, [] as string[])
|
|
@@ -188,15 +198,15 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
188
198
|
const who = agent(o.agent);
|
|
189
199
|
if (!mayWrite('add-options', o.hqOverride)) return;
|
|
190
200
|
const entry = new DecisionLedger(config).addOptions(id, o.option.map(parseOption), who);
|
|
191
|
-
emit(entry, o.json, formatDecisionDetail(entry));
|
|
201
|
+
return emit(entry, o.json, formatDecisionDetail(entry));
|
|
192
202
|
}));
|
|
193
203
|
root.command('withdraw <id>').description('결정 철회도 원장에 남긴다').requiredOption('--reason <reason>').option('--json').option('--hq-override')
|
|
194
|
-
.action((id: string, o: { reason: string; json?: boolean; hqOverride?: boolean }) => fail(() => { if (!mayWrite('withdraw', o.hqOverride)) return; const entry = new DecisionLedger(config).withdraw(id, o.reason); emit(entry, o.json, `철회: ${formatDecisionDetail(entry)}`); }));
|
|
204
|
+
.action((id: string, o: { reason: string; json?: boolean; hqOverride?: boolean }) => fail(() => { if (!mayWrite('withdraw', o.hqOverride)) return; const entry = new DecisionLedger(config).withdraw(id, o.reason); return emit(entry, o.json, `철회: ${formatDecisionDetail(entry)}`); }));
|
|
195
205
|
root.command('import-markdown <file>').description('기존 대표 결정 문서 씨앗을 가져온다 (재실행 안전)').option('--json').option('--hq-override')
|
|
196
206
|
.action((file: string, o: { json?: boolean; hqOverride?: boolean }) => fail(() => {
|
|
197
207
|
if (!mayWrite('import-markdown', o.hqOverride)) return;
|
|
198
208
|
const result = importDecisionMarkdown(new DecisionLedger(config), file);
|
|
199
|
-
emit(result, o.json, `가져옴 ${result.imported.length} · 기존 ${result.existing.length} · 불완전 ${result.incomplete.length} · 못 읽음 ${result.unread.length}${result.incomplete.length ? `\n${result.incomplete.join('\n')}` : ''}${result.unread.length ? `\n${result.unread.join('\n')}` : ''}`);
|
|
200
209
|
if (result.unread.length) process.exitCode = 1;
|
|
210
|
+
return emit(result, o.json, `가져옴 ${result.imported.length} · 기존 ${result.existing.length} · 불완전 ${result.incomplete.length} · 못 읽음 ${result.unread.length}${result.incomplete.length ? `\n${result.incomplete.join('\n')}` : ''}${result.unread.length ? `\n${result.unread.join('\n')}` : ''}`);
|
|
201
211
|
}));
|
|
202
212
|
}
|
|
@@ -79,7 +79,7 @@ export function renderModelInput(report: ModelInputReport): string {
|
|
|
79
79
|
`model input tokens · ${report.since} ~ ${report.until} · stores=${report.stores.join(', ') || '(없음)'} · records=${report.records}`,
|
|
80
80
|
'scope\tnodeKind\tmeasured\tmedian\tp90\t못 잼',
|
|
81
81
|
...(report.baselines.length === 0 ? ['(관측 표본 없음)'] : report.baselines.map((item) =>
|
|
82
|
-
`${item.scope}\t${item.nodeKind}\t${item.measured}\t${item.median ?? '
|
|
82
|
+
`${item.scope}\t${item.nodeKind}\t${item.measured}\t${item.median ?? '못 잼'}\t${item.p90 ?? '못 잼'}\t${item.unmeasured}`)),
|
|
83
83
|
].join('\n');
|
|
84
84
|
}
|
|
85
85
|
|
package/src/cli/ops-cli.ts
CHANGED
|
@@ -213,6 +213,17 @@ opsCmd.command('status').description('현재 상태 종합(미션·태스크·
|
|
|
213
213
|
}
|
|
214
214
|
return o.allInstances ? runOpsFleet(o.json === true, o.includeTest === true) : runOps('snapshot', o);
|
|
215
215
|
});
|
|
216
|
+
// OPS-OVERVIEW-CLI (RFC-ops-overview-flow-health-cli-2026-10-08) — 판정 먼저 · 이유 사슬 · 절. 못 잼 = null(0 아님).
|
|
217
|
+
opsCmd.command('overview').description('흐름 한 장 — 저작→구현→착지가 흐르나(판정 먼저·이유 사슬) · 판·일꾼·기계·착지·루프 · 못 잼은 null · exit 0=흐름 정상/저하 3=그 밖 1=수집 실패')
|
|
218
|
+
.option('--json', '칸 꼴 그대로 ⊕ 머리 {verdict, reasons, nextActions, meta.elapsedMs}')
|
|
219
|
+
.option('--watch [seconds]', '주기 재조회(기본 30초)')
|
|
220
|
+
.option('--since <window>', '착지 창(<n>m|h|d · 기본 1h)', '1h')
|
|
221
|
+
.option('--owner <owner>', '일꾼 절 거르기 — seat:TC · TC · unassigned · all')
|
|
222
|
+
.option('--version <v>', '판(기본: 다음 컷)')
|
|
223
|
+
.action(async (o: { json?: boolean; watch?: string | boolean; since?: string; owner?: string; version?: string }) => {
|
|
224
|
+
const { runOpsOverview } = await import('./ops-overview-cli.js');
|
|
225
|
+
process.exitCode = await runOpsOverview(o);
|
|
226
|
+
});
|
|
216
227
|
opsCmd.command('health').description('이상 판정만(blocked·errored·stale)').option('--json')
|
|
217
228
|
.action((o: OpsOpts) => runOps('health', o));
|
|
218
229
|
opsCmd.command('timeline').description('상태 전이 최근순 통합')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
import { collectOverview, parseSince } from '../ops/overview-collect.js';
|
|
3
|
+
import { computeVerdict, renderOverview, unmeasuredCells, verdictExitCode, VERDICT_LABEL } from '../ops/overview.js';
|
|
4
|
+
import { writeStdoutJson } from './stdout-json.js';
|
|
5
|
+
|
|
6
|
+
export interface OpsOverviewOptions { json?: boolean; watch?: string | boolean; since?: string; owner?: string; version?: string }
|
|
7
|
+
|
|
8
|
+
/** 한 번 모아서 내고 exit code 를 돌려준다(RFC §A4: flowing·degraded 0 · 그 밖 3 · 수집 실패 1). */
|
|
9
|
+
async function once(o: OpsOverviewOptions, previous: string | null): Promise<{ code: number; verdict: string | null }> {
|
|
10
|
+
const started = performance.now();
|
|
11
|
+
let since: { ms: number; label: string };
|
|
12
|
+
try { since = parseSince(o.since); } catch (error) { console.error(String((error as Error).message)); return { code: 1, verdict: null }; }
|
|
13
|
+
try {
|
|
14
|
+
const snapshot = await collectOverview({ sinceMs: since.ms, sinceLabel: since.label, ...(o.owner ? { owner: o.owner } : {}), ...(o.version ? { version: o.version } : {}) });
|
|
15
|
+
const result = computeVerdict(snapshot);
|
|
16
|
+
const elapsedMs = Math.round(performance.now() - started);
|
|
17
|
+
const unmeasured = unmeasuredCells(snapshot);
|
|
18
|
+
debug.log('ops.overview', 'computed', { verdict: result.verdict, elapsedMs, unmeasured });
|
|
19
|
+
debug.flush();
|
|
20
|
+
if (o.json) {
|
|
21
|
+
await writeStdoutJson(JSON.stringify({ verdict: result.verdict, verdictLabel: VERDICT_LABEL[result.verdict], reasons: result.reasons, nextActions: result.nextActions,
|
|
22
|
+
meta: { elapsedMs, source: 'local', unmeasured }, ...snapshot }, null, 2) + '\n');
|
|
23
|
+
} else {
|
|
24
|
+
const text = renderOverview(snapshot, result, { elapsedMs });
|
|
25
|
+
if (previous !== null && previous !== result.verdict) console.log(`🔔 판정 바뀜: ${previous} → ${result.verdict}`);
|
|
26
|
+
console.log(text);
|
|
27
|
+
}
|
|
28
|
+
return { code: verdictExitCode(result.verdict), verdict: result.verdict };
|
|
29
|
+
} catch (error) {
|
|
30
|
+
debug.log('ops.overview', 'failed', { reason: String(error) });
|
|
31
|
+
debug.flush();
|
|
32
|
+
console.error(`ops overview 수집 실패: ${String(error)}`);
|
|
33
|
+
return { code: 1, verdict: null };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function runOpsOverview(o: OpsOverviewOptions): Promise<number> {
|
|
38
|
+
// 독립 CLI 프로세스는 데몬 StoreSink 를 물려받지 않는다 — 등록 없이는 debug.log 가 logs.db 에 안 닿는다(관측 안 한 것).
|
|
39
|
+
try { await (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink('cli'); } catch { /* fail-open */ }
|
|
40
|
+
if (o.watch === undefined || o.watch === false) return (await once(o, null)).code;
|
|
41
|
+
const seconds = o.watch === true ? 30 : Number(o.watch);
|
|
42
|
+
if (!Number.isFinite(seconds) || seconds < 5) { console.error('--watch 는 5초 이상'); return 1; }
|
|
43
|
+
let previous: string | null = null;
|
|
44
|
+
for (;;) {
|
|
45
|
+
if (!o.json) process.stdout.write('\x1b[2J\x1b[H');
|
|
46
|
+
const r = await once(o, previous);
|
|
47
|
+
previous = r.verdict ?? previous;
|
|
48
|
+
await new Promise((res) => setTimeout(res, seconds * 1000));
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/cli/pod-cli.ts
CHANGED
|
@@ -151,6 +151,7 @@ export function registerPodCommands(program: Command, deps: PodCliDeps = {}): vo
|
|
|
151
151
|
try {
|
|
152
152
|
const result = await run({
|
|
153
153
|
command: commandArgs,
|
|
154
|
+
returnLogs: true,
|
|
154
155
|
...(opts.pool ? { pool: opts.pool } : {}),
|
|
155
156
|
...(skills.length ? { skills } : {}),
|
|
156
157
|
...(opts.llm === 'grok' ? { llm: 'grok' as const } : {}),
|
package/src/cli/pr-cli.ts
CHANGED
|
@@ -62,6 +62,9 @@ import { enqueueL8ShadowQueue, runL8ShadowQueue, shadowPrNumber, statusL8ShadowQ
|
|
|
62
62
|
export { branchLineageSlug, findSiblingPrs };
|
|
63
63
|
|
|
64
64
|
export interface PrLandOpts {
|
|
65
|
+
/** Pin an existing PR and its reviewed head; both must be supplied together. */
|
|
66
|
+
pr?: string;
|
|
67
|
+
expectedHead?: string;
|
|
65
68
|
base?: string;
|
|
66
69
|
cwd?: string;
|
|
67
70
|
dryRun?: boolean;
|
|
@@ -1180,10 +1183,33 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1180
1183
|
|
|
1181
1184
|
const cwd = opts.cwd ?? process.cwd();
|
|
1182
1185
|
const run = deps.run ?? defaultCmdRunner;
|
|
1186
|
+
const pinned = opts.pr !== undefined || opts.expectedHead !== undefined;
|
|
1187
|
+
let pinnedBranch: string | undefined;
|
|
1188
|
+
let pinnedUrl: string | undefined;
|
|
1189
|
+
if (pinned) {
|
|
1190
|
+
const pr = Number(opts.pr);
|
|
1191
|
+
if (!/^[1-9]\d*$/.test(opts.pr ?? '') || !Number.isSafeInteger(pr) || !/^[a-f0-9]{40}$/i.test(opts.expectedHead ?? '') || opts.hold || opts.dryRun) {
|
|
1192
|
+
out.error('✗ expected-head: --pr and --expected-head (full SHA) are required together without --hold/--dry-run');
|
|
1193
|
+
return 1;
|
|
1194
|
+
}
|
|
1195
|
+
const viewed = run('gh', ['pr', 'view', String(pr), '--json', 'headRefOid,headRefName,state,isDraft,url'], { cwd });
|
|
1196
|
+
let value: { headRefOid?: string; headRefName?: string; state?: string; isDraft?: boolean; url?: string } = {};
|
|
1197
|
+
try { if (viewed.ok) value = JSON.parse(viewed.out) as typeof value; } catch { /* unreadable is not approval */ }
|
|
1198
|
+
const local = run('git', ['rev-parse', 'HEAD'], { cwd });
|
|
1199
|
+
const dirty = run('git', ['status', '--porcelain'], { cwd });
|
|
1200
|
+
if (value.state !== 'OPEN' || value.isDraft !== false || value.headRefOid?.toLowerCase() !== opts.expectedHead!.toLowerCase()
|
|
1201
|
+
|| !value.url?.endsWith(`/pull/${pr}`) || !value.headRefName || !local.ok || local.out.trim().toLowerCase() !== opts.expectedHead!.toLowerCase()
|
|
1202
|
+
|| !dirty.ok || dirty.out.trim()) {
|
|
1203
|
+
out.error('✗ expected-head: PR OPEN non-draft, matching local HEAD and clean worktree required');
|
|
1204
|
+
return 1;
|
|
1205
|
+
}
|
|
1206
|
+
pinnedBranch = value.headRefName;
|
|
1207
|
+
pinnedUrl = value.url;
|
|
1208
|
+
}
|
|
1183
1209
|
const resolveBase = deps.resolveBase ?? resolveDeliverableBase;
|
|
1184
1210
|
const branch = (deps.currentBranch ?? liveCurrentBranch)(cwd);
|
|
1185
|
-
if (!branch) {
|
|
1186
|
-
const detail = '현재 브랜치를 해석하지 못했습니다.';
|
|
1211
|
+
if (!branch || (pinned && branch !== pinnedBranch)) {
|
|
1212
|
+
const detail = pinned ? 'PR head branch와 현재 브랜치가 다릅니다.' : '현재 브랜치를 해석하지 못했습니다.';
|
|
1187
1213
|
record('branch', false);
|
|
1188
1214
|
out.error(`✗ branch: ${detail}`);
|
|
1189
1215
|
return 1;
|
|
@@ -1567,6 +1593,10 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1567
1593
|
});
|
|
1568
1594
|
}
|
|
1569
1595
|
const hold = !!opts.hold || overlapDecision?.outcome === 'user-hold';
|
|
1596
|
+
if (pinned && overlapDecision && overlapDecision.outcome !== 'user-merge') {
|
|
1597
|
+
out.error('✗ expected-head: overlap merge approval unavailable for the reviewed head');
|
|
1598
|
+
return 1;
|
|
1599
|
+
}
|
|
1570
1600
|
|
|
1571
1601
|
const manager = deps.manager ?? makePrManager(run);
|
|
1572
1602
|
const existing = manager.findPrForBranchOutcome(branch, cwd);
|
|
@@ -1638,7 +1668,12 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1638
1668
|
}
|
|
1639
1669
|
}
|
|
1640
1670
|
|
|
1641
|
-
|
|
1671
|
+
// A pinned, already-reviewed commit must not go through upsertPr (git add/commit/force-push/PR edit).
|
|
1672
|
+
const upsert = pinned
|
|
1673
|
+
? existing.status === 'ok OUTPUT' && existing.url === pinnedUrl
|
|
1674
|
+
? { ok: true as const, url: pinnedUrl!, reused: true }
|
|
1675
|
+
: { ok: false as const, reason: 'gh' as const, detail: 'pinned PR is not the branch open PR' }
|
|
1676
|
+
: manager.upsertPr({
|
|
1642
1677
|
branch,
|
|
1643
1678
|
worktreePath: cwd,
|
|
1644
1679
|
base,
|
|
@@ -1654,7 +1689,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1654
1689
|
...(excludingActiveRunFiles ? { excludePaths } : {}),
|
|
1655
1690
|
});
|
|
1656
1691
|
if (!upsert.ok) {
|
|
1657
|
-
if (upsert.reason === 'noop' && excludingActiveRunFiles) {
|
|
1692
|
+
if (upsert.reason === 'noop' && excludingActiveRunFiles && !pinned) {
|
|
1658
1693
|
record('upsert-ready-noop', true, { excludePaths, detail: upsert.detail });
|
|
1659
1694
|
out.log(`✓ upsert-ready: 제외 후 올릴 것이 없습니다 — ${upsert.detail}`);
|
|
1660
1695
|
return 0;
|
|
@@ -1664,6 +1699,13 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1664
1699
|
return 1;
|
|
1665
1700
|
}
|
|
1666
1701
|
record('upsert-ready', true);
|
|
1702
|
+
if (pinned) {
|
|
1703
|
+
const upsertHead = run('git', ['rev-parse', 'HEAD'], { cwd });
|
|
1704
|
+
if (!upsert.reused || upsert.url !== pinnedUrl || !upsertHead.ok || upsertHead.out.trim().toLowerCase() !== opts.expectedHead!.toLowerCase()) {
|
|
1705
|
+
out.error('✗ expected-head: pinned PR identity or reviewed HEAD changed');
|
|
1706
|
+
return 1;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1667
1709
|
out.log(`✓ upsert-ready: ${upsert.url}${upsert.reused ? ' (기존 PR)' : ' (새 PR)'}`);
|
|
1668
1710
|
|
|
1669
1711
|
if (hold) {
|
|
@@ -1688,21 +1730,34 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1688
1730
|
debug.log('harness.merge', 'frozen', { prUrl: upsert.url, reason: frozen.reason, until: frozen.until });
|
|
1689
1731
|
record('freeze', true, { url: upsert.url, reason: frozen.reason, until: frozen.until });
|
|
1690
1732
|
out.log(`✓ ready: ${upsert.url} — ${landingFreezeMessage(frozen)} · 병합 연기`);
|
|
1691
|
-
return 0;
|
|
1733
|
+
return pinned ? 1 : 0;
|
|
1692
1734
|
}
|
|
1693
1735
|
if (admission.kind === 'taken') {
|
|
1694
1736
|
record('freeze', true, { url: upsert.url, resumedElsewhere: true });
|
|
1695
1737
|
out.log(`✓ ready: ${upsert.url} — 동결이 막 풀려 보류 병합 재개가 이 PR 을 맡았습니다`);
|
|
1696
|
-
return 0;
|
|
1738
|
+
return pinned ? 1 : 0;
|
|
1697
1739
|
}
|
|
1698
1740
|
const landing = admission;
|
|
1741
|
+
if (pinned) {
|
|
1742
|
+
const view = run('gh', ['pr', 'view', String(opts.pr), '--json', 'headRefOid,state,isDraft'], { cwd });
|
|
1743
|
+
let current: { headRefOid?: string; state?: string; isDraft?: boolean } = {};
|
|
1744
|
+
try { if (view.ok) current = JSON.parse(view.out) as typeof current; } catch { /* fail closed */ }
|
|
1745
|
+
const finalHead = run('git', ['rev-parse', 'HEAD'], { cwd });
|
|
1746
|
+
if (current.headRefOid?.toLowerCase() !== opts.expectedHead!.toLowerCase() || current.state !== 'OPEN' || current.isDraft !== false
|
|
1747
|
+
|| !finalHead.ok || finalHead.out.trim().toLowerCase() !== opts.expectedHead!.toLowerCase()) {
|
|
1748
|
+
landing.end(false);
|
|
1749
|
+
out.error('✗ expected-head: PR head/state changed before merge');
|
|
1750
|
+
return 1;
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1699
1753
|
let merged: ReturnType<typeof manager.mergePrOutcome>;
|
|
1700
1754
|
try {
|
|
1701
|
-
merged = manager.mergePrOutcome(upsert.url);
|
|
1755
|
+
merged = manager.mergePrOutcome(upsert.url, pinned ? opts.expectedHead : undefined, pinned ? cwd : undefined);
|
|
1702
1756
|
// `GIT-S14` — 병합이 «미완료(OPEN)»로 끝났고 GitHub 가 아직 `mergeable=UNKNOWN`(병합 가능 여부 계산 중)이면
|
|
1703
1757
|
// 짧게 기다렸다 다시 병합한다. 표본 셋(08-25 · 09-24 🅢 #20233 등)이 모두 «같은 명령 재시도에 병합»이었다.
|
|
1704
1758
|
// ⛔ UNKNOWN 일 때만 재시도한다 — CONFLICTING 등 다른 값은 기다려도 안 풀린다(그대로 실패를 낸다).
|
|
1705
1759
|
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
1760
|
+
// pinned 도 재시도한다 — mergePrOutcome 이 머리를 다시 확인하고 --match-head-commit 으로 병합하므로 바뀐 머리로는 안 들어간다.
|
|
1706
1761
|
for (let attempt = 1; !merged.ok && merged.kind === 'not-merged' && merged.state === 'OPEN' && attempt <= PR_LAND_MERGEABLE_UNKNOWN_RETRIES; attempt += 1) {
|
|
1707
1762
|
const mergeable = run('gh', ['pr', 'view', upsert.url, '--json', 'mergeable', '--jq', '.mergeable'], { cwd });
|
|
1708
1763
|
const value = mergeable.ok ? mergeable.out.trim() : '';
|
|
@@ -1710,7 +1765,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1710
1765
|
record('merge-retry', true, { attempt, mergeable: value, waitMs: PR_LAND_MERGEABLE_UNKNOWN_WAIT_MS });
|
|
1711
1766
|
out.log(`⏳ merge: mergeable=UNKNOWN — GitHub 가 병합 가능 여부를 아직 계산 중입니다 · ${PR_LAND_MERGEABLE_UNKNOWN_WAIT_MS / 1000}초 뒤 다시 병합 (${attempt}/${PR_LAND_MERGEABLE_UNKNOWN_RETRIES})`);
|
|
1712
1767
|
await sleep(PR_LAND_MERGEABLE_UNKNOWN_WAIT_MS);
|
|
1713
|
-
merged = manager.mergePrOutcome(upsert.url);
|
|
1768
|
+
merged = manager.mergePrOutcome(upsert.url, pinned ? opts.expectedHead : undefined, pinned ? cwd : undefined);
|
|
1714
1769
|
}
|
|
1715
1770
|
} finally { landing.end(merged!?.ok === true); }
|
|
1716
1771
|
if (!merged.ok) {
|
|
@@ -1781,6 +1836,8 @@ export function registerPrCommands(program: Command, deps: PrLandDeps = {}, queu
|
|
|
1781
1836
|
.description('현재 브랜치 PR을 생성 또는 갱신해 ready 상태로 만들고 squash merge')
|
|
1782
1837
|
.option('--base <branch>', 'PR base branch')
|
|
1783
1838
|
.option('--cwd <path>', '작업 트리 경로')
|
|
1839
|
+
.option('--pr <number>', '기존 PR 번호 고정 (--expected-head 와 함께)')
|
|
1840
|
+
.option('--expected-head <sha>', '리뷰된 PR 머리 SHA 고정 (--pr 와 함께)')
|
|
1784
1841
|
.option('--dry-run', '변경 없이 landing 계획만 출력')
|
|
1785
1842
|
.option('--hold', 'PR을 생성 또는 갱신한 뒤 병합하지 않고 쌓아 둔다')
|
|
1786
1843
|
.option('--title <title>', 'PR title')
|
package/src/cli/release-cli.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// ⛔ 공개본은 «원본 매니페스트»(`release/public-export.yaml`)대로만 만든다 — 매매 실행 코드는 그 매니페스트가 이미 뺀다(🅢 #20529).
|
|
19
19
|
import { spawnSync } from 'node:child_process';
|
|
20
20
|
import { createHash } from 'node:crypto';
|
|
21
|
-
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
22
22
|
import { tmpdir } from 'node:os';
|
|
23
23
|
import { dirname, join, resolve } from 'node:path';
|
|
24
24
|
import type { Command } from 'commander';
|
|
@@ -27,7 +27,7 @@ import { effectiveInstanceRoot, releaseLedgerRoot } from '../instance/resolve.js
|
|
|
27
27
|
import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
|
|
28
28
|
import { envLiteral } from '../platform/env-literal.js';
|
|
29
29
|
import { getUserConfig, userConfigPath } from '../user-config.js';
|
|
30
|
-
import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, devVersion, listChecklist, ownerMatches, parseOwner, parityGap, removeItem, renderRefsStatus, seedFromRoadmap, setItem, summarizeChecklist, type ChecklistStatus, type ChecklistDisposition, type ChecklistKind } from '../release-loop/checklist.js';
|
|
30
|
+
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
31
|
import * as features from '../release-loop/feature-store.js';
|
|
32
32
|
import { evidencePlan, landedButYellow, type MergedChecklistPr } from '../release-loop/landed-but-yellow.js';
|
|
33
33
|
import { formatSchedule, getSchedule, listSchedules, setSchedule } from '../release-loop/release-schedule.js';
|
|
@@ -705,11 +705,28 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
705
705
|
console.log(`루브릭 없는 칸 ${missing}`);
|
|
706
706
|
});
|
|
707
707
|
withContext(checklist.command('refs <doc>').description('문서를 인용하는 칸 — 모든 판의 구현 현황(읽기 전용)'))
|
|
708
|
-
.
|
|
708
|
+
.option('--lint', '문서 절과 칸 인용을 양방향 대조(읽기 전용)')
|
|
709
|
+
.action(async (doc: string, opts: { lint?: boolean }, cmd: Command) => {
|
|
709
710
|
if (!doc.trim() || doc.trim().startsWith('#')) throw new CliUserError(`잘못된 문서: ${doc}`, '저장소 상대 경로[#절] — 예: docs/RFC-x.md#§3');
|
|
710
711
|
const { json } = context(cmd);
|
|
711
712
|
const ledgerRoot = releaseLedgerRoot();
|
|
712
|
-
const
|
|
713
|
+
const checklists = features.assignedVersions(ledgerRoot).map((version) => listChecklist(version, ledgerRoot));
|
|
714
|
+
if (opts.lint) {
|
|
715
|
+
const path = doc.trim().split('#')[0]!.replace(/^\.\//, '');
|
|
716
|
+
const roots = refRoots();
|
|
717
|
+
normalizeRefs([path], roots);
|
|
718
|
+
const file = roots.map((root) => join(root, path)).find((candidate) => {
|
|
719
|
+
try { return statSync(candidate).isFile(); } catch { return false; }
|
|
720
|
+
})!;
|
|
721
|
+
const result = lintDocRefs(path, readFileSync(file, 'utf8'), checklists);
|
|
722
|
+
debug.log('release.checklist', 'refs-lint', { doc, sections: result.sections.length, uncovered: result.uncoveredSections.length, dangling: result.danglingRefs.length });
|
|
723
|
+
if (json) { await writeStdoutJson(`${JSON.stringify({ doc, ...result })}\n`); return; }
|
|
724
|
+
console.log(`칸 없는 절: ${result.uncoveredSections.join(', ') || '없음'}`);
|
|
725
|
+
console.log(`없는 절을 가리키는 칸: ${result.danglingRefs.map(({ version, id, ref }) => `${version} ${id} ${ref}`).join(' · ') || '없음'}`);
|
|
726
|
+
console.log(`절 ${result.sections.length} · 칸 없는 절 ${result.uncoveredSections.length} · 없는 절을 가리키는 칸 ${result.danglingRefs.length}`);
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
const rows = cellsReferencingDoc(doc, checklists);
|
|
713
730
|
const byStatus = { green: 0, yellow: 0, red: 0, done: 0 } as Record<ChecklistStatus, number>;
|
|
714
731
|
for (const row of rows) byStatus[row.status] += 1;
|
|
715
732
|
debug.log('release.checklist', 'refs-read', { doc, rows: rows.length });
|