elanous 0.2.20 → 0.2.21
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/MObU8ujkMciAKr6ljAV05/_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-77fad80cf54477c6.js → 1307-c97eba9fb72a9a5e.js} +1 -1
- 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/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/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/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-59fedea50d13c762.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-f1762140ef9a96b1.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-7581825d511a64c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +23 -0
- package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +1 -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-937c92292a4ab4f0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-85b316bb4235980b.js → page-d781be3e3a9cfd74.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-9b2b26a33cb2cd42.js → page-b0a80997903852d8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-c9955fde67b1bcb5.js → page-2b1263165630d9c8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-7a852956c74015a3.js → page-ea998f7f5d156bea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-4ba4abe096b6c2a8.js → page-e2d6bed48ac20120.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-575d4a8b4f7becb2.js → page-111cabe4d1fd69ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/{page-f5d56ff5f45ad164.js → page-544dd4bd4847eeb7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/{page-2260e9eef0357421.js → page-3ee191319bf97d87.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-466bf0ee16ad1432.js → page-a449f1ed472b81c2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-a23bc71713bcc08f.js → page-9045094d6d3b5cd0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-ec102c9b8b691e37.js → page-7a12f61be4a579d1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/{page-f6055495e9ed7ea8.js → page-8cc707bd09a497d9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-db03ae3589a81c9e.js → page-dc39ee7a36d26385.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-4a6463b97f0ad94f.js → page-84ae759f76053672.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-75bffecc9aa1004e.js → page-3db58ddb61fe2be9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-31d5b875760bb62d.js → page-2fe368efb6de3b6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/{page-c26fa10aac6c21c4.js → page-8d04132dd0ac5e10.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-68793c6e10331d66.js → page-f23484de467c9ea3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/{page-46d5201d2207a511.js → page-c69762987b751174.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/{page-be1c4e8697f22360.js → page-d75f7cd65845ce98.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/{page-0fd895fab9b62c1b.js → page-a6eb73b8a4840f1c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-c6e4364d9de8f717.js → page-6c0b88068c143f15.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-0acc8e198f7b0dfb.js → page-7f8d7fcdf058a845.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-34882c84f84021c5.js → page-22163556cd38bc88.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.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/e81df11490b4413b.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/drafts/recipes.yaml +4 -4
- package/graphs/implement-loop.yaml +277 -5
- package/package.json +1 -1
- package/scripts/coord-channel-watch.sh +31 -4
- package/scripts/docs-lint.ts +4 -1
- package/scripts/marketing/generate-ax-brief.ts +18 -1
- package/scripts/measure-nl-routing-corpus.ts +11 -3
- package/scripts/release-loop/gate-node.ts +5 -5
- package/scripts/release-loop/shard-plan.ts +50 -5
- package/scripts/rhythm/daily.ts +2 -1
- package/src/browser-cdp/client.ts +10 -5
- 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/tasks-cli.ts +106 -0
- package/src/dashboard/index.ts +40 -4
- package/src/esc-abort-gate.ts +3 -1
- package/src/graph-runner/graph-cli.ts +57 -0
- package/src/graph-runner/graph-run-api.ts +13 -0
- package/src/graph-wizard/archetypes.ts +88 -0
- package/src/graph-wizard/generate.ts +545 -0
- package/src/graph-wizard/saved-steps.ts +120 -0
- package/src/graph-wizard/steps.ts +193 -0
- package/src/harness/harness-cli-command.ts +68 -12
- package/src/index.ts +7 -4
- package/src/intake-plane/digest.ts +18 -11
- package/src/maturity/feature-maturity.ts +2 -1
- package/src/nexus/api/draft-metrics.ts +114 -0
- package/src/nexus/api/graph-wizard-api.ts +53 -0
- package/src/nexus/api/graphs-api.ts +50 -12
- package/src/nexus/api/harness-traversal.ts +205 -0
- package/src/nexus/api/http-server.ts +31 -0
- package/src/nexus/outbound/router.ts +28 -8
- 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/release-loop/gate-shards.ts +7 -2
- package/src/self-dev/ask-launch-flow.ts +4 -2
- package/src/self-dev/ask-launch-io.ts +3 -1
- 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/release-path-guard.ts +7 -4
- package/src/self-implement/frozen-merges.ts +23 -0
- package/src/self-implement/goal-author.ts +14 -0
- package/src/self-implement/heal-intake.ts +3 -0
- package/src/self-implement/orchestrator.ts +16 -1
- package/src/self-implement/seams.ts +3 -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 +17 -3
- package/src/task-agent/card-evidence.ts +6 -0
- package/src/task-agent/parent-host.ts +315 -0
- package/src/task-agent/task-hand.ts +9 -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/self-implement-pod.ts +39 -6
- package/src/tool-runtime/browser-runtime.ts +87 -3
- package/src/tool-runtime/index.ts +1 -0
- package/src/user-config.ts +20 -4
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/Bam1YziK2iH9bN4K0utGk/_buildManifest.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/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/approvals/page-c855c24de7db74fe.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/loops/page-35bfec2e631d3eae.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/missions/[id]/page-f9ccb1b1adbea14d.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/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/showroom/page-d81c07a7b4f618ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-cf0a4b4abead71ea.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/vault/page-8b6c1454a8e8f306.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 → MObU8ujkMciAKr6ljAV05}/_ssgManifest.js +0 -0
- /package/skills/project-onboarding/{skill.md → SKILL.md} +0 -0
|
@@ -38,8 +38,12 @@
|
|
|
38
38
|
# (파일 이름은 RFC 어휘를 남겨 둔다 — 사람이 찾는 이름과 조인 키가 다를 수 있다.)
|
|
39
39
|
graph_id: self-implement
|
|
40
40
|
version: 1
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
# ⭐ HARNESS-FULL-GRAPH (0.2.21 · 대표 10-08) — 입구부터 회수까지 «여정 전체»가 노드다.
|
|
42
|
+
# 📄 내부 문서 `RFC-harness-full-journey-as-graph-2026-10-08` · 코드 = src/self-dev/graph-journey-nodes.ts
|
|
43
|
+
# ⛔ 여정 노드(intake … stopped)의 id 는 원장·라이브 그래프 화면의 조인 키다 — 바꾸지 마라.
|
|
44
|
+
# 🔀 분기는 «데이터»다(`on:` 상태 키 ⊕ `map:` 값→노드) — 기본 = 풀세트, 환경(substrate·freeze·queue)이 일부를 건너뛴다.
|
|
45
|
+
entry_node: intake
|
|
46
|
+
terminal_nodes: [cleanup, stopped]
|
|
43
47
|
|
|
44
48
|
# Runner-provided inputs are declared here so contract-flow can distinguish them from undeclared gaps.
|
|
45
49
|
runner_inputs: [ask_text, goal, worktree, branch, review-intent, head-sha, base-branch]
|
|
@@ -61,8 +65,13 @@ runner_inputs: [ask_text, goal, worktree, branch, review-intent, head-sha, base-
|
|
|
61
65
|
# 🔑 ⇒ ***여기 적은 도구 권한은 「선언」이고 「제한」이 아니다.*** 자식의 실제 권한은 코드가 정한다.
|
|
62
66
|
# ⛔ 그러니 이 칸을 좁혀 「자식이 그 도구를 못 쓴다」고 읽지 마라 — 지금은 안 그렇다.
|
|
63
67
|
# 🔎 반증: rg -n "readonly contract" src/self-implement/graph-templates.ts (⇒ 0건이면 여전히 그렇다)
|
|
68
|
+
# 🧩 `group:` = 나중에 `graphs/units/*.yaml` 로 들어 올릴 «한 노드로 부르는 부분 그래프» 단위(대표 10-08).
|
|
69
|
+
# entry · dispatch · author · dispatch-pod · build · verify · land · recover · end
|
|
70
|
+
# ⛔ 지금 파서는 이 칸을 «읽지 않는다»(무시) — 단위 호출은 0.2.22(RFC §6). 묶음은 «위치»가 아니라 이 태그로 정한다
|
|
71
|
+
# (오버레이가 /nodes/<번호> 로 가리켜 노드를 재배열할 수 없다).
|
|
64
72
|
nodes:
|
|
65
73
|
- node_id: author
|
|
74
|
+
group: author
|
|
66
75
|
kind: agent
|
|
67
76
|
recipe: goal-author
|
|
68
77
|
max_visits: 2
|
|
@@ -74,6 +83,7 @@ nodes:
|
|
|
74
83
|
outputs: [goal_path, goal_id, goal_type, grounding_context]
|
|
75
84
|
|
|
76
85
|
- node_id: plan
|
|
86
|
+
group: author
|
|
77
87
|
kind: agent
|
|
78
88
|
recipe: harness-plan-rfc
|
|
79
89
|
max_visits: 2
|
|
@@ -85,6 +95,7 @@ nodes:
|
|
|
85
95
|
outputs: [rfc_path, markdown, arcs, open_questions]
|
|
86
96
|
|
|
87
97
|
- node_id: decompose
|
|
98
|
+
group: author
|
|
88
99
|
kind: judge
|
|
89
100
|
recipe: fabric-decompose-adapter
|
|
90
101
|
max_visits: 12
|
|
@@ -96,6 +107,7 @@ nodes:
|
|
|
96
107
|
outputs: [pieces, ordering, depends_on_edges, hot_path_edges, omitted_goal_count]
|
|
97
108
|
|
|
98
109
|
- node_id: implement
|
|
110
|
+
group: build
|
|
99
111
|
kind: agent
|
|
100
112
|
recipe: headless-goal-loop # seams.implement → 자식 PTY
|
|
101
113
|
max_visits: 12
|
|
@@ -109,6 +121,7 @@ nodes:
|
|
|
109
121
|
outputs: [diff, summary, changed-files]
|
|
110
122
|
|
|
111
123
|
- node_id: gate
|
|
124
|
+
group: verify
|
|
112
125
|
kind: gate
|
|
113
126
|
recipe: gate-baseline # 변경 파일 «범위» · 새 회귀만
|
|
114
127
|
max_visits: 11
|
|
@@ -122,6 +135,7 @@ nodes:
|
|
|
122
135
|
outputs: [passed, gate-log, reflect-gate-facts]
|
|
123
136
|
|
|
124
137
|
- node_id: review
|
|
138
|
+
group: verify
|
|
125
139
|
kind: judge
|
|
126
140
|
recipe: pr-reviewer # agent-substrate/pr-reviewer
|
|
127
141
|
max_visits: 11
|
|
@@ -135,6 +149,7 @@ nodes:
|
|
|
135
149
|
outputs: [verdict, must-fix, should-fix, review-summary]
|
|
136
150
|
|
|
137
151
|
- node_id: rework
|
|
152
|
+
group: verify
|
|
138
153
|
kind: agent
|
|
139
154
|
recipe: headless-goal-loop # 같은 루프의 다음 라운드
|
|
140
155
|
max_visits: 10
|
|
@@ -148,6 +163,7 @@ nodes:
|
|
|
148
163
|
outputs: [diff, summary]
|
|
149
164
|
|
|
150
165
|
- node_id: main-sync
|
|
166
|
+
group: land
|
|
151
167
|
kind: git
|
|
152
168
|
recipe: seams-git-merge-main # LLM 충돌해결 포함
|
|
153
169
|
max_visits: 2
|
|
@@ -159,6 +175,7 @@ nodes:
|
|
|
159
175
|
outputs: [synced, conflicts]
|
|
160
176
|
|
|
161
177
|
- node_id: regate
|
|
178
|
+
group: land
|
|
162
179
|
kind: gate
|
|
163
180
|
recipe: gate-baseline # 충돌해결 «뒤» 재-gate
|
|
164
181
|
max_visits: 2
|
|
@@ -170,6 +187,7 @@ nodes:
|
|
|
170
187
|
outputs: [passed, gate-log]
|
|
171
188
|
|
|
172
189
|
- node_id: open-pr
|
|
190
|
+
group: land
|
|
173
191
|
kind: git
|
|
174
192
|
recipe: seams-gh-open-pr
|
|
175
193
|
# 📏 실측 2026-09-08 (원장 30일 · 전 우주 · 걸음 191개 소급 계산):
|
|
@@ -185,6 +203,7 @@ nodes:
|
|
|
185
203
|
outputs: [pr-number, pr-url]
|
|
186
204
|
|
|
187
205
|
- node_id: merge
|
|
206
|
+
group: land
|
|
188
207
|
kind: git
|
|
189
208
|
recipe: seams-gh-merge-squash
|
|
190
209
|
# 📏 실측 2026-09-08 (원장 30일 · 전 우주 · 걸음 191개 소급 계산):
|
|
@@ -199,6 +218,176 @@ nodes:
|
|
|
199
218
|
tools: gh-pr-merge
|
|
200
219
|
outputs: [merged]
|
|
201
220
|
|
|
221
|
+
# ⛔ 여정 노드는 «목록 끝»에 둔다 — 오버레이가 JSON 포인터(/nodes/<번호>)로 노드를 가리킨다(rework-patient). 앞에 끼우면 번호가 밀린다.
|
|
222
|
+
# ───────── 여정 앞단: 입구 → 대기열 → 발사 관문 → 배치 ─────────
|
|
223
|
+
- node_id: intake
|
|
224
|
+
group: entry
|
|
225
|
+
kind: observe
|
|
226
|
+
recipe: harness-entrance # src/harness/harness-cli-command.ts (say · ask · TUI /harness)
|
|
227
|
+
max_visits: 1
|
|
228
|
+
terminal_stages: []
|
|
229
|
+
contract:
|
|
230
|
+
inputs: [ask_text]
|
|
231
|
+
tools: none
|
|
232
|
+
outputs: [entrance, journey_key]
|
|
233
|
+
|
|
234
|
+
- node_id: queue
|
|
235
|
+
group: entry
|
|
236
|
+
kind: gate
|
|
237
|
+
recipe: harness-queue # src/harness/harness-queue.ts (directSay 플래그 · 기본 끔 → 건너뜀)
|
|
238
|
+
max_visits: 1
|
|
239
|
+
terminal_stages: []
|
|
240
|
+
contract:
|
|
241
|
+
inputs: [entrance, seat]
|
|
242
|
+
tools: queue-write
|
|
243
|
+
outputs: [queue_item, queue_outcome]
|
|
244
|
+
|
|
245
|
+
- node_id: launch-gate
|
|
246
|
+
group: entry
|
|
247
|
+
kind: gate
|
|
248
|
+
recipe: pre-launch-gate # harness-cli-command.ts preLaunchGate (예산 · 같은 골 활성 런)
|
|
249
|
+
max_visits: 1
|
|
250
|
+
terminal_stages: []
|
|
251
|
+
contract:
|
|
252
|
+
inputs: [goal_id, budget]
|
|
253
|
+
tools: read-only
|
|
254
|
+
outputs: [launch_decision]
|
|
255
|
+
|
|
256
|
+
- node_id: dispatch
|
|
257
|
+
group: dispatch
|
|
258
|
+
kind: judge
|
|
259
|
+
recipe: harness-substrate-select # resolveLaunchSubstrate → substrate = local | pod
|
|
260
|
+
max_visits: 2
|
|
261
|
+
terminal_stages: []
|
|
262
|
+
contract:
|
|
263
|
+
inputs: [launch_decision]
|
|
264
|
+
tools: read-only
|
|
265
|
+
outputs: [substrate]
|
|
266
|
+
|
|
267
|
+
# ───────── Pod 배치 (substrate == pod 일 때만 — local 은 건너뛴다) ─────────
|
|
268
|
+
- node_id: pool-admit
|
|
269
|
+
group: dispatch-pod
|
|
270
|
+
kind: gate
|
|
271
|
+
recipe: pod-pool-admission # src/task-orchestrator/surfaces/self-implement-pod.ts (입장 · 멤버 슬롯 · 메모리 등급)
|
|
272
|
+
max_visits: 4
|
|
273
|
+
terminal_stages: []
|
|
274
|
+
contract:
|
|
275
|
+
inputs: [substrate, memory_tier]
|
|
276
|
+
tools: pod-lease
|
|
277
|
+
outputs: [pool_member]
|
|
278
|
+
|
|
279
|
+
- node_id: image-sync
|
|
280
|
+
group: dispatch-pod
|
|
281
|
+
kind: gate
|
|
282
|
+
recipe: pod-pool-image-sync # src/task-orchestrator/surfaces/pod-pool.ts syncPoolImages (멤버별 · pack 한 번)
|
|
283
|
+
max_visits: 4
|
|
284
|
+
terminal_stages: []
|
|
285
|
+
contract:
|
|
286
|
+
inputs: [pool_member]
|
|
287
|
+
tools: image-ship
|
|
288
|
+
outputs: [image_current]
|
|
289
|
+
|
|
290
|
+
- node_id: credential-refresh
|
|
291
|
+
group: dispatch-pod
|
|
292
|
+
kind: gate
|
|
293
|
+
recipe: pod-credential-prerefresh # self-implement-pod.ts podCodexCredentialWithPrerefresh
|
|
294
|
+
max_visits: 4
|
|
295
|
+
terminal_stages: []
|
|
296
|
+
contract:
|
|
297
|
+
inputs: [pool_member]
|
|
298
|
+
tools: credential-refresh
|
|
299
|
+
outputs: [usable_accounts]
|
|
300
|
+
|
|
301
|
+
# ───────── 착지: 동결 검사 → (보류) → 병합 → 회수 ─────────
|
|
302
|
+
- node_id: freeze-check
|
|
303
|
+
group: land
|
|
304
|
+
kind: gate
|
|
305
|
+
recipe: landing-freeze-admission # src/self-implement/frozen-merges.ts admitLandingMerge (병합 직전 한 곳)
|
|
306
|
+
max_visits: 4
|
|
307
|
+
terminal_stages: []
|
|
308
|
+
contract:
|
|
309
|
+
inputs: [pr-number]
|
|
310
|
+
tools: read-only
|
|
311
|
+
outputs: [freeze]
|
|
312
|
+
|
|
313
|
+
- node_id: hold
|
|
314
|
+
group: land
|
|
315
|
+
kind: hitl
|
|
316
|
+
recipe: frozen-merge-queue # frozen-merges.ts queueFrozenMerge → sweepFrozenMerges 가 해제 뒤 재개
|
|
317
|
+
max_visits: 4
|
|
318
|
+
terminal_stages: []
|
|
319
|
+
contract:
|
|
320
|
+
inputs: [pr-number, head-sha]
|
|
321
|
+
tools: queue-write
|
|
322
|
+
outputs: [held]
|
|
323
|
+
|
|
324
|
+
- node_id: cleanup
|
|
325
|
+
group: land
|
|
326
|
+
kind: git
|
|
327
|
+
recipe: post-merge-cleanup # src/self-implement/orchestrator.ts (워크트리 ⊕ 브랜치 회수)
|
|
328
|
+
max_visits: 1
|
|
329
|
+
terminal_stages: []
|
|
330
|
+
contract:
|
|
331
|
+
inputs: [worktree, branch]
|
|
332
|
+
tools: git-write
|
|
333
|
+
outputs: [cleaned]
|
|
334
|
+
|
|
335
|
+
# ───────── 실패 쪽: 결과 해석 → 수확 → heal → 다음 한 수 ─────────
|
|
336
|
+
- node_id: result-parse
|
|
337
|
+
group: recover
|
|
338
|
+
kind: observe
|
|
339
|
+
recipe: pod-failure-reason # src/task-orchestrator/surfaces/pod-failure-reason.ts
|
|
340
|
+
max_visits: 4
|
|
341
|
+
terminal_stages: []
|
|
342
|
+
contract:
|
|
343
|
+
inputs: [pod_log]
|
|
344
|
+
tools: read-only
|
|
345
|
+
outputs: [failure_reason]
|
|
346
|
+
|
|
347
|
+
- node_id: salvage
|
|
348
|
+
group: recover
|
|
349
|
+
kind: git
|
|
350
|
+
recipe: salvage-branch # salvage/si-task-<job>/… (Pod Job 이 push · salvage-branches.ts 가 읽는다)
|
|
351
|
+
max_visits: 4
|
|
352
|
+
terminal_stages: []
|
|
353
|
+
contract:
|
|
354
|
+
inputs: [worktree]
|
|
355
|
+
tools: git-write
|
|
356
|
+
outputs: [salvage_ref]
|
|
357
|
+
|
|
358
|
+
- node_id: heal
|
|
359
|
+
group: recover
|
|
360
|
+
kind: judge
|
|
361
|
+
recipe: heal-intake # src/self-implement/heal-intake.ts (호스트에서만)
|
|
362
|
+
max_visits: 4
|
|
363
|
+
terminal_stages: []
|
|
364
|
+
contract:
|
|
365
|
+
inputs: [failure_reason, salvage_ref]
|
|
366
|
+
tools: read-only
|
|
367
|
+
outputs: [heal_signature]
|
|
368
|
+
|
|
369
|
+
- node_id: next-move
|
|
370
|
+
group: recover
|
|
371
|
+
kind: judge
|
|
372
|
+
recipe: task-agent-judge # src/task-agent/judge.ts (판단부 → 실행부)
|
|
373
|
+
max_visits: 4
|
|
374
|
+
terminal_stages: []
|
|
375
|
+
contract:
|
|
376
|
+
inputs: [heal_signature]
|
|
377
|
+
tools: read-only
|
|
378
|
+
outputs: [next_action]
|
|
379
|
+
|
|
380
|
+
- node_id: stopped
|
|
381
|
+
group: end
|
|
382
|
+
kind: observe
|
|
383
|
+
recipe: journey-stopped # 거절·포기 — 종결
|
|
384
|
+
max_visits: 1
|
|
385
|
+
terminal_stages: []
|
|
386
|
+
contract:
|
|
387
|
+
inputs: []
|
|
388
|
+
tools: none
|
|
389
|
+
outputs: []
|
|
390
|
+
|
|
202
391
|
# ═══════════════════════════════════════════════════════════════════════
|
|
203
392
|
# 엣지 — ⛔ 출처는 «코드 선언 ⊕ 원장 실측» 둘 다다. 어느 하나만 보면 틀린다.
|
|
204
393
|
# 📏 2026-09-08 실측 (pipeline-traversal-shadow 182 걸음 · 판정 함수가 «실제로 본» 것):
|
|
@@ -207,14 +396,83 @@ nodes:
|
|
|
207
396
|
# gate→main-sync · gate→open-pr · review→open-pr
|
|
208
397
|
# 🔑 그래서 엣지마다 `observed` 를 «값으로» 적는다 — 「선언했다」와 「돈다」를 가른다.
|
|
209
398
|
edges:
|
|
399
|
+
# ───── 여정 앞단 — 분기는 «데이터»(on/map). 값은 코드가 낸다(RFC §4.3 ⑵) ─────
|
|
400
|
+
- from: intake
|
|
401
|
+
on: queue
|
|
402
|
+
map:
|
|
403
|
+
queued: queue # harness.queue.directSay 켬 ⊕ 자리 있음
|
|
404
|
+
direct: launch-gate # 기본(플래그 끔) — 대기열을 건너뛴다
|
|
405
|
+
|
|
406
|
+
- from: queue
|
|
407
|
+
on: queue_outcome
|
|
408
|
+
map:
|
|
409
|
+
launched: launch-gate # 대기열이 발사한 자식이 다시 intake 를 밟는다(queueLaunchId 로 잇는다)
|
|
410
|
+
waiting: stopped # 이 프로세스는 여기서 끝난다(발사는 대기열 tick 의 몫)
|
|
411
|
+
refused: stopped # 같은 요청이 이미 대기열에 있다
|
|
412
|
+
|
|
413
|
+
- from: launch-gate
|
|
414
|
+
on: outcome
|
|
415
|
+
map:
|
|
416
|
+
pass: dispatch
|
|
417
|
+
refuse: stopped
|
|
418
|
+
|
|
419
|
+
- from: dispatch
|
|
420
|
+
to: author
|
|
421
|
+
|
|
210
422
|
- from: author
|
|
211
423
|
to: plan
|
|
212
424
|
|
|
213
425
|
- from: plan
|
|
214
426
|
to: decompose
|
|
215
427
|
|
|
428
|
+
# ⭐ 실행 칸(substrate)이 «Pod 쪽 세 노드»를 켜고 끈다 — local 은 곧장 구현.
|
|
216
429
|
- from: decompose
|
|
217
|
-
|
|
430
|
+
on: substrate
|
|
431
|
+
map:
|
|
432
|
+
local: implement
|
|
433
|
+
pod: pool-admit
|
|
434
|
+
|
|
435
|
+
- from: pool-admit
|
|
436
|
+
on: outcome
|
|
437
|
+
map:
|
|
438
|
+
admitted: image-sync
|
|
439
|
+
refused: stopped
|
|
440
|
+
|
|
441
|
+
- from: image-sync
|
|
442
|
+
to: credential-refresh
|
|
443
|
+
|
|
444
|
+
- from: credential-refresh
|
|
445
|
+
on: outcome
|
|
446
|
+
map:
|
|
447
|
+
usable: implement
|
|
448
|
+
exhausted: stopped
|
|
449
|
+
|
|
450
|
+
# 실패 쪽 — Pod 구현이 rc≠0 이면 결과 해석으로.
|
|
451
|
+
- from: implement
|
|
452
|
+
on: pod_result
|
|
453
|
+
map:
|
|
454
|
+
failed: result-parse
|
|
455
|
+
|
|
456
|
+
- from: result-parse
|
|
457
|
+
to: salvage
|
|
458
|
+
|
|
459
|
+
# ⚠️ heal 은 실패 사건 «접수»다 — 호스트에서만(Pod 안에서는 시작 안 함 · POD-RESULT-PARSE).
|
|
460
|
+
- from: salvage
|
|
461
|
+
to: heal
|
|
462
|
+
|
|
463
|
+
- from: heal
|
|
464
|
+
to: next-move
|
|
465
|
+
|
|
466
|
+
# 출구 라벨 = task-agent 판단부의 수(TaskMove · src/task-agent/judge.ts). 관측 배선은 0.2.22(판단이 카드 단위라 런 조인 먼저).
|
|
467
|
+
- from: next-move
|
|
468
|
+
on: move
|
|
469
|
+
map:
|
|
470
|
+
narrow-relaunch: dispatch
|
|
471
|
+
salvage-relaunch: dispatch
|
|
472
|
+
alternative: dispatch
|
|
473
|
+
wait-retry: dispatch
|
|
474
|
+
decision-card: stopped
|
|
475
|
+
wait: stopped
|
|
218
476
|
|
|
219
477
|
- from: implement
|
|
220
478
|
to: gate
|
|
@@ -264,6 +522,20 @@ edges:
|
|
|
264
522
|
to: open-pr
|
|
265
523
|
observed: 80
|
|
266
524
|
|
|
525
|
+
# ⭐ HARNESS-FULL-GRAPH — 코드 간선 open-pr→merge 사이에 «동결 검사»가 늘 끼어 있었다(병합 직전 한 곳).
|
|
267
526
|
- from: open-pr
|
|
268
|
-
to:
|
|
269
|
-
observed: 80
|
|
527
|
+
to: freeze-check
|
|
528
|
+
observed: 80 # 옛 open-pr→merge 관측 — 그 사이에 동결 검사가 늘 있었다
|
|
529
|
+
|
|
530
|
+
- from: freeze-check
|
|
531
|
+
on: freeze
|
|
532
|
+
map:
|
|
533
|
+
open: merge
|
|
534
|
+
frozen: hold
|
|
535
|
+
taken: stopped # 다른 착지자(재개 sweep)가 그 PR 을 쥐었다
|
|
536
|
+
|
|
537
|
+
- from: hold
|
|
538
|
+
to: freeze-check # 해제 뒤 재검사
|
|
539
|
+
|
|
540
|
+
- from: merge
|
|
541
|
+
to: cleanup
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elanous",
|
|
3
3
|
"mcpName": "io.github.ElanvitalAI/elanous",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.21",
|
|
5
5
|
"description": "Self-healing coding harness where eyes, hands, and memory all turn on one sentence — it authors its own goals, implements them in isolated worktrees, and reviews its own work.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Elanvital AI",
|
|
@@ -240,15 +240,42 @@ lsof_fd1() {
|
|
|
240
240
|
return 0
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
# 🐧 lsof 가 없는 리눅스(게이트 Pod 이미지 · 0.2.20 컷 실측)에서는 /proc/<pid>/fd/1 을 읽어
|
|
244
|
+
# lsof -Ftn 과 «같은 모양»(t<type>\nn<name>)으로 낸다 — 아래 판정 표를 그대로 쓴다.
|
|
245
|
+
# ⛔ 못 읽으면(죽은 pid·권한) 1 을 돌려 「모름」으로 끝낸다.
|
|
246
|
+
proc_fd1() {
|
|
247
|
+
local pid="$1" target
|
|
248
|
+
target=$(readlink "/proc/$pid/fd/1" 2>/dev/null) || return 1
|
|
249
|
+
[ -n "$target" ] || return 1
|
|
250
|
+
case "$target" in
|
|
251
|
+
pipe:*) printf 'tPIPE\nn%s\n' "$target" ;;
|
|
252
|
+
socket:*) printf 'tunix\nn%s\n' "$target" ;;
|
|
253
|
+
*)
|
|
254
|
+
if [ -c "$target" ]; then printf 'tCHR\nn%s\n' "$target"
|
|
255
|
+
elif [ -f "$target" ]; then printf 'tREG\nn%s\n' "$target"
|
|
256
|
+
else printf 'tunknown\nn%s\n' "$target"
|
|
257
|
+
fi ;;
|
|
258
|
+
esac
|
|
259
|
+
return 0
|
|
260
|
+
}
|
|
261
|
+
|
|
243
262
|
delivery_of() {
|
|
244
263
|
local pid="$1" out t n
|
|
245
264
|
case "$pid" in
|
|
246
265
|
''|*[!0-9]*) printf '⚠️ «못 쟀다»(감시자 pid 를 «증명하지 못했다») — 「정상」이 아니라 «모름»이다'; return 0 ;;
|
|
247
266
|
esac
|
|
248
|
-
command -v lsof >/dev/null 2>&1
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
267
|
+
if command -v lsof >/dev/null 2>&1; then
|
|
268
|
+
if ! out=$(lsof_fd1 "$pid"); then
|
|
269
|
+
printf '⚠️ «못 쟀다»(lsof 가 %s틱 안에 안 끝나 죽였다) — 「정상」이 아니라 «모름»이다' "$LSOF_WAIT_TICKS"
|
|
270
|
+
return 0
|
|
271
|
+
fi
|
|
272
|
+
elif command -v readlink >/dev/null 2>&1 && [ -d /proc/self/fd ]; then
|
|
273
|
+
if ! out=$(proc_fd1 "$pid"); then
|
|
274
|
+
printf '⚠️ «못 쟀다»(/proc/%s/fd/1 을 못 읽었다 · lsof 없음) — 「정상」이 아니라 «모름»이다' "$pid"
|
|
275
|
+
return 0
|
|
276
|
+
fi
|
|
277
|
+
else
|
|
278
|
+
printf '⚠️ «못 쟀다»(lsof 없음) — 「정상」이 아니라 «모름»이다'; return 0
|
|
252
279
|
fi
|
|
253
280
|
t=$(printf '%s\n' "$out" | sed -n 's/^t//p' | head -1)
|
|
254
281
|
n=$(printf '%s\n' "$out" | sed -n 's/^n//p' | head -1)
|
package/scripts/docs-lint.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from '../src/autopilot/discovery/doc-lint.js';
|
|
14
14
|
import { parseIndexLinks } from '../src/autopilot/discovery/doc-inventory.js';
|
|
15
15
|
import { execFileSync } from 'node:child_process';
|
|
16
|
+
import { runGitCommand } from '../src/git-fs/runner.js';
|
|
16
17
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
17
18
|
import { basename, join, relative } from 'node:path';
|
|
18
19
|
import { sourceIdentifierInventory, inlineCodeIdentifiers } from '../src/autopilot/discovery/source-identifiers.js';
|
|
@@ -80,7 +81,9 @@ const readText = (relPath: string): string | null => { try { return readFileSync
|
|
|
80
81
|
// 전부 「못 읽음」이 되어 이 규칙이 통째로 잡음이 된다. 그래서 파일명 → repo 경로를 «한 번» 만든다.
|
|
81
82
|
// ⛔ 같은 파일명이 둘 이상이면 «해석하지 않는다** — 틀린 파일을 대면 「어긋남」이 거짓으로 난다.
|
|
82
83
|
const sourcePathsByBasename = new Map<string, string | null>();
|
|
83
|
-
|
|
84
|
+
const lsFiles = runGitCommand(repoRoot, ['ls-files', '*.ts', '*.tsx'], { encoding: 'utf-8', maxBuffer: 64 * 1024 * 1024 });
|
|
85
|
+
if (lsFiles.status !== 0) throw new Error(`git ls-files failed: ${lsFiles.stderr.trim() || `rc=${lsFiles.status}`}`);
|
|
86
|
+
for (const relPath of lsFiles.stdout.split('\n')) {
|
|
84
87
|
if (relPath === '') continue;
|
|
85
88
|
const base = basename(relPath);
|
|
86
89
|
sourcePathsByBasename.set(base, sourcePathsByBasename.has(base) ? null : relPath);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
2
|
+
import { basename, resolve } from 'node:path';
|
|
3
3
|
import { FEATURE_MATURITY } from '../../src/maturity/feature-maturity.js';
|
|
4
4
|
import type { ChecklistItem } from '../../src/release-loop/checklist.js';
|
|
5
5
|
import type { ReleaseSchedule } from '../../src/release-loop/release-schedule.js';
|
|
6
6
|
import type { MergedRunLedgerQuery } from '../../src/self-implement/run-ledger.js';
|
|
7
7
|
import { generateFeatureMap } from './generate-feature-map.js';
|
|
8
|
+
import { draftReleaseStory } from '../release-story/draft.js';
|
|
8
9
|
|
|
9
10
|
const MAP = resolve(import.meta.dir, '../../docs/marketing/MAP-value-props-to-features.md');
|
|
10
11
|
const AUTONOMY = new Set(['ORCH1', 'ORCH2', 'LOOP-LIVE1', 'AUTOQ-LOOP', 'AUTHOR-PAR', 'RUN-HELPER', 'FINISH-RATE']);
|
|
@@ -110,6 +111,22 @@ export function generateAxBrief(version: string, sources: AxBriefSources): strin
|
|
|
110
111
|
].join('\n');
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
/** Derive the next release's internal brief from its ledgers and the RELEASE-STORY version-note draft.
|
|
115
|
+
* The release loop supplies its version, ledger sources and isolated story paths; the standalone CLI stays unchanged. */
|
|
116
|
+
export function generateNextVersionAxBrief(
|
|
117
|
+
nextVersion: string,
|
|
118
|
+
sources: AxBriefSources,
|
|
119
|
+
storyOptions: Omit<Parameters<typeof draftReleaseStory>[0], 'version'> = {},
|
|
120
|
+
): string {
|
|
121
|
+
const brief = generateAxBrief(nextVersion, sources);
|
|
122
|
+
const story = draftReleaseStory({ ...storyOptions, version: nextVersion });
|
|
123
|
+
const announcementFile = story.files.find((file) => basename(file) === 'announcement.md');
|
|
124
|
+
const announcement = story.status === 'drafted' && announcementFile
|
|
125
|
+
? readFileSync(announcementFile, 'utf8').replace(/^# [^\r\n]*\r?\n/, '').trim()
|
|
126
|
+
: '사용자 대상 변경 없음 — RELEASE-STORY 초안을 건너뜀';
|
|
127
|
+
return `${brief}\n## 5. 다음 판 변화·근거 (RELEASE-STORY 초안)\n\n> 공개 전 CMO 확인 필요 · 원천: release/next.md, 해당 판의 green 칸, 연결된 검증 소구점 원장\n\n${announcement}\n`;
|
|
128
|
+
}
|
|
129
|
+
|
|
113
130
|
if (import.meta.main) {
|
|
114
131
|
const args = process.argv.slice(2);
|
|
115
132
|
const option = (name: string) => {
|
|
@@ -3,7 +3,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { buildEvalPromptToolSurface, EVAL_PROMPT_TOOL_SURFACES, isEvalPromptToolSurface, resolveReproModelId, runEvalPrompt, type EvalPromptToolSurface } from '../src/eval-prompt-cli.js';
|
|
5
5
|
import { getModelFamily } from '../src/models/prompts.js';
|
|
6
|
-
import { resolveDefaultProvider } from '../src/llm.js';
|
|
6
|
+
import { NoLlmProviderAvailableError, resolveDefaultProvider } from '../src/llm.js';
|
|
7
7
|
import { filterToolsByDeny } from '../src/tool-runtime/tool-deny.js';
|
|
8
8
|
import { getUserConfig } from '../src/user-config.js';
|
|
9
9
|
import { resolveObserveOnlyDecision, type ObserveOnlyDecision } from '../src/self-implement/observe-only.js';
|
|
@@ -80,8 +80,16 @@ function formatMachineLoad(load: MachineLoad): string {
|
|
|
80
80
|
|
|
81
81
|
function authoritativeSurfaceToolNames(surface: EvalPromptToolSurface): string[] {
|
|
82
82
|
const cfg = getUserConfig();
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
// ⛔ 안전 관문(노출된 변이 툴)은 «provider 해석보다 먼저» 닫혀야 한다 — 자격이 없는 기계(게이트 Pod)에서
|
|
84
|
+
// provider 해석이 먼저 던지면 관문이 안내 대신 「No LLM provider」로 끝났다(0.2.20 컷 pod-7·pod-22).
|
|
85
|
+
// provider 가 없으면 러너의 마지막 기본 모델로 서피스를 재서 관문을 그대로 판정한다(런은 어차피 못 돈다).
|
|
86
|
+
let providerDefaultModel: string | undefined;
|
|
87
|
+
try {
|
|
88
|
+
providerDefaultModel = resolveDefaultProvider().defaultModel;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (!(error instanceof NoLlmProviderAvailableError)) throw error;
|
|
91
|
+
}
|
|
92
|
+
const modelFamily = getModelFamily(resolveReproModelId(undefined, providerDefaultModel));
|
|
85
93
|
const { specs } = buildEvalPromptToolSurface(surface, modelFamily, cfg);
|
|
86
94
|
const tools = filterToolsByDeny(specs, cfg.chat.toolDeny) ?? specs;
|
|
87
95
|
return tools.map((tool) => tool.name);
|
|
@@ -20,6 +20,7 @@ import { runPodCommand, parsePodCpu, resolvePodCpu, type RunPodCommandOptions, t
|
|
|
20
20
|
import { POD_BUN_CACHE_HOST_PATH, parseInstallSeconds, podBunCacheVolume } from '../../src/task-orchestrator/surfaces/pod-bun-cache.js';
|
|
21
21
|
import { PodPoolScheduler, parsePodPool, checkPodPool } from '../../src/task-orchestrator/surfaces/pod-pool.js';
|
|
22
22
|
import { POD_INSTALL_SLOTS_DEFAULT, POD_INSTALL_SLOTS_HOST_PATH, installSlotScript } from '../../src/task-orchestrator/surfaces/pod-install-slots.js';
|
|
23
|
+
import { gateDepsInstallScript, parseGateDeps } from '../../src/task-orchestrator/surfaces/pod-gate-deps.js';
|
|
23
24
|
import { gateShardsPath, writeGateShards, type GateShard } from '../../src/release-loop/gate-shards.js';
|
|
24
25
|
import { defaultKubectl } from '../../src/task-orchestrator/surfaces/self-implement-pod.js';
|
|
25
26
|
|
|
@@ -253,7 +254,7 @@ export function shardParts(paths: readonly string[], seconds: (file: string) =>
|
|
|
253
254
|
* leaving `install.log`/`install.rc`, `part-<i>.log`/`.rc`/`.junit.xml`, and `shard.timeout` (the part index) when the
|
|
254
255
|
* deadline cut the shard. A part without `.rc` did not finish. The shell itself always exits 0 (as before).
|
|
255
256
|
*/
|
|
256
|
-
export function gateShardShell(o: { parts: readonly (readonly string[])[]; cdpPatterns: readonly string[]; softSeconds: number; cachePrefix: string; installSlots: number }): string {
|
|
257
|
+
export function gateShardShell(o: { parts: readonly (readonly string[])[]; cdpPatterns: readonly string[]; softSeconds: number; cachePrefix: string; installSlots: number; depsDir?: string }): string {
|
|
257
258
|
const run = o.parts.map((part, index) => {
|
|
258
259
|
const ignores = o.cdpPatterns.filter((pattern) => part.includes(pattern)).flatMap((pattern) => ['--path-ignore-patterns', pattern]);
|
|
259
260
|
return `run_part ${index} ${['bun', 'run', 'test:deterministic', ...ignores, ...part.map(asPath)].map(quote).join(' ')}`;
|
|
@@ -276,9 +277,8 @@ export function gateShardShell(o: { parts: readonly (readonly string[])[]; cdpPa
|
|
|
276
277
|
' echo "$prc" > "$O/part-$i.rc"',
|
|
277
278
|
'}',
|
|
278
279
|
'if cd .. && cd repo; then',
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
...(o.installSlots > 0 ? [' install_slot_release'] : []),
|
|
280
|
+
// GATE-IMAGE-DEPS: link the image's baked node_modules when the lockfiles match; only a miss installs (behind a slot).
|
|
281
|
+
...gateDepsInstallScript({ log: '"$O/install.log"', installSlots: o.installSlots, ...(o.depsDir ? { depsDir: o.depsDir } : {}) }).split('\n').map((line) => ` ${line}`),
|
|
282
282
|
' echo "$irc" > "$O/install.rc"',
|
|
283
283
|
` if [ "$irc" -eq 0 ]; then ${run || 'true'}; fi`,
|
|
284
284
|
'else echo 5 > "$O/install.rc"; fi',
|
|
@@ -800,7 +800,7 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
800
800
|
}
|
|
801
801
|
const installSeconds = parseInstallSeconds(output ?? '');
|
|
802
802
|
// GATE-TIMEOUT-HEAL ③: a cut shard is «reason: timeout» (with the files that still finished), not a bare rc=null.
|
|
803
|
-
if (!reused && !descent) debug.log('release-loop.gate', 'pod-shard', { shard, files: paths, durationMs, rc: rc ?? null, attempt: depth + 1, installSeconds, deadlineSeconds: shardDeadline, parts: parts.length,
|
|
803
|
+
if (!reused && !descent) debug.log('release-loop.gate', 'pod-shard', { shard, files: paths, durationMs, rc: rc ?? null, attempt: depth + 1, installSeconds, gateDeps: parseGateDeps(output ?? ''), deadlineSeconds: shardDeadline, parts: parts.length,
|
|
804
804
|
...(timedOut ? { reason: 'timeout', finishedFiles: finished.length } : {}) });
|
|
805
805
|
if (!reused && !descent) markShard(shard, { ...(installSeconds !== null ? { installSec: installSeconds } : {}), ...(rc !== undefined ? { rc } : {}), ...(timedOut ? { state: 'timeout' as const } : {}) });
|
|
806
806
|
let clean = output?.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
|
|
@@ -1,15 +1,60 @@
|
|
|
1
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
3
3
|
import { debug } from '../../src/debug/log.js';
|
|
4
4
|
|
|
5
5
|
/** Plan weights for a Pod sweep: wall-scaled when the previous cut recorded shard wall times, junit seconds otherwise. */
|
|
6
|
-
export function planDurations(durationSource: string | undefined): { durations: Map<string, number>; wall?: { shards: number; scaledFiles: number } } {
|
|
6
|
+
export function planDurations(durationSource: string | undefined): { durations: Map<string, number>; wall?: { shards: number; scaledFiles: number }; fallback?: string } {
|
|
7
7
|
if (!durationSource) return { durations: new Map() };
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const primary = planDurationsFrom(durationSource);
|
|
9
|
+
if (primary.durations.size) return primary;
|
|
10
|
+
// GATE-PLAN-TIMINGS: the baseline cut left no reports (0.2.20: baseline 0.2.19 was gated from another universe, so
|
|
11
|
+
// all 5,585 files were «unknown», planned 3.9 min, measured 13–20 min). Use the most recent sibling cut instead.
|
|
12
|
+
const fallback = latestSiblingCutDir(durationSource);
|
|
13
|
+
if (!fallback) {
|
|
14
|
+
debug.log('release-loop.gate', 'plan-duration-fallback', { source: durationSource, fallback: null });
|
|
15
|
+
return primary;
|
|
16
|
+
}
|
|
17
|
+
const result = planDurationsFrom(fallback);
|
|
18
|
+
debug.log('release-loop.gate', 'plan-duration-fallback', { source: durationSource, fallback, files: result.durations.size, wall: !!result.wall });
|
|
19
|
+
return result.durations.size ? { ...result, fallback } : primary;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function planDurationsFrom(dir: string): { durations: Map<string, number>; wall?: { shards: number; scaledFiles: number } } {
|
|
23
|
+
const junit = readFileDurations(dir);
|
|
24
|
+
const wall = readFileWallWeights(dir, junit);
|
|
10
25
|
return wall ? { durations: wall.weights, wall: { shards: wall.shards, scaledFiles: wall.scaledFiles } } : { durations: junit };
|
|
11
26
|
}
|
|
12
27
|
|
|
28
|
+
/**
|
|
29
|
+
* For a `<root>/<version>/<a>/<b>` duration source (the gate passes `<ledger>/release/<baseline>/gate-logs/cut`), the
|
|
30
|
+
* sibling `<root>/<other>/<a>/<b>` directory whose newest `*.junit.xml` is the most recent — «the latest gate». The
|
|
31
|
+
* source itself is skipped. Undefined when the path is too shallow or no sibling holds a junit report.
|
|
32
|
+
*/
|
|
33
|
+
export function latestSiblingCutDir(durationSource: string): string | undefined {
|
|
34
|
+
const source = resolve(durationSource);
|
|
35
|
+
const b = basename(source);
|
|
36
|
+
const a = basename(dirname(source));
|
|
37
|
+
const root = dirname(dirname(dirname(source)));
|
|
38
|
+
if (!a || !b || root === dirname(dirname(source))) return undefined;
|
|
39
|
+
let versions: string[];
|
|
40
|
+
try { versions = readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name); }
|
|
41
|
+
catch { return undefined; }
|
|
42
|
+
let best: { dir: string; mtimeMs: number } | undefined;
|
|
43
|
+
for (const version of versions.sort()) {
|
|
44
|
+
const dir = join(root, version, a, b);
|
|
45
|
+
if (dir === source) continue;
|
|
46
|
+
let newest = -1;
|
|
47
|
+
try {
|
|
48
|
+
for (const name of readdirSync(dir)) {
|
|
49
|
+
if (!name.endsWith('.junit.xml')) continue;
|
|
50
|
+
try { newest = Math.max(newest, statSync(join(dir, name)).mtimeMs); } catch { /* vanished mid-scan */ }
|
|
51
|
+
}
|
|
52
|
+
} catch { continue; }
|
|
53
|
+
if (newest >= 0 && (!best || newest > best.mtimeMs)) best = { dir, mtimeMs: newest };
|
|
54
|
+
}
|
|
55
|
+
return best?.dir;
|
|
56
|
+
}
|
|
57
|
+
|
|
13
58
|
/** Observation for GATE-PLAN-WALLTIME, emitted once the shards are planned so `maxPlannedMin` is the heaviest shard. */
|
|
14
59
|
export function logPlanWalltime(wall: { shards: number; scaledFiles: number } | undefined, shards: ReadonlyArray<{ plannedSeconds: number }>): void {
|
|
15
60
|
if (!wall) return;
|
package/scripts/rhythm/daily.ts
CHANGED
|
@@ -587,8 +587,9 @@ export async function main(args: string[] = process.argv.slice(2), deps: DailyDe
|
|
|
587
587
|
for (const arg of args) if (!['--dry-run', '--no-news', '--json'].includes(arg)) throw new Error(`알 수 없는 옵션: ${arg}`);
|
|
588
588
|
const result = await runDaily({ dryRun: args.includes('--dry-run'), noNews: args.includes('--no-news'), stage }, deps);
|
|
589
589
|
(deps.print ?? console.log)(args.includes('--json') ? JSON.stringify(result) : `${result.markdown}\n파일: ${result.file} · ${result.deliveryLine}`);
|
|
590
|
-
//
|
|
590
|
+
// 그래프 deliver 는 미발송도 출력·tick 에 기록한 뒤 실패로 종결한다.
|
|
591
591
|
if ((stage === 'compose' || !stage) && result.vaultFatal) throw new Error(`볼트 사본 실패 · ${result.vaultError}`);
|
|
592
|
+
if (stage === 'deliver' && result.deliveryState === 'send-disabled') throw new Error('발송 실패 · 발송 비활성');
|
|
592
593
|
if (stage === 'deliver' && result.sendError) throw new Error(`발송 실패 · ${result.sendError}`);
|
|
593
594
|
return result;
|
|
594
595
|
}
|