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
|
@@ -19,10 +19,13 @@ import { setInProcessOutbound } from '../../domains/outbound-alert.js';
|
|
|
19
19
|
import { getUserConfig } from '../../user-config.js';
|
|
20
20
|
import type { TelegramEvent } from '../../workflow-runtime/triggers/telegram-source.js';
|
|
21
21
|
import { spawnSync } from 'node:child_process';
|
|
22
|
-
import { isAbsolute } from 'node:path';
|
|
22
|
+
import { isAbsolute, join, dirname, relative } from 'node:path';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { readdirSync, realpathSync, statSync } from 'node:fs';
|
|
23
25
|
import { createProject, listProjects } from '../../project/project-store.js';
|
|
24
26
|
import { handleOutputsGet, type OutputsDeps } from './outputs-route.js';
|
|
25
27
|
import { buildGridData, type GridDeps } from './grid.js';
|
|
28
|
+
import { createDraftMetricsSource, type DraftMetricsSource } from './draft-metrics.js';
|
|
26
29
|
import { DECISIONS_PATH, handleDecisions, type DecisionsRouteDeps } from './decisions-route.js';
|
|
27
30
|
import { OPS_BOARD_PATH, handleOpsBoard, type OpsBoardDeps } from './ops-board-route.js';
|
|
28
31
|
import { CARD_FOLLOWUP_PATH, createCardFollowupJobs, type CardFollowupJobs } from './card-followup-route.js';
|
|
@@ -31,6 +34,7 @@ import { compareTokenConstTime } from '../../acp/transport/auth.js';
|
|
|
31
34
|
import { ensureAuthToken } from '../../auth/acp-token.js';
|
|
32
35
|
import type { NexusState } from '../state/state.js';
|
|
33
36
|
import { DEFAULT_NEXUS_HTTP_PORT } from '../default-port.js';
|
|
37
|
+
|
|
34
38
|
export { DEFAULT_NEXUS_HTTP_PORT } from '../default-port.js';
|
|
35
39
|
import type { TabRegistry } from '../state/tab-registry.js';
|
|
36
40
|
import type { FeedbackEnvelope } from '../../feedback/envelope.js';
|
|
@@ -164,6 +168,7 @@ import {
|
|
|
164
168
|
} from './vault-api.js';
|
|
165
169
|
import { handleBuildsGet, parseBuildsPath } from './builds-api.js';
|
|
166
170
|
import { handleHarnessAskPost, handleHarnessAskStatusGet, handleHarnessRunEventsGet, handleHarnessRunScreenGet, handleHarnessRunsGet, handleHarnessStopPost } from './harness-api.js';
|
|
171
|
+
import { handleHarnessRunTraversalGet } from './harness-traversal.js';
|
|
167
172
|
import { handleLoopEdgesGet } from './loop-edges.js';
|
|
168
173
|
import { handleFabricPlans, type FabricPlansRouteOpts } from './fabric-plans.js';
|
|
169
174
|
import { dispatchPersonaRoute } from './personas.js';
|
|
@@ -365,11 +370,12 @@ import {
|
|
|
365
370
|
} from './workflows.js';
|
|
366
371
|
import { handleTriggersSnapshot } from './triggers.js';
|
|
367
372
|
import { handleWorkflowTemplatesList } from './workflow-templates.js';
|
|
368
|
-
import { handleGraphVersionsGet, handleGraphsGet, handleGraphsMutation } from './graphs-api.js';
|
|
373
|
+
import { graphAccessForRequest, handleGraphAccess, handleGraphAccessPut, handleGraphVersionsGet, handleGraphsGet, handleGraphsMutation } from './graphs-api.js';
|
|
369
374
|
import { handleGraphKindsGet, handleGraphsValidatePost } from './graph-kinds.js';
|
|
375
|
+
import { handleGraphWizardPost, handleGraphWizardPacksGet } from './graph-wizard-api.js';
|
|
370
376
|
import { syncInstalledPluginNodes } from '../../graph-kinds/installed-plugin-nodes.js';
|
|
371
377
|
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
372
|
-
import { handlePluginsIndexGet, handlePluginsGet, handlePluginsMarketRefresh, handlePluginsInstall, handlePluginsRemove } from './plugins-market.js';
|
|
378
|
+
import { handlePluginsIndexGet, handlePluginsGet, handlePluginsMarketRefresh, handlePluginsInstall, handlePluginsRemove, handlePluginWizardList, handlePluginWizardSave } from './plugins-market.js';
|
|
373
379
|
import { handlePluginsCredentialsGet, handlePluginsCredentialsPut } from './plugins-credentials-api.js';
|
|
374
380
|
import {
|
|
375
381
|
handleWorkflowsList,
|
|
@@ -426,6 +432,9 @@ import {
|
|
|
426
432
|
parseShowroomLayoutPath,
|
|
427
433
|
} from './showroom-layouts.js';
|
|
428
434
|
|
|
435
|
+
/** Process-wide DRAFT-METRIC cache (one background collection per TTL, shared by every page load). */
|
|
436
|
+
let sharedDraftMetrics: DraftMetricsSource | undefined;
|
|
437
|
+
|
|
429
438
|
export const NEXUS_HTTP_PORT_RANGE = 16; // try 31415..31430
|
|
430
439
|
/** Short timeout for the pre-bind localhost occupancy probe. */
|
|
431
440
|
export const NEXUS_PORT_PROBE_TIMEOUT_MS = 400;
|
|
@@ -480,11 +489,17 @@ export type NexusWsBridgeInit = Omit<WsBridgeOpts, 'hostname' | 'port'>;
|
|
|
480
489
|
export interface NexusHttpServerOpts {
|
|
481
490
|
/** Optional fabric-plan ledger and decomposition seam; production uses the instance root and existing fabric decomposer. */
|
|
482
491
|
fabricPlans?: FabricPlansRouteOpts;
|
|
492
|
+
/** GRAPH-WIZARD 시험 주입(LLM·템플릿 뿌리). 운영은 비워 둔다. */
|
|
493
|
+
graphWizard?: import('../../graph-wizard/generate.js').GraphWizardDeps;
|
|
494
|
+
/** Roots the remote folder picker may browse (default: the daemon user's home). Tests inject a temp root. */
|
|
495
|
+
projectFolderRoots?: string[];
|
|
483
496
|
/** Optional installer state root for isolated API consumers and tests. */
|
|
484
497
|
pluginStateRoot?: string;
|
|
485
498
|
outputs?: OutputsDeps;
|
|
486
499
|
/** Read-only grid measurement seam; omitted in production for live HQ and Pod pool reads. */
|
|
487
500
|
grid?: GridDeps;
|
|
501
|
+
/** DRAFT-METRIC cached source seam; omitted in production for the process-wide TTL cache. */
|
|
502
|
+
draftMetrics?: DraftMetricsSource;
|
|
488
503
|
decisions?: Pick<DecisionsRouteDeps, 'ledger'>;
|
|
489
504
|
opsBoard?: Pick<OpsBoardDeps, 'openStore'>;
|
|
490
505
|
cardFollowup?: CardFollowupJobs;
|
|
@@ -835,6 +850,55 @@ export function handleProjectsGet(): Response {
|
|
|
835
850
|
return jsonResponse({ projects: listProjects() });
|
|
836
851
|
}
|
|
837
852
|
|
|
853
|
+
function isWithinRoot(path: string, root: string): boolean {
|
|
854
|
+
const rel = relative(root, path);
|
|
855
|
+
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Remote folder picker: lists sub-folders under an allow-listed root only.
|
|
860
|
+
* Every path is resolved with realpath first, so `..` segments and symlinks cannot escape the roots;
|
|
861
|
+
* dot-folders are hidden and symlinked entries that point outside the roots are not listed.
|
|
862
|
+
*/
|
|
863
|
+
export function handleProjectFoldersGet(req: Request, roots: string[] = [homedir()]): Response {
|
|
864
|
+
const allowed: string[] = [];
|
|
865
|
+
for (const root of roots) {
|
|
866
|
+
try { allowed.push(realpathSync(root)); } catch { /* a missing root grants nothing */ }
|
|
867
|
+
}
|
|
868
|
+
if (allowed.length === 0) return jsonResponse({ error: 'folder_unavailable' }, 404);
|
|
869
|
+
const requested = new URL(req.url).searchParams.get('path') ?? allowed[0]!;
|
|
870
|
+
if (!isAbsolute(requested) || requested.includes('\0')) return jsonResponse({ error: 'invalid_folder' }, 400);
|
|
871
|
+
let path: string;
|
|
872
|
+
try { path = realpathSync(requested); }
|
|
873
|
+
catch {
|
|
874
|
+
debug.log('nexus.projects', 'folders-unavailable', { reason: 'missing' });
|
|
875
|
+
return jsonResponse({ error: 'folder_unavailable' }, 404);
|
|
876
|
+
}
|
|
877
|
+
if (!allowed.some(root => isWithinRoot(path, root))) {
|
|
878
|
+
debug.log('nexus.projects', 'folders-refused', { reason: 'outside-roots' });
|
|
879
|
+
return jsonResponse({ error: 'outside_allowed_roots' }, 403);
|
|
880
|
+
}
|
|
881
|
+
try {
|
|
882
|
+
if (!statSync(path).isDirectory()) return jsonResponse({ error: 'not_directory' }, 400);
|
|
883
|
+
const folders = readdirSync(path, { withFileTypes: true })
|
|
884
|
+
.filter(entry => {
|
|
885
|
+
if (entry.name.startsWith('.')) return false;
|
|
886
|
+
if (entry.isDirectory()) return true;
|
|
887
|
+
if (!entry.isSymbolicLink()) return false;
|
|
888
|
+
try {
|
|
889
|
+
const target = realpathSync(join(path, entry.name));
|
|
890
|
+
return statSync(target).isDirectory() && allowed.some(root => isWithinRoot(target, root));
|
|
891
|
+
} catch { return false; }
|
|
892
|
+
})
|
|
893
|
+
.map(entry => ({ name: entry.name, path: join(path, entry.name) }))
|
|
894
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
895
|
+
const atRoot = allowed.includes(path);
|
|
896
|
+
return jsonResponse({ path, parent: atRoot ? null : dirname(path), folders });
|
|
897
|
+
} catch {
|
|
898
|
+
return jsonResponse({ error: 'folder_unavailable' }, 404);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
838
902
|
export async function handleProjectsPost(req: Request): Promise<Response> {
|
|
839
903
|
let body: unknown;
|
|
840
904
|
try { body = await req.json(); }
|
|
@@ -985,7 +1049,9 @@ export async function routeRequest(
|
|
|
985
1049
|
const offered = req.headers.get('authorization');
|
|
986
1050
|
const fallbackAuthorized = fallbackToken !== undefined && offered?.startsWith('Bearer ') === true
|
|
987
1051
|
&& compareTokenConstTime(offered.slice('Bearer '.length).trim(), fallbackToken);
|
|
988
|
-
|
|
1052
|
+
const graphPeerAuthorized = (method === 'GET' || method === 'PUT')
|
|
1053
|
+
&& graphAccessForRequest(pathname, method, offered?.startsWith('Bearer ') ? offered.slice(7).trim() : null);
|
|
1054
|
+
if (!(opts.metaApi ? checkAuth(req, opts.metaApi) : fallbackAuthorized) && !graphPeerAuthorized) {
|
|
989
1055
|
const name = method === 'POST' && (pathname === '/v1/tasks' || pathname === '/v1/reports/ingest') && opts.metaApi
|
|
990
1056
|
? matchIngestAuthorization(req)?.name
|
|
991
1057
|
: undefined;
|
|
@@ -1360,6 +1426,13 @@ export async function routeRequest(
|
|
|
1360
1426
|
return handleHarnessRunEventsGet(req, opts.metaApi);
|
|
1361
1427
|
}
|
|
1362
1428
|
|
|
1429
|
+
// HARNESS-RUN-LIVE-GRAPH — one run's ordered node steps ⊕ journey band (PWA /live-run).
|
|
1430
|
+
if (pathname === '/v1/harness/run-traversal' && method === 'GET') {
|
|
1431
|
+
if (!opts.metaApi) return jsonResponse({ error: 'meta-api-runtime-not-wired' }, 503);
|
|
1432
|
+
if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1433
|
+
return handleHarnessRunTraversalGet(req);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1363
1436
|
// Design direction is a write: check owner auth before the handler reads the body.
|
|
1364
1437
|
// Keep this POST ahead of the mutation fallback, and never make it a public route.
|
|
1365
1438
|
if (method === 'POST' && pathname === DESIGN_DIRECTION_PATH) {
|
|
@@ -1389,11 +1462,27 @@ export async function routeRequest(
|
|
|
1389
1462
|
return handleGraphsValidatePost(req, opts.metaApi);
|
|
1390
1463
|
}
|
|
1391
1464
|
|
|
1465
|
+
// GRAPH-WIZARD — 설치된 팩 목록과 말 → 그래프 YAML(저장 안 함). 같은 소유자 인증.
|
|
1466
|
+
if (method === 'GET' && pathname === '/v1/graphs/wizard/packs') {
|
|
1467
|
+
if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
|
|
1468
|
+
if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1469
|
+
return handleGraphWizardPacksGet(opts.graphWizard);
|
|
1470
|
+
}
|
|
1471
|
+
if (method === 'POST' && pathname === '/v1/graphs/wizard') {
|
|
1472
|
+
if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
|
|
1473
|
+
if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1474
|
+
return handleGraphWizardPost(req, opts.graphWizard);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1392
1477
|
if (pathname === '/v1/fabric/decompose' || pathname.startsWith('/v1/fabric/plans/')) {
|
|
1393
1478
|
if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1394
1479
|
return handleFabricPlans(req, opts.fabricPlans);
|
|
1395
1480
|
}
|
|
1396
1481
|
|
|
1482
|
+
if (pathname === '/v1/projects/folders' && method === 'GET') {
|
|
1483
|
+
if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1484
|
+
return handleProjectFoldersGet(req, opts.projectFolderRoots);
|
|
1485
|
+
}
|
|
1397
1486
|
if (pathname === '/v1/projects' && (method === 'GET' || method === 'POST')) {
|
|
1398
1487
|
if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1399
1488
|
return method === 'GET' ? handleProjectsGet() : handleProjectsPost(req);
|
|
@@ -1437,6 +1526,12 @@ export async function routeRequest(
|
|
|
1437
1526
|
if (method !== 'GET') return jsonResponse({ error: 'method-not-allowed', method }, 405);
|
|
1438
1527
|
return jsonResponse(buildGridData(opts.grid));
|
|
1439
1528
|
}
|
|
1529
|
+
// DRAFT-METRIC: answers from memory; a stale/cold cache starts one background collection (never per request).
|
|
1530
|
+
if (pathname === '/v1/drafts/metrics') {
|
|
1531
|
+
if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1532
|
+
if (method !== 'GET') return jsonResponse({ error: 'method-not-allowed', method }, 405);
|
|
1533
|
+
return jsonResponse((opts.draftMetrics ?? (sharedDraftMetrics ??= createDraftMetricsSource())).read());
|
|
1534
|
+
}
|
|
1440
1535
|
if (method === 'GET' && pathname === '/v1/outputs') {
|
|
1441
1536
|
if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1442
1537
|
return handleOutputsGet(req, opts.outputs);
|
|
@@ -1484,6 +1579,10 @@ export async function routeRequest(
|
|
|
1484
1579
|
...opts.decisions,
|
|
1485
1580
|
});
|
|
1486
1581
|
}
|
|
1582
|
+
if (method === 'POST' && pathname === '/v1/plugins/wizard') {
|
|
1583
|
+
if (!opts.metaApi) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1584
|
+
return handlePluginWizardSave(req, opts.metaApi, opts.pluginStateRoot);
|
|
1585
|
+
}
|
|
1487
1586
|
if (method === 'POST' && pathname === '/v1/plugins/install') {
|
|
1488
1587
|
if (!opts.metaApi) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1489
1588
|
return handlePluginsInstall(req, opts.metaApi, opts.pluginStateRoot);
|
|
@@ -1503,10 +1602,19 @@ export async function routeRequest(
|
|
|
1503
1602
|
if (!opts.metaApi) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1504
1603
|
return handlePluginsRemove(req, pluginRemove[1]!, opts.metaApi, opts.pluginStateRoot);
|
|
1505
1604
|
}
|
|
1605
|
+
if (method === 'PUT' && /^\/v1\/graphs\/[^/]+\/access$/.test(pathname)) {
|
|
1606
|
+
if (!opts.metaApi || bearerCredential(req, opts.metaApi) === undefined) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1607
|
+
return handleGraphAccessPut(pathname, req);
|
|
1608
|
+
}
|
|
1506
1609
|
if ((method === 'PUT' || method === 'POST') && (pathname.startsWith('/v1/graphs/') || pathname === '/v1/graphs')) {
|
|
1507
1610
|
if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
|
|
1508
|
-
|
|
1509
|
-
|
|
1611
|
+
const peerMayEdit = method === 'PUT' && graphAccessForRequest(pathname, method,
|
|
1612
|
+
req.headers.get('authorization')?.startsWith('Bearer ') ? req.headers.get('authorization')!.slice(7).trim() : null);
|
|
1613
|
+
const ownerAuthorized = checkAuth(req, opts.metaApi);
|
|
1614
|
+
if (!ownerAuthorized && !peerMayEdit) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
1615
|
+
// A peer save is recorded on the graph so every run path refuses it until the owner approves (W9c run guard).
|
|
1616
|
+
const mutated = await handleGraphsMutation(pathname, req, {}, ownerAuthorized ? null
|
|
1617
|
+
: { peerToken: req.headers.get('authorization')!.slice(7).trim() });
|
|
1510
1618
|
if (mutated) return mutated;
|
|
1511
1619
|
}
|
|
1512
1620
|
const cardClose = /^\/v1\/task-cards\/([^/]+)\/close$/.exec(pathname);
|
|
@@ -2798,6 +2906,10 @@ export async function routeRequest(
|
|
|
2798
2906
|
// surface (`/v1/workflows` · `~/.elanous/workflows-runs/`) covers the same
|
|
2799
2907
|
// user need.
|
|
2800
2908
|
|
|
2909
|
+
if (method === 'GET' && pathname === '/v1/plugins/wizard') {
|
|
2910
|
+
if (!opts.metaApi) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
2911
|
+
return handlePluginWizardList(req, opts.metaApi, opts.pluginStateRoot);
|
|
2912
|
+
}
|
|
2801
2913
|
const pluginCredentialsGet = /^\/v1\/plugins\/([^/]+)\/credentials$/.exec(pathname);
|
|
2802
2914
|
if (method === 'GET' && pluginCredentialsGet) {
|
|
2803
2915
|
if (!opts.metaApi) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
@@ -2813,6 +2925,10 @@ export async function routeRequest(
|
|
|
2813
2925
|
catch (error) { debug.log('graph.kinds', 'installed-sync-failed', { reason: String(error) }); }
|
|
2814
2926
|
return handleGraphKindsGet(req, opts.metaApi);
|
|
2815
2927
|
}
|
|
2928
|
+
if (method === 'GET' && /^\/v1\/graphs\/[^/]+\/access$/.test(pathname)) {
|
|
2929
|
+
if (!opts.metaApi || bearerCredential(req, opts.metaApi) === undefined) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
2930
|
+
return handleGraphAccess(pathname, req);
|
|
2931
|
+
}
|
|
2816
2932
|
// F-M1 read + P-F1 raw YAML. Writes live in the mutation block and never touch core graphs/.
|
|
2817
2933
|
if (method === 'GET' && (pathname === '/v1/graphs' || /^\/v1\/graphs\/[^/]+$/.test(pathname) || /^\/v1\/graphs\/[^/]+\/yaml$/.test(pathname))) {
|
|
2818
2934
|
return handleGraphsGet(pathname);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { listWizardDrafts, saveWizardDraft, type WizardResearchDraft } from '../../plugins/maker/wizard-generate.js';
|
|
2
3
|
import { dirname, join } from 'node:path';
|
|
3
4
|
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
4
5
|
import { debug } from '../../debug/log.js';
|
|
@@ -120,6 +121,29 @@ export function handlePluginsIndexGet(req: Request, opts: MetaApiOpts, root?: st
|
|
|
120
121
|
return jsonResponse(readMarketIndex(root, configuredTrustedKeys(configPath)));
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
export function handlePluginWizardList(req: Request, opts: MetaApiOpts, root = elanousStateRoot()): Response {
|
|
125
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
126
|
+
return jsonResponse({ plugins: listWizardDrafts(join(root, 'plugins-local')) });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function handlePluginWizardSave(req: Request, opts: MetaApiOpts, root = elanousStateRoot()): Promise<Response> {
|
|
130
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
131
|
+
let body: unknown;
|
|
132
|
+
try { body = await req.json(); } catch { return jsonResponse({ error: 'bad_request' }, 400); }
|
|
133
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) return jsonResponse({ error: 'bad_request' }, 400);
|
|
134
|
+
const input = body as { name?: unknown; draft?: unknown; regenerate?: unknown };
|
|
135
|
+
if (typeof input.name !== 'string' || !/^[a-z0-9][a-z0-9-]{1,31}$/.test(input.name) ||
|
|
136
|
+
!input.draft || typeof input.draft !== 'object' || Array.isArray(input.draft) ||
|
|
137
|
+
(input.regenerate !== undefined && typeof input.regenerate !== 'boolean')) return jsonResponse({ error: 'bad_request' }, 400);
|
|
138
|
+
try {
|
|
139
|
+
saveWizardDraft(join(root, 'plugins-local'), input.name, input.draft as WizardResearchDraft, input.regenerate === true);
|
|
140
|
+
return jsonResponse({ name: input.name, saved: true });
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const reason = error instanceof Error ? error.message : 'invalid draft';
|
|
143
|
+
return jsonResponse({ error: 'invalid_wizard_draft', reason: /already exists|research draft/.test(reason) ? reason : 'invalid draft' }, 422);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
123
147
|
export function handlePluginsGet(req: Request, opts: MetaApiOpts, root?: string): Response {
|
|
124
148
|
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
125
149
|
return jsonResponse(listInstalledPlugins(root));
|
package/src/nexus/index.ts
CHANGED
|
@@ -2743,11 +2743,12 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
|
|
|
2743
2743
|
if ((getUserConfig().raw?.decisions as { cards?: unknown } | undefined)?.cards !== false && !isAutonomousRunContext()) {
|
|
2744
2744
|
try {
|
|
2745
2745
|
const { DecisionCardService } = await import('../decisions/decision-cards.js');
|
|
2746
|
-
const { webPushDecisionTransport } = await import('../decisions/web-push-decision-cards.js');
|
|
2746
|
+
const { webPushDecisionTransport, webPushUrgency } = await import('../decisions/web-push-decision-cards.js');
|
|
2747
2747
|
const { listSubscriptions } = await import('../web-push/subscriptions.js');
|
|
2748
2748
|
const { DecisionLedger } = await import('../decisions/decision-ledger.js');
|
|
2749
2749
|
const ledger = new DecisionLedger();
|
|
2750
|
-
const service = new DecisionCardService({ transport: webPushDecisionTransport(ledger), ownerIds: [], ledger
|
|
2750
|
+
const service = new DecisionCardService({ transport: webPushDecisionTransport(ledger), ownerIds: [], ledger,
|
|
2751
|
+
sendFilter: (entry, now) => webPushUrgency(entry, now) !== 'not-urgent', deferredReason: webPushUrgency });
|
|
2751
2752
|
await service.tick();
|
|
2752
2753
|
webPushDecisionTimer = setInterval(() => {
|
|
2753
2754
|
void service.tick().catch((error: unknown) => {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
// { "type": "discord", "webhookUrl": "https://discord.com/api/webhooks/..." },
|
|
17
17
|
// { "type": "pushcut", "webhookUrl": "https://api.pushcut.io/.../notifications/..." }
|
|
18
18
|
// ],
|
|
19
|
-
// "routes": { "alert": ["telegram", "pushcut"], "report": ["telegram", "discord"] }
|
|
19
|
+
// "routes": { "alert": ["telegram", "pushcut"], "report": ["telegram", "discord"] },
|
|
20
|
+
// "awayRoutes": { "alert": ["discord"] }
|
|
20
21
|
// }
|
|
21
22
|
//
|
|
22
23
|
// Backward compat: when `outbound` is absent/malformed the resolved
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
// that boolean before falling back to direct Telegram).
|
|
28
29
|
|
|
29
30
|
import { createHash } from 'node:crypto';
|
|
31
|
+
import { readPresence } from '../../away/presence.js';
|
|
30
32
|
import { debug } from '../../debug/log.js';
|
|
31
33
|
import { sendTelegramReport } from '../../telegram-report.js';
|
|
32
34
|
import { getPushcutClient } from '../../pushcut/client.js';
|
|
@@ -58,6 +60,8 @@ export interface OutboundFanoutConfig {
|
|
|
58
60
|
* `routes.default`, then to ALL configured channels. An explicitly
|
|
59
61
|
* empty route (`"heartbeat": []`) suppresses that kind. */
|
|
60
62
|
routes?: Record<string, string[]>;
|
|
63
|
+
/** 외출 중 kind → channel types. 미지정 kind는 awayRoutes.default, 이것도 없으면 기존 routes를 유지한다. */
|
|
64
|
+
awayRoutes?: Record<string, string[]>;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
export interface ChannelResult {
|
|
@@ -118,14 +122,17 @@ export function normalizeOutbound(raw: unknown): OutboundFanoutConfig | undefine
|
|
|
118
122
|
channels.push({ type, ...(webhookUrl ? { webhookUrl } : {}), ...(notification ? { notification } : {}) });
|
|
119
123
|
}
|
|
120
124
|
if (channels.length === 0) return undefined;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
routes = {};
|
|
124
|
-
for (const [kind, v] of Object.entries(
|
|
125
|
+
const parseRoutes = (value: unknown): Record<string, string[]> | undefined => {
|
|
126
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
|
|
127
|
+
const routes: Record<string, string[]> = {};
|
|
128
|
+
for (const [kind, v] of Object.entries(value as Record<string, unknown>)) {
|
|
125
129
|
if (Array.isArray(v)) routes[kind] = v.filter((t): t is string => typeof t === 'string');
|
|
126
130
|
}
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
return routes;
|
|
132
|
+
};
|
|
133
|
+
const routes = parseRoutes(o.routes);
|
|
134
|
+
const awayRoutes = parseRoutes(o.awayRoutes);
|
|
135
|
+
return { channels, ...(routes ? { routes } : {}), ...(awayRoutes ? { awayRoutes } : {}) };
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
/** Resolve the channel list for one message kind. No/empty config →
|
|
@@ -219,7 +226,20 @@ export async function routeOutbound(cfg: UserConfig, msg: OutboundMsg, deps: Rou
|
|
|
219
226
|
} catch { /* 원장 조회 실패 — 억제 없이 진행 */ }
|
|
220
227
|
}
|
|
221
228
|
|
|
222
|
-
|
|
229
|
+
// 상태 파일이 없거나 읽기에 실패하면 기존 kind 경로를 그대로 사용한다.
|
|
230
|
+
let list = resolveChannels(outbound, msg.kind);
|
|
231
|
+
if (outbound?.awayRoutes) {
|
|
232
|
+
try {
|
|
233
|
+
if (readPresence().away) {
|
|
234
|
+
const awayRoute = outbound.awayRoutes[msg.kind] ?? outbound.awayRoutes.default;
|
|
235
|
+
// kind 도 default 도 없으면 기존 경로로 · 명시적인 빈 배열은 기존 routes 와 같은 규칙(채널 0)을 따른다.
|
|
236
|
+
if (awayRoute !== undefined) {
|
|
237
|
+
list = outbound.channels.filter(ch => awayRoute.includes(ch.type));
|
|
238
|
+
try { debug.log('outbound.send', 'away-route', { kind: msg.kind, channels: list.map(ch => ch.type) }); } catch { /* 관측 실패는 발송 결과에 영향 없음 */ }
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
} catch { /* 상태 조회 실패 — 기존 경로 유지 */ }
|
|
242
|
+
}
|
|
223
243
|
const channels = await Promise.all(list.map(async (ch): Promise<ChannelResult> => {
|
|
224
244
|
try {
|
|
225
245
|
if (ch.type === 'telegram') return await deliverTelegram(cfg, outMsg, deps);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ClaudePtyMaturity =
|
|
2
|
+
| { readonly mature: true }
|
|
3
|
+
| { readonly mature: false; readonly why: 'too-few-samples' | 'completion-below-70' | 'unknown-screen-above-10' | 'intervention-above-0.2' | 'sample-unreadable' };
|
|
4
|
+
|
|
5
|
+
export type ClaudePtyMaturitySample = {
|
|
6
|
+
readonly runCount: number;
|
|
7
|
+
readonly completedCount: number;
|
|
8
|
+
readonly unknownScreenCount: number;
|
|
9
|
+
readonly interventionCount: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** 최근 런의 계수만 판정한다. 표본을 못 읽거나 계수가 불가능하면 성숙으로 추정하지 않는다. */
|
|
13
|
+
export function judgeClaudePtyMaturity(sample: ClaudePtyMaturitySample | null | undefined): ClaudePtyMaturity {
|
|
14
|
+
if (!sample || ![sample.runCount, sample.completedCount, sample.unknownScreenCount, sample.interventionCount]
|
|
15
|
+
.every((count) => Number.isSafeInteger(count) && count >= 0)
|
|
16
|
+
|| sample.completedCount > sample.runCount || sample.unknownScreenCount > sample.runCount) {
|
|
17
|
+
return { mature: false, why: 'sample-unreadable' };
|
|
18
|
+
}
|
|
19
|
+
if (sample.runCount < 10) return { mature: false, why: 'too-few-samples' };
|
|
20
|
+
if (sample.completedCount / sample.runCount < 0.7) return { mature: false, why: 'completion-below-70' };
|
|
21
|
+
if (sample.unknownScreenCount / sample.runCount > 0.1) return { mature: false, why: 'unknown-screen-above-10' };
|
|
22
|
+
if (sample.interventionCount / sample.runCount > 0.2) return { mature: false, why: 'intervention-above-0.2' };
|
|
23
|
+
return { mature: true };
|
|
24
|
+
}
|
|
@@ -19,9 +19,10 @@
|
|
|
19
19
|
// 지갑을 여는» 일이 없다. (2026-08-13 실측 · RESEARCH-grok-oauth-… §7b)
|
|
20
20
|
|
|
21
21
|
import type { RotationCandidate } from './codex-account-rotation.js';
|
|
22
|
+
import type { ClaudePtyMaturity } from './claude-pty-maturity.js';
|
|
22
23
|
|
|
23
24
|
/** 체인에 놓을 수 있는 칸. ⛔ 모르는 이름은 «조용히 건너뛰지 않고» 거부한다(오타 방어). */
|
|
24
|
-
export const FALLBACK_STEPS = ['codex-rotate', 'grok'] as const;
|
|
25
|
+
export const FALLBACK_STEPS = ['codex-rotate', 'grok', 'claude-pty'] as const;
|
|
25
26
|
export type FallbackStep = (typeof FALLBACK_STEPS)[number];
|
|
26
27
|
|
|
27
28
|
/** 기본 체인 — ⛔⭐ **2026-08-20 에 `grok` 이 «기본»으로 들어왔다**(대표 지시).
|
|
@@ -75,8 +76,8 @@ export type RotationOutcome =
|
|
|
75
76
|
export type FallbackDecision =
|
|
76
77
|
/** codex 계정을 갈아탄다(종전 동작). */
|
|
77
78
|
| { readonly action: 'codex-rotate'; readonly to: RotationCandidate }
|
|
78
|
-
/** 백엔드를 통째로 바꾼다.
|
|
79
|
-
| { readonly action: 'switch-backend'; readonly backend: 'grok' }
|
|
79
|
+
/** 백엔드를 통째로 바꾼다. */
|
|
80
|
+
| { readonly action: 'switch-backend'; readonly backend: 'grok' | 'claude' }
|
|
80
81
|
/** 아무것도 안 한다 — 이유를 «값으로» 남긴다. */
|
|
81
82
|
| { readonly action: 'stay'; readonly why: StayReason };
|
|
82
83
|
|
|
@@ -96,7 +97,9 @@ export type StayReason =
|
|
|
96
97
|
/** 다음 칸이 grok 인데 grok 자격이 «없다». */
|
|
97
98
|
| 'grok-unavailable'
|
|
98
99
|
/** grok 자격은 있는데 «잔량이 소진»됐다 — 자격 부재와 «다른 값»이다. */
|
|
99
|
-
| 'grok-exhausted'
|
|
100
|
+
| 'grok-exhausted'
|
|
101
|
+
/** claude PTY 의 최근 표본이 성숙 관문을 통과하지 못했거나 읽히지 않는다. */
|
|
102
|
+
| 'claude-pty-immature';
|
|
100
103
|
|
|
101
104
|
type FallbackRunPosition =
|
|
102
105
|
| { readonly currentCredentialRateLimited?: false; readonly currentStep?: FallbackStep }
|
|
@@ -120,6 +123,8 @@ export type FallbackInput = {
|
|
|
120
123
|
* (⇒ 그리고 그 사실은 관측에 값으로 남는다 — 「모르고 갔다」를 셀 수 있다.)
|
|
121
124
|
*/
|
|
122
125
|
readonly grokQuota?: 'usable' | 'exhausted' | 'unknown';
|
|
126
|
+
/** 최근 claude PTY 표본의 순수 성숙 판정. 생략·못 읽음은 전환 불가. */
|
|
127
|
+
readonly claudePtyMaturity?: ClaudePtyMaturity;
|
|
123
128
|
/**
|
|
124
129
|
* `reset-credit-available` 에서 체인을 타지 않고 머문다.
|
|
125
130
|
* 기본(생략·false)은 `no-candidate` 와 같이 `codex-rotate` 다음 칸을 찾는다.
|
|
@@ -148,12 +153,12 @@ export type FallbackInput = {
|
|
|
148
153
|
export function decideFallback(input: FallbackInput): FallbackDecision {
|
|
149
154
|
const {
|
|
150
155
|
rotation, chain, currentStep, currentCredentialRateLimited = false,
|
|
151
|
-
grokAvailable, grokQuota = 'unknown', stayOnResetCreditAvailable = false,
|
|
156
|
+
grokAvailable, grokQuota = 'unknown', claudePtyMaturity, stayOnResetCreditAvailable = false,
|
|
152
157
|
} = input;
|
|
153
158
|
|
|
154
159
|
if (currentCredentialRateLimited) {
|
|
155
160
|
if (currentStep === undefined) return { action: 'stay', why: 'chain-exhausted' };
|
|
156
|
-
return stepAfter(chain, currentStep, grokAvailable, grokQuota, 'chain-exhausted');
|
|
161
|
+
return stepAfter(chain, currentStep, grokAvailable, grokQuota, claudePtyMaturity, 'chain-exhausted');
|
|
157
162
|
}
|
|
158
163
|
if (rotation.reason === 'explicit') return { action: 'stay', why: 'explicit' };
|
|
159
164
|
if (rotation.reason === 'not-reached' || (rotation.reason === 'credit-pace' && !('to' in rotation))) {
|
|
@@ -167,13 +172,13 @@ export function decideFallback(input: FallbackInput): FallbackDecision {
|
|
|
167
172
|
// 회전이 답을 냈는데 체인이 codex-rotate 를 «빼» 놨다면 그 뜻을 존중하고
|
|
168
173
|
// 다음 칸으로 간다(회전을 원치 않는 구성).
|
|
169
174
|
if (chain.includes('codex-rotate')) return { action: 'codex-rotate', to: rotation.to };
|
|
170
|
-
return stepAfterCodex(chain, grokAvailable, grokQuota, 'chain-exhausted');
|
|
175
|
+
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, 'chain-exhausted');
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
// no-candidate | disabled | reset-credit-available(기본) — codex 축이 끝났다. 다음 칸을 본다.
|
|
174
179
|
// ⛔ 다음 칸이 «없을 때»의 이름만 고른다. 진행(stepAfterCodex)은 그대로다.
|
|
175
180
|
const fallbackWhy = stayReasonWhenCodexAxisEnds(rotation.reason === 'credit-pace' ? 'no-candidate' : rotation.reason);
|
|
176
|
-
return stepAfterCodex(chain, grokAvailable, grokQuota, fallbackWhy);
|
|
181
|
+
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, fallbackWhy);
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
/** codex 축이 끝났는데 체인 다음 칸도 없을 때 머무는 이유.
|
|
@@ -191,9 +196,10 @@ function stepAfterCodex(
|
|
|
191
196
|
chain: readonly FallbackStep[],
|
|
192
197
|
grokAvailable: boolean,
|
|
193
198
|
grokQuota: 'usable' | 'exhausted' | 'unknown',
|
|
199
|
+
claudePtyMaturity: ClaudePtyMaturity | undefined,
|
|
194
200
|
whyIfNone: StayReason,
|
|
195
201
|
): FallbackDecision {
|
|
196
|
-
return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, whyIfNone);
|
|
202
|
+
return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, claudePtyMaturity, whyIfNone);
|
|
197
203
|
}
|
|
198
204
|
|
|
199
205
|
function stepAfter(
|
|
@@ -201,20 +207,27 @@ function stepAfter(
|
|
|
201
207
|
currentStep: FallbackStep | undefined,
|
|
202
208
|
grokAvailable: boolean,
|
|
203
209
|
grokQuota: 'usable' | 'exhausted' | 'unknown',
|
|
210
|
+
claudePtyMaturity: ClaudePtyMaturity | undefined,
|
|
204
211
|
whyIfNone: StayReason,
|
|
205
212
|
): FallbackDecision {
|
|
206
213
|
const idx = currentStep === undefined ? -1 : chain.indexOf(currentStep);
|
|
207
214
|
const rest = idx === -1 ? chain : chain.slice(idx + 1);
|
|
215
|
+
let unavailableWhy: StayReason | undefined;
|
|
208
216
|
for (const step of rest) {
|
|
209
217
|
if (step === 'grok') {
|
|
210
|
-
//
|
|
211
|
-
if (!grokAvailable)
|
|
212
|
-
//
|
|
213
|
-
if (grokQuota === 'exhausted')
|
|
218
|
+
// 자격 부재와 소진은 다른 값이다. 다음 칸이 있으면 그 칸을 살핀다.
|
|
219
|
+
if (!grokAvailable) { unavailableWhy = 'grok-unavailable'; continue; }
|
|
220
|
+
// 「모른다」는 통과시킨다 — 못 읽었다고 갈 곳을 없애지 않는다.
|
|
221
|
+
if (grokQuota === 'exhausted') { unavailableWhy = 'grok-exhausted'; continue; }
|
|
214
222
|
return { action: 'switch-backend', backend: 'grok' };
|
|
215
223
|
}
|
|
224
|
+
if (step === 'claude-pty') {
|
|
225
|
+
// 미성숙·못 읽음은 «건너뛴다» — 뒤에 다른 칸이 있으면 그 칸을 본다(없으면 이 사유로 머문다).
|
|
226
|
+
if (claudePtyMaturity?.mature !== true) { unavailableWhy = 'claude-pty-immature'; continue; }
|
|
227
|
+
return { action: 'switch-backend', backend: 'claude' };
|
|
228
|
+
}
|
|
216
229
|
}
|
|
217
|
-
return { action: 'stay', why: whyIfNone };
|
|
230
|
+
return { action: 'stay', why: unavailableWhy ?? whyIfNone };
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
/** 사람이 읽는 한 줄 — 관측·CLI 표면용. ⛔ 토큰·계정 홈은 넣지 않는다. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as readline from 'node:readline/promises';
|
|
2
2
|
import { detectProviders, type DetectedProvider } from '../llm/provider-detect.js';
|
|
3
3
|
import { debug } from '../debug/log.js';
|
|
4
|
+
import { unattendedNextStepLine } from './entry-hints.js';
|
|
4
5
|
import { resolveProviderCredential } from '../llm/provider-credentials.js';
|
|
5
6
|
import {
|
|
6
7
|
getUserConfig, saveUserConfig, userConfigPath,
|
|
@@ -57,6 +58,8 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
|
|
|
57
58
|
if (!provider) {
|
|
58
59
|
if ((deps.isTTY ?? process.stdin.isTTY) !== true) {
|
|
59
60
|
print('eln setup llm 으로 고르세요');
|
|
61
|
+
// FIRST-CHAT-NONTTY — bare `elanous` with no TTY gets the same one-line next step as the other entrances.
|
|
62
|
+
print(unattendedNextStepLine());
|
|
60
63
|
observe('needs-llm', 0);
|
|
61
64
|
return { outcome: 'needs-llm', inputs: 0 };
|
|
62
65
|
}
|