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
|
@@ -62,6 +62,9 @@ export interface DraftSweepOptions {
|
|
|
62
62
|
adapters: DraftSweepAdapters;
|
|
63
63
|
apply?: boolean;
|
|
64
64
|
now?: Date;
|
|
65
|
+
/** Per-tick close cap; resolve it with resolveDraftSweepCloseCap. Absent or invalid ⇒ DRAFT_SWEEP_CLOSE_CAP. */
|
|
66
|
+
closeCap?: number;
|
|
67
|
+
closeCapSource?: DraftSweepCloseCapSource;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
export interface DraftSweepEntry {
|
|
@@ -83,8 +86,11 @@ export interface DraftSweepResult {
|
|
|
83
86
|
counts: Record<string, number>;
|
|
84
87
|
/** Drafts whose run could not be observed from here (kept, or closed by the idle rule). */
|
|
85
88
|
unobserved?: number;
|
|
86
|
-
/** Closes decided this tick (at most
|
|
89
|
+
/** Closes decided this tick (at most `closeCap`). */
|
|
87
90
|
closed?: number;
|
|
91
|
+
/** The per-tick close cap this sweep used, and where it came from. */
|
|
92
|
+
closeCap?: number;
|
|
93
|
+
closeCapSource?: DraftSweepCloseCapSource;
|
|
88
94
|
/** Fresh running claims protected this tick. */
|
|
89
95
|
claimed?: number;
|
|
90
96
|
/** Running claims older than the idle window, including those kept by liveness. */
|
|
@@ -420,8 +426,36 @@ const approvalLabel = PR_LABELS.find((entry) => entry.axis === 'state' && entry.
|
|
|
420
426
|
const keepLabel = PR_LABELS.find((entry) => entry.sweep.action === 'exclude')?.name;
|
|
421
427
|
const releaseHoldLabel = PR_LABELS.find((entry) => entry.axis === 'addon' && entry.sweep.action === 'none')?.name;
|
|
422
428
|
const PAGE_SIZE = 100;
|
|
423
|
-
/** At most this many closes per tick, so a wrong rule cannot close everything at once. */
|
|
429
|
+
/** At most this many closes per tick, so a wrong rule cannot close everything at once. Default for `tools.selfImplement.draftSweepCloseCap`. */
|
|
424
430
|
export const DRAFT_SWEEP_CLOSE_CAP = 10;
|
|
431
|
+
export const DRAFT_SWEEP_CLOSE_CAP_MIN = 1;
|
|
432
|
+
export const DRAFT_SWEEP_CLOSE_CAP_MAX = 100;
|
|
433
|
+
export type DraftSweepCloseCapSource = 'flag' | 'config' | 'default';
|
|
434
|
+
|
|
435
|
+
export interface DraftSweepCloseCapResolution {
|
|
436
|
+
readonly closeCap: number;
|
|
437
|
+
readonly closeCapSource: DraftSweepCloseCapSource;
|
|
438
|
+
/** One line per rejected input (flag or config); each rejection falls through to the next source. */
|
|
439
|
+
readonly warnings: readonly string[];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function validCloseCap(value: unknown): number | undefined {
|
|
443
|
+
const parsed = typeof value === 'string' && /^\s*\d+\s*$/.test(value) ? Number(value) : value;
|
|
444
|
+
return typeof parsed === 'number' && Number.isSafeInteger(parsed)
|
|
445
|
+
&& parsed >= DRAFT_SWEEP_CLOSE_CAP_MIN && parsed <= DRAFT_SWEEP_CLOSE_CAP_MAX ? parsed : undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** Flag over config over default; a value outside 1–100 (or not an integer) is rejected with a warning. */
|
|
449
|
+
export function resolveDraftSweepCloseCap(input: { flag?: unknown; config?: unknown }): DraftSweepCloseCapResolution {
|
|
450
|
+
const warnings: string[] = [];
|
|
451
|
+
for (const [source, value, name] of [['flag', input.flag, '--close-cap'], ['config', input.config, 'tools.selfImplement.draftSweepCloseCap']] as const) {
|
|
452
|
+
if (value === undefined || value === null) continue;
|
|
453
|
+
const cap = validCloseCap(value);
|
|
454
|
+
if (cap !== undefined) return { closeCap: cap, closeCapSource: source, warnings };
|
|
455
|
+
warnings.push(`${name}=${JSON.stringify(value)} 무시 — ${DRAFT_SWEEP_CLOSE_CAP_MIN}~${DRAFT_SWEEP_CLOSE_CAP_MAX} 정수만 (기본 ${DRAFT_SWEEP_CLOSE_CAP})`);
|
|
456
|
+
}
|
|
457
|
+
return { closeCap: DRAFT_SWEEP_CLOSE_CAP, closeCapSource: 'default', warnings };
|
|
458
|
+
}
|
|
425
459
|
|
|
426
460
|
/** Post-merge shortcut: only the existing superseded-by decision can authorize a close. */
|
|
427
461
|
export async function supersedeDraftsOnMerge(input: {
|
|
@@ -571,8 +605,11 @@ export function draftSweepDaily(
|
|
|
571
605
|
}
|
|
572
606
|
|
|
573
607
|
/** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
|
|
574
|
-
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date() }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
575
|
-
const
|
|
608
|
+
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date(), closeCap: requestedCap, closeCapSource: requestedSource }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
609
|
+
const validCap = validCloseCap(requestedCap);
|
|
610
|
+
const closeCap = validCap ?? DRAFT_SWEEP_CLOSE_CAP;
|
|
611
|
+
const closeCapSource: DraftSweepCloseCapSource = validCap === undefined ? 'default' : requestedSource ?? 'flag';
|
|
612
|
+
const result: DraftSweepResult = { repository, apply, complete: false, entries: [], counts: {}, closeCap, closeCapSource };
|
|
576
613
|
const record = (entry: DraftSweepEntry): void => {
|
|
577
614
|
result.entries.push(entry);
|
|
578
615
|
result.counts[entry.reason] = (result.counts[entry.reason] ?? 0) + 1;
|
|
@@ -591,7 +628,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
591
628
|
const at = Date.now();
|
|
592
629
|
try {
|
|
593
630
|
debug.log('self-dev.draft-sweep', 'timing', { phase, ms: at - phaseStarted, count, ...(outcome ? { outcome } : {}) });
|
|
594
|
-
if (outcome) debug.log('self-dev.draft-sweep', 'timing', { phase: 'total', ms: at - started, count, outcome });
|
|
631
|
+
if (outcome) debug.log('self-dev.draft-sweep', 'timing', { phase: 'total', ms: at - started, count, outcome, closeCap, closeCapSource });
|
|
595
632
|
} catch { /* fail-soft */ }
|
|
596
633
|
phaseStarted = at;
|
|
597
634
|
};
|
|
@@ -706,7 +743,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
706
743
|
record({ number: draft.number, action: 'keep', reason: 'claim-expired-but-live', applied: false });
|
|
707
744
|
continue;
|
|
708
745
|
}
|
|
709
|
-
const action = closes >=
|
|
746
|
+
const action = closes >= closeCap ? 'keep' : 'close';
|
|
710
747
|
if (action === 'close') closes += 1;
|
|
711
748
|
const entry: DraftSweepEntry = { number: draft.number, action,
|
|
712
749
|
reason: action === 'close' ? runStatus === 'self-implement.result final'
|
|
@@ -737,7 +774,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
737
774
|
finalRunResult, ageHours: runStatus ? ageHours : idleHours });
|
|
738
775
|
if (!runStatus && (decision.reason === 'unobserved' || decision.reason === 'stale-unobserved')) unobserved += 1;
|
|
739
776
|
if (!contradiction && decision.action === 'close') {
|
|
740
|
-
if (closes >=
|
|
777
|
+
if (closes >= closeCap) decision = { action: 'keep', reason: 'close-cap' };
|
|
741
778
|
else closes += 1;
|
|
742
779
|
}
|
|
743
780
|
const action = contradiction ? 'report' : decision.action;
|
|
@@ -772,7 +809,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
772
809
|
}
|
|
773
810
|
}
|
|
774
811
|
timing('decide', drafts.length);
|
|
775
|
-
try { debug.log('self-dev.draft-sweep', 'timing', { phase: 'total', ms: Date.now() - started, count: drafts.length }); } catch { /* fail-soft */ }
|
|
812
|
+
try { debug.log('self-dev.draft-sweep', 'timing', { phase: 'total', ms: Date.now() - started, count: drafts.length, closed: closes, closeCap, closeCapSource }); } catch { /* fail-soft */ }
|
|
776
813
|
result.unobserved = unobserved;
|
|
777
814
|
result.closed = closes;
|
|
778
815
|
result.claimed = claimed;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
import { GRAPH_SPECS, GRAPH_TEMPLATES, GRAPH_TEMPLATES_SOURCE, pipelineNodeEntryPayload, templateForGoalType, type GraphTemplate } from '../self-implement/graph-templates.js';
|
|
4
|
+
import type { GoalType } from '../self-implement/goal-author.js';
|
|
5
|
+
|
|
6
|
+
/** ⭐ HARNESS-FULL-GRAPH (0.2.21 · 대표 10-08) — 하니스 «여정» 전 단계를 그래프 노드로 선언·관측한다.
|
|
7
|
+
*
|
|
8
|
+
* 🩸 계기: `내부 문서 `TECH-harness-map-2026-10-06`` 차트의 단계 중 «입구·대기열·발사 관문·배치·Pod 입장·
|
|
9
|
+
* 이미지 동기화·자격 선갱신·동결 검사·보류·회수·실패 쪽(결과 해석·수확·heal·다음 한 수)»이
|
|
10
|
+
* 그래프 밖의 «맨 코드»였다. 공개 문서는 「그래프 선언이 모든 걸음을 대조한다」고 말한다 — 거짓이 되지 않게.
|
|
11
|
+
*
|
|
12
|
+
* ⛔ 이 모듈은 «관측»이다(1단계) — 흐름을 바꾸지 않는다. 진입은 기존 노드와 «같은 사건»
|
|
13
|
+
* (`self-implement` / `pipeline-node-entry` · 같은 `pipelineNodeEntryPayload`)으로 남겨
|
|
14
|
+
* 그래프 권위의 declared/undeclared 판정과 원장 질의가 이 노드들을 «같은 자»로 본다.
|
|
15
|
+
* 출구는 `pipeline-node-exit`(결과 `outcome` 포함)로 남긴다.
|
|
16
|
+
* ⛔ fail-soft — 관측이 발사·착지를 죽이지 않는다.
|
|
17
|
+
*
|
|
18
|
+
* 🔗 조인(런 id 가 없는 앞단): 입구에서 `ELANOUS_JOURNEY_KEY` 를 한 번 만들어 환경에 싣는다.
|
|
19
|
+
* 자식 프로세스는 그 값을 물려받고, 오케스트레이터의 모든 파이프라인 관측에도 `journeyKey` 가 실린다.
|
|
20
|
+
* ⇒ `journeyKey` 로 「runId 없이 남은 앞단 걸음」과 「runId 가 있는 후반 걸음」을 한 질의로 묶는다.
|
|
21
|
+
* 대기열을 거친 발사는 부모·자식 프로세스가 다르다 — 그 자리는 `queueLaunchId`(=`ELANOUS_HARNESS_QUEUE_LAUNCH`)가 잇는다.
|
|
22
|
+
* 설계 = 내부 문서 `RFC-harness-full-journey-as-graph-2026-10-08` §4. */
|
|
23
|
+
|
|
24
|
+
/** 여정 노드 — ⛔ id 는 원장의 조인 키이자 라이브 그래프 화면(HARNESS-RUN-LIVE-GRAPH)의 키다. 바꾸지 마라. */
|
|
25
|
+
export const JOURNEY_NODE_IDS = [
|
|
26
|
+
'intake',
|
|
27
|
+
'queue',
|
|
28
|
+
'launch-gate',
|
|
29
|
+
'dispatch',
|
|
30
|
+
'pool-admit',
|
|
31
|
+
'image-sync',
|
|
32
|
+
'credential-refresh',
|
|
33
|
+
'freeze-check',
|
|
34
|
+
'hold',
|
|
35
|
+
'cleanup',
|
|
36
|
+
'result-parse',
|
|
37
|
+
'salvage',
|
|
38
|
+
'heal',
|
|
39
|
+
'next-move',
|
|
40
|
+
'stopped',
|
|
41
|
+
] as const;
|
|
42
|
+
export type JourneyNodeId = typeof JOURNEY_NODE_IDS[number];
|
|
43
|
+
|
|
44
|
+
export const JOURNEY_KEY_ENV = 'ELANOUS_JOURNEY_KEY';
|
|
45
|
+
const QUEUE_LAUNCH_ENV = 'ELANOUS_HARNESS_QUEUE_LAUNCH';
|
|
46
|
+
const RUN_ID_ENV = 'ELANOUS_RUN_ID';
|
|
47
|
+
|
|
48
|
+
/** 이 여정의 조인 키 — 없으면 만들어 환경에 싣는다(자식이 물려받는다). */
|
|
49
|
+
export function ensureJourneyKey(env: NodeJS.ProcessEnv = process.env): string {
|
|
50
|
+
const existing = env[JOURNEY_KEY_ENV]?.trim();
|
|
51
|
+
if (existing) return existing;
|
|
52
|
+
const key = `jrn-${randomUUID()}`;
|
|
53
|
+
env[JOURNEY_KEY_ENV] = key;
|
|
54
|
+
return key;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 관측 자리마다 펼치는 조인 칸(있는 것만). */
|
|
58
|
+
export function journeyJoinFields(env: NodeJS.ProcessEnv = process.env): { journeyKey?: string; queueLaunchId?: string } {
|
|
59
|
+
const journeyKey = env[JOURNEY_KEY_ENV]?.trim();
|
|
60
|
+
const queueLaunchId = env[QUEUE_LAUNCH_ENV]?.trim();
|
|
61
|
+
return {
|
|
62
|
+
...(journeyKey ? { journeyKey } : {}),
|
|
63
|
+
...(queueLaunchId ? { queueLaunchId } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 여정 노드를 선언한 템플릿 — 골 종류의 템플릿이 그 노드를 선언하면 그것, 아니면 구현 루프. */
|
|
68
|
+
export function journeyTemplate(node: string, goalType?: GoalType | null): GraphTemplate {
|
|
69
|
+
const own = goalType ? templateForGoalType(goalType) : null;
|
|
70
|
+
if (own && own.nodes.some((n) => n.nodeId === node)) return own;
|
|
71
|
+
return GRAPH_TEMPLATES['self-implement'] as GraphTemplate;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface JourneyObservation {
|
|
75
|
+
readonly provenance: string;
|
|
76
|
+
readonly outcome?: string;
|
|
77
|
+
readonly runId?: string;
|
|
78
|
+
readonly goalType?: GoalType | null;
|
|
79
|
+
readonly data?: Readonly<Record<string, unknown>>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function emit(entry: boolean, node: JourneyNodeId, o: JourneyObservation): void {
|
|
83
|
+
try {
|
|
84
|
+
const template = journeyTemplate(node, o.goalType);
|
|
85
|
+
const runId = o.runId ?? process.env[RUN_ID_ENV]?.trim();
|
|
86
|
+
const fields = {
|
|
87
|
+
node,
|
|
88
|
+
round: 0,
|
|
89
|
+
phase: 'journey',
|
|
90
|
+
provenance: o.provenance,
|
|
91
|
+
...(o.outcome === undefined ? {} : { outcome: o.outcome }),
|
|
92
|
+
...(runId ? { runId } : {}),
|
|
93
|
+
...(o.goalType ? { goalType: o.goalType } : {}),
|
|
94
|
+
...journeyJoinFields(),
|
|
95
|
+
...o.data,
|
|
96
|
+
graphTemplatesSource: GRAPH_TEMPLATES_SOURCE,
|
|
97
|
+
};
|
|
98
|
+
// ⛔ 진입은 «공용 payload» 를 그 호출 안에서 펼친다 — 우회 가드(graph-templates.ts)가 행 단위로 문다.
|
|
99
|
+
if (entry) debug.log('self-implement', 'pipeline-node-entry', { ...pipelineNodeEntryPayload(template, node), ...fields });
|
|
100
|
+
else debug.log('self-implement', 'pipeline-node-exit', { ...pipelineNodeEntryPayload(template, node), ...fields });
|
|
101
|
+
} catch { /* 관측은 fail-soft */ }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** 노드 진입. */
|
|
105
|
+
export function enterJourneyNode(node: JourneyNodeId, o: JourneyObservation): void {
|
|
106
|
+
emit(true, node, o);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** 노드 출구 — `outcome` 이 그 노드에서 나간 간선의 라벨(YAML `map` 키)이다.
|
|
110
|
+
* ⭐ 그 라벨이 선언에서 종결 노드 `stopped` 로 가면 `stopped` 진입도 남긴다 — 거절·포기 런이 «선언된 종결점»에서 끝난다.
|
|
111
|
+
* `outcome: 'error'` = 노드 안 작업이 예외를 던졌다(예외는 호출자에게 그대로 간다). */
|
|
112
|
+
export function exitJourneyNode(node: JourneyNodeId, o: JourneyObservation & { readonly outcome: string }): void {
|
|
113
|
+
emit(false, node, o);
|
|
114
|
+
if (node !== 'stopped' && journeyEdgeTarget(node, o.outcome) === 'stopped') {
|
|
115
|
+
const { outcome: _outcome, ...rest } = o;
|
|
116
|
+
emit(true, 'stopped', { ...rest, provenance: `${node}:${o.outcome}` });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** 선언(기준 YAML)에서 `from` 의 `label` 간선이 가는 노드. 없으면 undefined. */
|
|
121
|
+
export function journeyEdgeTarget(from: string, label: string): string | undefined {
|
|
122
|
+
try {
|
|
123
|
+
for (const edge of GRAPH_SPECS['self-implement']?.edges ?? []) {
|
|
124
|
+
if (edge.from === from && edge.map !== undefined && Object.hasOwn(edge.map, label)) return edge.map[label];
|
|
125
|
+
}
|
|
126
|
+
} catch { /* 관측 보조 — 실패해도 출구는 이미 남았다 */ }
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** 노드 안 작업을 감싼다 — 예외면 출구 `error` 를 남기고 다시 던진다(진입 뒤 출구가 빠지지 않게). */
|
|
131
|
+
export function withJourneyNode<T>(node: JourneyNodeId, o: JourneyObservation, work: () => Promise<T>): Promise<T> {
|
|
132
|
+
const onError = (error: unknown): void => {
|
|
133
|
+
exitJourneyNode(node, { ...o, outcome: 'error', data: { ...o.data, error: error instanceof Error ? error.message : String(error) } });
|
|
134
|
+
};
|
|
135
|
+
let pending: Promise<T>;
|
|
136
|
+
try { pending = work(); }
|
|
137
|
+
catch (error) { onError(error); throw error; }
|
|
138
|
+
// ⛔ 같은 약속을 «그대로» 돌려준다 — async/await 로 감싸면 마이크로태스크가 늘어 호출자의 순서가 밀린다
|
|
139
|
+
// (2판에서 self-implement-pod 시험이 그 차이를 잡았다). 관측은 곁가지(.then)로만 붙인다.
|
|
140
|
+
pending.then(undefined, onError);
|
|
141
|
+
return pending;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** 동기 판. */
|
|
145
|
+
export function withJourneyNodeSync<T>(node: JourneyNodeId, o: JourneyObservation, work: () => T): T {
|
|
146
|
+
try { return work(); }
|
|
147
|
+
catch (error) {
|
|
148
|
+
exitJourneyNode(node, { ...o, outcome: 'error', data: { ...o.data, error: error instanceof Error ? error.message : String(error) } });
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** 진입·출구를 한 번에 — 판정만 하는 노드(대기 없는 관문)용. */
|
|
154
|
+
export function passJourneyNode(node: JourneyNodeId, o: JourneyObservation & { readonly outcome: string }): void {
|
|
155
|
+
enterJourneyNode(node, o);
|
|
156
|
+
exitJourneyNode(node, o);
|
|
157
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
import { GRAPH_SPECS } from '../self-implement/graph-templates.js';
|
|
3
|
+
import { applyGraphOverlays, defaultOverlaysDir, loadGraphOverlays, selectOverlays, type GraphOverlaySpec } from '../self-implement/graph-overlay-yaml.js';
|
|
4
|
+
import type { GraphTemplateSpec } from '../self-implement/graph-yaml.js';
|
|
5
|
+
import { journeyJoinFields } from './graph-journey-nodes.js';
|
|
6
|
+
|
|
7
|
+
/** ⭐ HARNESS-FULL-GRAPH 2판 — 「다음 노드」를 코드가 아니라 «그래프»가 정한다.
|
|
8
|
+
*
|
|
9
|
+
* 대표 10-08: *«그래프에 따라 실제 경로가 바뀌어야 한다. 기본은 풀세트, 환경 셋업·운영 방법에 따라 일부만 걷거나 생략.»*
|
|
10
|
+
* ⇒ 코드는 «상태 값»(queue=queued|direct · substrate=local|pod · freeze=open|frozen …)만 낸다.
|
|
11
|
+
* 그 값으로 «어느 간선을 타나»는 YAML 의 `on:`/`map:`(⊕ `stage: launch` 오버레이)이 정한다.
|
|
12
|
+
* ⛔ 기본 YAML 은 오늘 코드와 «같은 길»을 낸다 — 시험이 그 동치를 문다(graph-journey-route.test.ts).
|
|
13
|
+
* ⛔ 그래프가 답을 못 내면(간선 없음·로드 실패) 코드 기본으로 간다 — 그 사실을 `source: 'code-default'` 로 남긴다.
|
|
14
|
+
* 🔎 관측: `self-implement` / `graph-edge-taken` { from, on, label, to, source, overlays } */
|
|
15
|
+
|
|
16
|
+
export interface JourneyRoute {
|
|
17
|
+
readonly from: string;
|
|
18
|
+
readonly on: string | null;
|
|
19
|
+
readonly label: string;
|
|
20
|
+
/** 그래프가 고른 다음 노드. 못 고르면 null. */
|
|
21
|
+
readonly to: string | null;
|
|
22
|
+
readonly source: 'graph' | 'code-default';
|
|
23
|
+
readonly overlays: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** ⛔ 캐시하지 않는다 — 여러 런을 처리하는 프로세스(데몬·대기열 tick)가 다음 발사에서 오버레이 변경을 봐야 한다.
|
|
27
|
+
* 여정 판정은 발사당 몇 번뿐이라 디렉터리 한 번 읽기가 싸다. */
|
|
28
|
+
let overlaysForTesting: readonly GraphOverlaySpec[] | undefined;
|
|
29
|
+
function launchOverlays(): readonly GraphOverlaySpec[] {
|
|
30
|
+
if (overlaysForTesting !== undefined) return overlaysForTesting;
|
|
31
|
+
try { return loadGraphOverlays(defaultOverlaysDir()).overlays; }
|
|
32
|
+
catch { return []; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** 시험 전용 — 오버레이 묶음을 고정한다(undefined 면 디스크에서 읽는다). */
|
|
36
|
+
export function setJourneyOverlaysForTesting(overlays: readonly GraphOverlaySpec[] | undefined): void {
|
|
37
|
+
overlaysForTesting = overlays;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 상태 값으로 고른 «이 런의 여정 선언» — 기준 YAML ⊕ 조건이 맞는 launch 오버레이. */
|
|
41
|
+
export function journeySpec(
|
|
42
|
+
state: Readonly<Record<string, unknown>>,
|
|
43
|
+
base: GraphTemplateSpec | undefined = GRAPH_SPECS['self-implement'],
|
|
44
|
+
overlays: readonly GraphOverlaySpec[] = launchOverlays(),
|
|
45
|
+
): { readonly spec: GraphTemplateSpec | undefined; readonly applied: readonly string[] } {
|
|
46
|
+
if (base === undefined) return { spec: undefined, applied: [] };
|
|
47
|
+
try {
|
|
48
|
+
const { applied } = selectOverlays(overlays, { graphId: base.graphId, stage: 'launch', state });
|
|
49
|
+
if (applied.length === 0) return { spec: base, applied: [] };
|
|
50
|
+
const result = applyGraphOverlays(base, applied);
|
|
51
|
+
// ⛔ 거절된 오버레이는 길을 바꾸지 않는다 — 기준 선언으로 간다.
|
|
52
|
+
return result.ok ? { spec: result.template, applied: result.overlayIds } : { spec: base, applied: [] };
|
|
53
|
+
} catch {
|
|
54
|
+
return { spec: base, applied: [] };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** `from` 노드에서 `label` 로 나가는 다음 노드를 그래프에서 «읽는다»(기록하지 않는다).
|
|
59
|
+
* ⛔ 판독과 기록을 가른다 — 실제로 탄 간선은 전제 검사·실제 단계 경계 «뒤»에 `recordJourneyEdge` 로 남긴다. */
|
|
60
|
+
export function readJourneyEdge(
|
|
61
|
+
from: string,
|
|
62
|
+
label: string,
|
|
63
|
+
state: Readonly<Record<string, unknown>> = {},
|
|
64
|
+
deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[] } = {},
|
|
65
|
+
): JourneyRoute {
|
|
66
|
+
const { spec, applied } = journeySpec(state, deps.base ?? GRAPH_SPECS['self-implement'], deps.overlays ?? launchOverlays());
|
|
67
|
+
let route: JourneyRoute = { from, on: null, label, to: null, source: 'code-default', overlays: applied };
|
|
68
|
+
for (const edge of spec?.edges ?? []) {
|
|
69
|
+
if (edge.from !== from) continue;
|
|
70
|
+
if (edge.map !== undefined && Object.hasOwn(edge.map, label)) {
|
|
71
|
+
route = { from, on: edge.on ?? null, label, to: edge.map[label]!, source: 'graph', overlays: applied };
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return route;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** 실제로 탄 간선을 남긴다 — `taken` 은 실제 다음 노드(그래프 답과 다르면 `honored: false` · 그 이유를 `reason` 에). */
|
|
79
|
+
export function recordJourneyEdge(route: JourneyRoute, taken: string, reason?: string): void {
|
|
80
|
+
try {
|
|
81
|
+
debug.log('self-implement', 'graph-edge-taken', {
|
|
82
|
+
graphId: 'self-implement', ...route, taken, honored: route.to === null || route.to === taken,
|
|
83
|
+
...(reason === undefined ? {} : { reason }), ...journeyJoinFields(),
|
|
84
|
+
});
|
|
85
|
+
} catch { /* 관측은 fail-soft */ }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** 판독 ⊕ 그 자리에서 기록 — 판독 자리가 곧 실제 단계 경계일 때만 쓴다. */
|
|
89
|
+
export function routeJourneyEdge(
|
|
90
|
+
from: string,
|
|
91
|
+
label: string,
|
|
92
|
+
state: Readonly<Record<string, unknown>> = {},
|
|
93
|
+
deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[] } = {},
|
|
94
|
+
): JourneyRoute {
|
|
95
|
+
const route = readJourneyEdge(from, label, state, deps);
|
|
96
|
+
recordJourneyEdge(route, route.to ?? label);
|
|
97
|
+
return route;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** 입구의 대기열 갈래 — 그래프가 고른 다음 노드로 정한다. 그래프가 답을 못 내면 코드 라벨을 따른다.
|
|
101
|
+
* ⛔ `eligible`(자리 있음 · 대기열 자식 아님 · --no-queue 아님)은 그래프가 못 넘는 전제다. */
|
|
102
|
+
export function intakeTakesQueue(label: 'queued' | 'direct', route: Pick<JourneyRoute, 'source' | 'to'>, eligible: boolean): boolean {
|
|
103
|
+
const graphQueues = route.source === 'graph' ? route.to === 'queue' : label === 'queued';
|
|
104
|
+
return graphQueues && eligible;
|
|
105
|
+
}
|
|
@@ -538,6 +538,9 @@ export interface LaunchPreflightInput {
|
|
|
538
538
|
readonly askTargetPaths?: readonly string[];
|
|
539
539
|
/** 대상 경로 라벨이 «있는데» 거부된 조각. 0건 막음 문면이 그 이유를 말하게 한다(판정은 안 바꾼다). */
|
|
540
540
|
readonly askTargetPathRejections?: readonly AskTargetPathHintRejection[];
|
|
541
|
+
/** AUTO-TARGET: machine-suggested target paths dropped because the goal is NOT-GROUNDED (no persistent evidence).
|
|
542
|
+
* Non-empty = the goal is a scope card and must not launch an implementation. */
|
|
543
|
+
readonly notGroundedDroppedTargetPaths?: readonly string[];
|
|
541
544
|
/** ask 원문 경로. 있으면 ask-outside-path 경고만 이 목록과 최종 대상을 비교한다. */
|
|
542
545
|
readonly askOutsidePathHints?: readonly string[];
|
|
543
546
|
/** 이번에 쏠 골의 브랜치 이름. 없으면 형제 PR 축의 경고를 내지 않는다. */
|
|
@@ -559,19 +562,31 @@ function emitAskMarkerObservation(result: LaunchPreflightResult): void {
|
|
|
559
562
|
emittedAskMarkerObservations.add(result);
|
|
560
563
|
}
|
|
561
564
|
|
|
565
|
+
/** AUTO-TARGET: blocker name for a NOT-GROUNDED goal whose only target paths were machine-suggested (a scope card). */
|
|
566
|
+
export const NOT_GROUNDED_SCOPE_CARD_BLOCKER = '(NOT-GROUNDED 범위 카드)';
|
|
567
|
+
|
|
562
568
|
export function evaluateLaunchPreflight(input: LaunchPreflightInput): LaunchPreflightResult {
|
|
563
569
|
const paths = [...new Set(input.paths.filter((path) => path.trim().length > 0))];
|
|
564
570
|
const blockers: LaunchPreflightBlocker[] = [];
|
|
565
571
|
const warnings: LaunchPreflightBlocker[] = [];
|
|
566
572
|
|
|
573
|
+
// AUTO-TARGET (10-08 canary · TSC-HEAP): a NOT-GROUNDED goal whose only target paths came from the
|
|
574
|
+
// harness candidate search is a scope card — refuse it with that reason, not the generic «no label» text.
|
|
575
|
+
const notGroundedDropped = input.notGroundedDroppedTargetPaths ?? [];
|
|
576
|
+
const notGroundedDetail = notGroundedDropped.length > 0
|
|
577
|
+
? `골이 NOT-GROUNDED(영속 근거 0)라 하니스 후보 검색이 넣은 대상 경로 ${notGroundedDropped.length}개(${notGroundedDropped.slice(0, 3).join(' · ')}${notGroundedDropped.length > 3 ? ' …' : ''})를 대상으로 쓰지 않는다 — 범위 카드: 구현 발사 대상이 아니다 · ask 첫 줄에 사람이 「대상 경로: <파일>」을 적거나 접지 근거를 복구한 뒤 다시 저작`
|
|
578
|
+
: undefined;
|
|
579
|
+
if (notGroundedDetail !== undefined && paths.length > 0) {
|
|
580
|
+
blockers.push({ kind: 'no-target-paths', name: NOT_GROUNDED_SCOPE_CARD_BLOCKER, detail: notGroundedDetail });
|
|
581
|
+
}
|
|
567
582
|
// ① 모집단이 0이면 «통과»가 아니라 «막는 사유»다(METHOD v32 를 이 코드에도 적용).
|
|
568
583
|
if (paths.length === 0) {
|
|
569
584
|
blockers.push({
|
|
570
585
|
kind: 'no-target-paths',
|
|
571
|
-
name: '(대상 경로 0)',
|
|
586
|
+
name: notGroundedDetail !== undefined ? NOT_GROUNDED_SCOPE_CARD_BLOCKER : '(대상 경로 0)',
|
|
572
587
|
// ⛔ 2026-09-23 — 라벨이 «있는데» 조각이 거부된 경우를 「라벨을 넣어라」로 뭉개면 「거부됐다」를 「없다」로 읽게 된다
|
|
573
588
|
// (실측: `대상 경로: README.md — 설명…` 한 줄 → has-whitespace 로 통째 거부 · 문면은 「넣어라」뿐이었다).
|
|
574
|
-
detail: (input.askTargetPathRejections?.length
|
|
589
|
+
detail: notGroundedDetail !== undefined ? notGroundedDetail : (input.askTargetPathRejections?.length
|
|
575
590
|
? `대상 경로 라벨은 있는데 조각 ${input.askTargetPathRejections.length}개가 거부됐다: ${input.askTargetPathRejections.slice(0, 3).map((r) => `「${r.fragment.length > 40 ? `${r.fragment.slice(0, 40)}…` : r.fragment}」(${r.reason})`).join(' · ')} — 그 줄에는 «경로만» 둔다(설명은 다음 줄)`
|
|
576
591
|
: '골에서 대상 경로를 하나도 못 뽑았다 — ask 첫 줄에 「대상 경로: <파일> · <파일>」을 넣어라')
|
|
577
592
|
+ ' — 이 상태의 「위반 0」은 「검사했다」가 아니다 — elanous self author --inspect-target-paths "<문면>"',
|
|
@@ -1192,6 +1207,9 @@ export interface AskPreflightDeps {
|
|
|
1192
1207
|
readonly askTargetPaths?: (document: string) => readonly string[];
|
|
1193
1208
|
/** 대상 경로 라벨 «안»에서 거부된 조각(이유 포함). 0건 막음 문면이 「라벨이 없다」와 「있는데 거부됐다」를 가르게 한다. */
|
|
1194
1209
|
readonly askTargetPathRejections?: (document: string) => readonly AskTargetPathHintRejection[];
|
|
1210
|
+
/** AUTO-TARGET: true when the authored goal is NOT-GROUNDED with no persistent evidence (a scope card).
|
|
1211
|
+
* Omitted = this distinction is not made (existing behavior). Production wires `isNotGroundedWithoutPersistentEvidence`. */
|
|
1212
|
+
readonly notGroundedWithoutPersistentEvidence?: (document: string) => boolean;
|
|
1195
1213
|
}
|
|
1196
1214
|
|
|
1197
1215
|
export interface AskPreflightOptions {
|
|
@@ -1212,6 +1230,10 @@ export interface AskPreflightOptions {
|
|
|
1212
1230
|
readonly plannedBranch?: string;
|
|
1213
1231
|
/** 저작 전 ask 원문. 주면 기존 ask-marker-check로 형식을 관측하되 발사를 막지 않는다. */
|
|
1214
1232
|
readonly askText?: string;
|
|
1233
|
+
/** AUTO-TARGET: target paths the harness put into the ask (candidate search), not the human.
|
|
1234
|
+
* If the authored goal is NOT-GROUNDED without persistent evidence, these paths are dropped and the
|
|
1235
|
+
* goal stops before launch (`no-target-paths` blocker naming the reason). */
|
|
1236
|
+
readonly machineSuggestedTargetPaths?: readonly string[];
|
|
1215
1237
|
}
|
|
1216
1238
|
|
|
1217
1239
|
export type PlannedBranchResolution =
|
|
@@ -1539,7 +1561,24 @@ export function decideAskPreflight(
|
|
|
1539
1561
|
}
|
|
1540
1562
|
}
|
|
1541
1563
|
// ⛔ 저작 전에는 pathsOverride 자체가 ask 대상 힌트다. 저작 뒤에는 골에서 뽑은 대상만 역할로 쓴다.
|
|
1542
|
-
const
|
|
1564
|
+
const declaredAskTargetPaths = opts.pathsOverride ?? (goalDocument && deps.askTargetPaths ? deps.askTargetPaths(goalDocument) : []);
|
|
1565
|
+
// AUTO-TARGET: a NOT-GROUNDED goal (no persistent evidence) carries no machine-suggested target path.
|
|
1566
|
+
const machineSuggested = new Set((opts.machineSuggestedTargetPaths ?? []).map((path) => path.trim()).filter(Boolean));
|
|
1567
|
+
let notGroundedGoal = false;
|
|
1568
|
+
if (!opts.pathsOverride && goalDocument !== null && machineSuggested.size > 0 && deps.notGroundedWithoutPersistentEvidence) {
|
|
1569
|
+
try { notGroundedGoal = deps.notGroundedWithoutPersistentEvidence(goalDocument); } catch { notGroundedGoal = false; }
|
|
1570
|
+
}
|
|
1571
|
+
const notGroundedDroppedTargetPaths = notGroundedGoal ? declaredAskTargetPaths.filter((path) => machineSuggested.has(path)) : [];
|
|
1572
|
+
const askTargetPaths = notGroundedDroppedTargetPaths.length > 0
|
|
1573
|
+
? declaredAskTargetPaths.filter((path) => !machineSuggested.has(path))
|
|
1574
|
+
: declaredAskTargetPaths;
|
|
1575
|
+
if (notGroundedDroppedTargetPaths.length > 0) {
|
|
1576
|
+
try {
|
|
1577
|
+
debug.log('harness.preflight', 'not-grounded-target-paths-dropped', { goalFile: opts.goalFile, dropped: notGroundedDroppedTargetPaths });
|
|
1578
|
+
} catch {
|
|
1579
|
+
// Observation never changes the launch decision.
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1543
1582
|
// 저작 뒤에는 접지가 읽은 경로와 선언 대상 경로를 함께 검사한다. 저작 전 pathsOverride는 그대로 쓴다.
|
|
1544
1583
|
const paths = opts.pathsOverride ?? [...new Set([...tracedPaths, ...askTargetPaths])];
|
|
1545
1584
|
const askMarkerInspection = opts.askText === undefined
|
|
@@ -1677,6 +1716,7 @@ export function decideAskPreflight(
|
|
|
1677
1716
|
...(goalRulersUnknownReason ? { goalRulersUnknownReason } : {}),
|
|
1678
1717
|
preexistingFailures,
|
|
1679
1718
|
...(askTargetPaths.length > 0 ? { askTargetPaths } : {}),
|
|
1719
|
+
...(notGroundedDroppedTargetPaths.length > 0 ? { notGroundedDroppedTargetPaths } : {}),
|
|
1680
1720
|
...(askTargetPaths.length === 0 && goalDocument && deps.askTargetPathRejections
|
|
1681
1721
|
? { askTargetPathRejections: deps.askTargetPathRejections(goalDocument) }
|
|
1682
1722
|
: {}),
|
|
@@ -298,6 +298,8 @@ export interface SelfDevJobResult {
|
|
|
298
298
|
providerErrors?: { count: number; provider: string; category: 'quota' | 'credential' | 'request' | 'other' };
|
|
299
299
|
/** Stable child run identity used to join its run-ledger proposal. */
|
|
300
300
|
runId?: string;
|
|
301
|
+
/** Self review verdict bound to the PR head observed by the child; absent if either observation is missing. */
|
|
302
|
+
selfReview?: { verdict: 'pass' | 'fail'; head: string };
|
|
301
303
|
/** Whether the child review actually ran; omitted preserves legacy producers. */
|
|
302
304
|
reviewed?: boolean;
|
|
303
305
|
/** Why the child did not run review; omitted preserves legacy review-unobserved handling. */
|
|
@@ -1499,6 +1501,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
|
|
|
1499
1501
|
...(disp?.prNumber !== undefined ? { prNumber: disp.prNumber } : {}),
|
|
1500
1502
|
...(disp?.merged !== undefined ? { merged: disp.merged } : {}),
|
|
1501
1503
|
...(disp?.checkedHeadCommit ? { checkedHeadCommit: disp.checkedHeadCommit } : {}),
|
|
1504
|
+
...(disp?.selfReview ? { selfReview: disp.selfReview } : {}),
|
|
1502
1505
|
// ⭐ `A1` — 판정 3종을 «끝까지» 옮긴다. 여기서 빠지면 트리아지가 눈을 잃는다.
|
|
1503
1506
|
...(disp?.mergeReason ? { mergeReason: disp.mergeReason } : {}),
|
|
1504
1507
|
...(!cancelling && disp?.stopReason ? { stopReason: disp.stopReason } : {}),
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
// Release path =
|
|
2
|
-
//
|
|
3
|
-
|
|
1
|
+
// Release path = release scripts and graph, manifest, notes and cut schedule, plus gate execution modules
|
|
2
|
+
// imported by scripts/release-loop/gate-node.ts (pod-command-job → pod-pool → pod-lease; pod-bun-cache; pod-install-slots; gate-shards).
|
|
3
|
+
// The checklist store (`checklist.ts`, `feature-store.ts`) remains shared ops ledger code (OP 10-03).
|
|
4
|
+
export const RELEASE_PATH_PREFIXES = ['scripts/release-loop/', 'graphs/release/', 'src/release-loop/manifest', 'src/release-loop/release-note', 'src/release-loop/release-schedule',
|
|
5
|
+
'src/task-orchestrator/surfaces/pod-command-job.ts', 'src/task-orchestrator/surfaces/pod-pool.ts', 'src/task-orchestrator/surfaces/pod-lease.ts',
|
|
6
|
+
'src/task-orchestrator/surfaces/pod-bun-cache.ts', 'src/task-orchestrator/surfaces/pod-install-slots.ts', 'src/release-loop/gate-shards.ts'] as const;
|
|
4
7
|
export const RELEASE_PATH_LABEL = 'elanous:release-path';
|
|
5
8
|
|
|
6
9
|
/** Flatten every GitHub PR file page, including the source of a rename. */
|
|
@@ -35,7 +38,7 @@ export function releaseGitDiffPaths(output: string): string[] {
|
|
|
35
38
|
|
|
36
39
|
/** Evaluate the paths from the opened PR, not the requested goal or local working tree. */
|
|
37
40
|
export function releasePathHold(paths: readonly string[]): string | undefined {
|
|
38
|
-
return paths.find((path) => RELEASE_PATH_PREFIXES.some((prefix) => path.startsWith(prefix)));
|
|
41
|
+
return paths.find((path) => RELEASE_PATH_PREFIXES.some((prefix) => prefix.endsWith('.ts') ? path === prefix : path.startsWith(prefix)));
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/** Fixed opening of the hold comment — also how a PR held by several merge surfaces (or polls) is recognised, so it is posted once. */
|
|
@@ -19,6 +19,89 @@
|
|
|
19
19
|
// 쿼터 축은 과부하에 «반응하지 않는다».
|
|
20
20
|
import { resolveModelAlias } from '../intelligence-map/model-alias.js';
|
|
21
21
|
import type { LLMProvider } from '../llm.js';
|
|
22
|
+
import { spawnSync } from 'node:child_process';
|
|
23
|
+
import { claudeBackend, resolveBackendSpawn } from '../agent-mission/driver.js';
|
|
24
|
+
import { checkClaudeSubscription } from '../agent-mission/claude-subscription.js';
|
|
25
|
+
import { getAcpBackend, type AcpBackendSpec } from '../acp/backend-registry.js';
|
|
26
|
+
import type { SubscriptionReviewerSpec } from '../user-config.js';
|
|
27
|
+
|
|
28
|
+
export interface SubscriptionReviewerDeps {
|
|
29
|
+
/** Returns measured Claude subscription usage; unknown usage fails closed. */
|
|
30
|
+
usedPercent?: () => number | undefined;
|
|
31
|
+
checkSubscription?: (env: Record<string, string>) => boolean;
|
|
32
|
+
runStatus?: (command: string, args: string[], env: Record<string, string>) => { status: number | null; stdout?: string | Buffer | null };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The runner and the subscription probe share the PTY backend's billing-env scrub. */
|
|
36
|
+
export function subscriptionReviewerSpawn(spec: SubscriptionReviewerSpec, env: NodeJS.ProcessEnv = process.env): {
|
|
37
|
+
command: string; args: string[]; env: Record<string, string>; backendSpec: AcpBackendSpec;
|
|
38
|
+
} {
|
|
39
|
+
const executor = spec.executor ?? 'cct';
|
|
40
|
+
const { env: cleanEnv } = resolveBackendSpawn(claudeBackend, env);
|
|
41
|
+
const command = executor === 'cct' ? 'teamclaude' : 'claude';
|
|
42
|
+
const args = executor === 'cct'
|
|
43
|
+
? ['run', '--auto-fallback', '--', '--dangerously-skip-permissions']
|
|
44
|
+
: ['--dangerously-skip-permissions'];
|
|
45
|
+
return { command, args, env: cleanEnv,
|
|
46
|
+
backendSpec: { ...getAcpBackend('claude'), command, args } };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Guard the ACP review before spawning. An unmeasured quota never authorizes subscription use. */
|
|
50
|
+
export function subscriptionReviewerAvailability(
|
|
51
|
+
spec: SubscriptionReviewerSpec,
|
|
52
|
+
cap: number,
|
|
53
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
54
|
+
deps: SubscriptionReviewerDeps = {},
|
|
55
|
+
): { spawn?: ReturnType<typeof subscriptionReviewerSpawn>; reason?: string } {
|
|
56
|
+
const spawn = subscriptionReviewerSpawn(spec, env);
|
|
57
|
+
const executor = spec.executor ?? 'cct';
|
|
58
|
+
const runStatus = deps.runStatus ?? ((command: string, args: string[], cleanEnv: Record<string, string>) =>
|
|
59
|
+
spawnSync(command, args, { env: { ...cleanEnv, NODE_ENV: process.env.NODE_ENV }, encoding: 'utf8', timeout: 5_000 }));
|
|
60
|
+
const usedPercent = deps.usedPercent ?? (() => {
|
|
61
|
+
const result = runStatus('teamclaude', ['status'], spawn.env);
|
|
62
|
+
if (result.status !== 0) return undefined;
|
|
63
|
+
// Only a named usage percentage is accepted; a random percentage in status is not quota evidence.
|
|
64
|
+
const match = String(result.stdout).match(/(?:usage|used)\s*[:=]?\s*(\d+(?:\.\d+)?)\s*%/i);
|
|
65
|
+
return match ? Number(match[1]) : undefined;
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
const subscribed = deps.checkSubscription ?? ((cleanEnv: Record<string, string>) => {
|
|
69
|
+
if (executor === 'cc') return checkClaudeSubscription({ env: cleanEnv }).ok;
|
|
70
|
+
const status = runStatus('teamclaude', ['status'], cleanEnv);
|
|
71
|
+
return status.status === 0 && /(?:subscription|claude\.ai|claude\s+(?:max|pro))/i.test(String(status.stdout))
|
|
72
|
+
&& !/(?:logged\s*out|not\s+logged\s+in|api[_ -]?key|not\s+authenticated)/i.test(String(status.stdout));
|
|
73
|
+
});
|
|
74
|
+
if (!subscribed(spawn.env)) return { reason: `${executor} subscription check failed` };
|
|
75
|
+
const used = usedPercent();
|
|
76
|
+
if (!Number.isFinite(cap) || cap < 0 || cap > 100 || used === undefined
|
|
77
|
+
|| !Number.isFinite(used) || used < 0 || used >= cap) return { reason: `Claude subscription usage unavailable or at harness cap (${cap}%)` };
|
|
78
|
+
return { spawn };
|
|
79
|
+
} catch {
|
|
80
|
+
return { reason: `${executor} subscription check failed` };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Keep a single notice attached to the actual default review result. */
|
|
85
|
+
export async function runSubscriptionReviewer(
|
|
86
|
+
spec: SubscriptionReviewerSpec | undefined,
|
|
87
|
+
cap: number,
|
|
88
|
+
prompt: string,
|
|
89
|
+
defaultReview: (prompt: string) => Promise<string>,
|
|
90
|
+
acpReview: (prompt: string, spawn: ReturnType<typeof subscriptionReviewerSpawn>) => Promise<string>,
|
|
91
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
92
|
+
deps: SubscriptionReviewerDeps = {},
|
|
93
|
+
): Promise<string> {
|
|
94
|
+
if (!spec) return defaultReview(prompt);
|
|
95
|
+
const availability = subscriptionReviewerAvailability(spec, cap, env, deps);
|
|
96
|
+
if (availability.spawn) {
|
|
97
|
+
try {
|
|
98
|
+
const text = await acpReview(prompt, availability.spawn);
|
|
99
|
+
if (text.trim()) return text;
|
|
100
|
+
} catch { /* ACP failure is not a completed review. */ }
|
|
101
|
+
}
|
|
102
|
+
const reason = availability.reason ?? 'ACP review failed';
|
|
103
|
+
return `${await defaultReview(prompt)}\n[reviewer fallback: ${reason}; default reviewer used]`;
|
|
104
|
+
}
|
|
22
105
|
|
|
23
106
|
export type ReviewFailureReason =
|
|
24
107
|
| 'overloaded'
|
|
@@ -623,7 +623,11 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
|
|
|
623
623
|
if (decision.stopReason && opts.taskAgentShadow !== false) {
|
|
624
624
|
// TASK-AGENT-SHADOW — 판단부를 그림자로 부른다(실행 0). 어떤 오류도 런의 결말을 바꾸지 않는다.
|
|
625
625
|
try {
|
|
626
|
-
|
|
626
|
+
const pr = results.find((result) => typeof result.prNumber === 'number' && result.prNumber > 0)?.prNumber;
|
|
627
|
+
const reviewed = results.filter((result) => result.prNumber === pr && result.selfReview && result.merged !== true);
|
|
628
|
+
const selfReview = pr && reviewed.length === 1 ? reviewed[0]!.selfReview : undefined;
|
|
629
|
+
await (opts.taskAgentShadow ?? recordTaskAgentShadowMove)({ runId, stopReason: decision.stopReason, results,
|
|
630
|
+
...(selfReview ? { selfReview } : {}), cycleId: `${runId ?? 'unknown'}:${decision.round}` });
|
|
627
631
|
} catch (error) {
|
|
628
632
|
try { debug.log('task-agent', 'shadow-move-failed', { runId, stopReason: decision.stopReason, error: String(error) }); } catch { /* fail-open */ }
|
|
629
633
|
}
|