elanous 0.2.13 → 0.2.15
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/LZcstaO9_NXypPFmujolv/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7334.a6679d9168f37aa8.js → 1268.0840ff91e083fcbd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-33ffcc49ab45123b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9656-c1540088f5859c80.js → 1844-9ec4b1d12f6e80eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{390.c373e31b3b9d0c41.js → 1948.15f356b15a625597.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4685-c3c1c625b71accd1.js → 4614-21403aac730d4586.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8039-df92e08fede5de8f.js → 4795-f372490b178583fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1452.93700483b9d4fc61.js → 6110.1297d4093fdfbb0d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6158.9c0449a9a8d0064b.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6877-7c6208705c284124.js +1 -0
- package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1829-b453a1b22d3999bb.js → 7327-2d69fb321ba73389.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8827-e2f5b09a8d37e83b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +25 -0
- package/apps/pwa/out/_next/static/chunks/{8421-1c4acfb1395a0edf.js → 8949-ecb4128a0858b911.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9103-7a3ae7f60af3b99f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3869-3cd46526879f454c.js → 9247-29d889b809288e65.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{79f8be9e-957d68913b590b08.js → a9f2b54d-7865aba0f4d2ee49.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-0e2c57fe6add4b2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e05a77df7e005b04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-f544338193a9a762.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5491c115b1f9a923.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b8c49f6b4fa2df91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-96398e364fbd4548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-976813c91d7394ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-28b9448091776c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1d4901eb7c2d8822.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-72d3e7ff35a8c954.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-60c7a8e1a4fe62ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-2a52b316cb143d9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c3ce483c8d5db370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-13c7b53e0c2519a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-96f074f6538e8a2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e97be5334d83a9f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-65e484302921a932.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-34d08facaf08f556.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-955ec2da3be4c560.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-9f88fbc15d9058d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-c1343f9499d86f3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-8739a2e0ae793130.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-c9fc5706b8abaa11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-d23b12bb92242558.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8d47f45a0dc044ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c7fea475488201a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e2ee2896811e98d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-83b19dae8619de05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-5efbf81124c474ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f1a1fc0a82738c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-da6c08aae0f92768.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-06ee266953d9c879.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-153c2b3bcc89e8de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-87a11e6a05f15199.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-7d4182964407c09c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-0d6d23b40263a7ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-7e8c39241f8eb6d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-008c1a96618a4887.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-63d14a4d8fe1e1c1.js → page-f5597e894c02cd33.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-0337fdf7fb5e37b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-73735b64bfe1ae67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8fcec4c9ea2e7f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f7e631e9b4daf66e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-4881b8f9f63694b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-9817c7f9007466cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-97f9f43172a3a90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5cd7e3a9-404fd6b8d0ecd44c.js → f6231284-45726550aba08fca.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f48170cc-d05d28bf87a43bf4.js → f6b7c9ba.64a895b8b2fedbdc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-539cde99554be20f.js +1 -0
- package/apps/pwa/out/_next/static/css/1f7c958c41ffa3b9.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -0
- package/apps/pwa/out/ceo/index.txt +33 -0
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -0
- package/apps/pwa/out/loops/index.txt +30 -0
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/heal/heal-loop.yaml +1 -1
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/orchestrator/orchestrator.yaml +59 -0
- package/graphs/orchestrator/recipes.yaml +18 -0
- package/graphs/release/recipes.yaml +6 -0
- package/graphs/release/release-loop.yaml +6 -1
- package/graphs/rhythm/daily.yaml +38 -0
- package/graphs/rhythm/recipes.yaml +18 -0
- package/graphs/rhythm/weekly.yaml +39 -0
- package/graphs/video/recipes.yaml +3 -0
- package/graphs/video/youtube-summary.yaml +17 -0
- package/package.json +1 -1
- package/scripts/audit-test-state-writes.ts +72 -17
- package/scripts/brand/check.ts +188 -0
- package/scripts/ci-typecheck-changed.ts +50 -18
- package/scripts/coord-post.sh +11 -1
- package/scripts/docs/generate-graph-anatomy.ts +315 -0
- package/scripts/docs-cli-check.ts +23 -6
- package/scripts/expose-rubric-check.ts +118 -0
- package/scripts/expose-rubric-suggest.ts +169 -0
- package/scripts/heal/run-role.ts +14 -0
- package/scripts/hq/standby-verify.ts +11 -7
- package/scripts/lecture-note/node.ts +31 -11
- package/scripts/lessons/handbook-page.ts +112 -0
- package/scripts/marketing/generate-ax-brief.ts +140 -0
- package/scripts/marketing/generate-feature-map.ts +118 -0
- package/scripts/release-loop/checklist-gate-node.ts +53 -14
- package/scripts/release-loop/gate-node.ts +89 -14
- package/scripts/release-loop/publish-node.ts +14 -1
- package/scripts/release-loop/unattended-release.ts +23 -1
- package/scripts/release-loop/vault-note-node.ts +428 -0
- package/scripts/release-story/draft.ts +220 -0
- package/scripts/rhythm/daily.ts +570 -0
- package/scripts/rhythm/weekly.ts +315 -0
- package/scripts/skills/public-check.ts +169 -0
- package/scripts/smart-merge/resync-shadow.ts +147 -0
- package/scripts/test-deterministic.ts +4 -8
- package/scripts/test-diet/effectiveness.ts +195 -0
- package/scripts/test-diet/lib.ts +16 -8
- package/scripts/test-diet/node.ts +77 -9
- package/scripts/ux/demo-rehearsal.ts +2 -2
- package/scripts/ux/lib/rehearsal-verdict.ts +1 -0
- package/scripts/video/youtube-summary.ts +133 -0
- package/skills/diagram-master/SKILL.md +42 -49
- package/skills/diagram-master/references/pyproject.toml +4 -1
- package/skills/diagram-master/references/routing-guide.md +4 -2
- package/skills/grill-me/SKILL.md +1 -0
- package/skills/youtube-master/SKILL.md +13 -13
- package/skills/youtube-master/package-lock.json +0 -545
- package/skills/youtube-master/package.json +2 -5
- package/skills/youtube-master/scripts/main.ts +2 -2
- package/skills/youtube-master/scripts/transcribe-local.ts +1 -1
- package/skills/youtube-master/src/util.ts +30 -7
- package/src/agent-env/profile.ts +161 -0
- package/src/agent-mission/driver.ts +3 -3
- package/src/agent-substrate/pr-reviewer.ts +2 -0
- package/src/ask-user-question/pending-questions.ts +5 -0
- package/src/auth/github-app-token.ts +112 -13
- package/src/autopilot/build/llm-conflict-merge.ts +73 -10
- package/src/autopilot/build/merge-intent.ts +53 -0
- package/src/briefing/brief-items.ts +121 -0
- package/src/chat/index.ts +2 -0
- package/src/claims/claims-ledger.ts +232 -0
- package/src/claims/claims-render.ts +166 -0
- package/src/cli/agent-env-cli.ts +21 -0
- package/src/cli/claims-cli.ts +94 -0
- package/src/cli/decisions-cli.ts +44 -3
- package/src/cli/docs-cli.ts +2 -0
- package/src/cli/doctor-cli.ts +23 -1
- package/src/cli/doctor-node-modules.ts +147 -0
- package/src/cli/flow-cli.ts +11 -0
- package/src/cli/freeze-cli.ts +45 -0
- package/src/cli/intake-cli.ts +46 -17
- package/src/cli/lesson-cli.ts +108 -0
- package/src/cli/logs-cli.ts +104 -2
- package/src/cli/logs-model-input.ts +131 -0
- package/src/cli/pod-cli.ts +2 -0
- package/src/cli/pr-cli.ts +29 -1
- package/src/cli/private-ledger-commands.ts +54 -4
- package/src/cli/pty-drive-verdict.ts +11 -2
- package/src/cli/release-cli.ts +190 -33
- package/src/cli/rfc-status.ts +91 -0
- package/src/cli/seat-requests-cli.ts +52 -0
- package/src/connectors/linear.ts +5 -3
- package/src/context-bus/condense.ts +15 -20
- package/src/context-bus/context-now-public.ts +96 -0
- package/src/context-bus/context-now-surfaces.ts +55 -2
- package/src/context-bus/context-now.ts +6 -3
- package/src/context-bus/coord-events.ts +6 -4
- package/src/context-bus/long-term-memory.ts +92 -11
- package/src/dashboard/index.ts +75 -22
- package/src/dashboard/slash-runtime/chat-persona.ts +66 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +99 -0
- package/src/dashboard/slash-runtime/loops-table.ts +77 -0
- package/src/decisions/decision-cards.ts +33 -7
- package/src/decisions/decision-ledger.ts +40 -1
- package/src/decisions/proact-meter.ts +286 -0
- package/src/decisions/proact1-lite.ts +86 -0
- package/src/decisions/web-push-decision-cards.ts +1 -1
- package/src/discord/sprint21-runtime.ts +16 -0
- package/src/discord-self-message.ts +8 -0
- package/src/discord-slash-wire.ts +31 -2
- package/src/domains/alert-audit.ts +271 -0
- package/src/domains/core-tools.ts +4 -3
- package/src/domains/ops-facts-tool.ts +31 -1
- package/src/domains/outbound-alert.ts +1 -1
- package/src/elanous-config-dir.ts +29 -4
- package/src/execution-loop/launch-gate.ts +29 -14
- package/src/flow/cards.ts +239 -0
- package/src/graph-runner/graph-tick.ts +4 -0
- package/src/graph-runner/runner.ts +30 -5
- package/src/harness/harness-cli-command.ts +259 -38
- package/src/harness/harness-incidents.ts +45 -12
- package/src/harness/harness-pod-dispatch.ts +102 -11
- package/src/harness/harness-queue-child.ts +3 -3
- package/src/harness/harness-queue.ts +583 -65
- package/src/harness/helper-repair.ts +87 -0
- package/src/harness/helper-scan.ts +151 -0
- package/src/harness/launch-stamp.ts +236 -0
- package/src/harness/ledger-write-guard-child.fixture.ts +12 -0
- package/src/harness/ledger-write-guard.ts +35 -0
- package/src/harness/model-input-observation.ts +37 -0
- package/src/harness/pod-memory-policy.ts +15 -0
- package/src/harness/repository-name.ts +55 -0
- package/src/hq/fence-audit.ts +90 -0
- package/src/hq/hq.ts +63 -5
- package/src/hq/lease.ts +4 -4
- package/src/hq/move-plan.ts +126 -0
- package/src/hq/promote.ts +332 -0
- package/src/index.ts +159 -27
- package/src/intake-plane/check.ts +63 -0
- package/src/intake-plane/digest.ts +37 -15
- package/src/intake-plane/front-classifier.ts +6 -0
- package/src/intake-plane/items.ts +3 -2
- package/src/intake-plane/lens.ts +177 -0
- package/src/intake-plane/linear-wish.ts +39 -11
- package/src/intake-plane/route.ts +145 -1
- package/src/intake-plane/wish-benchmark-ledger.ts +129 -0
- package/src/intake-plane/wish-card.ts +53 -2
- package/src/intake-plane/wish-folder.ts +5 -2
- package/src/intake-plane/wish-reply.ts +72 -0
- package/src/launch-head/seat-goal-queue-lock.fixture.ts +15 -0
- package/src/launch-head/seat-goal-queue.ts +198 -0
- package/src/lessons/lesson-import.ts +106 -0
- package/src/lessons/lesson-ledger.ts +206 -0
- package/src/loops/activity.ts +203 -0
- package/src/loops/budget.ts +63 -0
- package/src/loops/checker.ts +5 -3
- package/src/loops/contract/examples/orchestrator.loop.yaml +1 -1
- package/src/loops/loop-cli.ts +36 -4
- package/src/loops/neighbors.ts +40 -0
- package/src/loops/observe.ts +10 -0
- package/src/loops/orchestrator/author-depth.ts +220 -0
- package/src/loops/orchestrator/author-input-check.ts +82 -0
- package/src/loops/orchestrator/author-ledger.ts +232 -0
- package/src/loops/orchestrator/finish-rate.ts +175 -0
- package/src/loops/orchestrator/overlap.ts +51 -12
- package/src/loops/orchestrator/resync-shadow.ts +227 -0
- package/src/loops/orchestrator/seat-share.ts +56 -0
- package/src/loops/orchestrator/tick.ts +309 -0
- package/src/loops/orchestrator/traffic.ts +134 -13
- package/src/loops/registry.ts +535 -9
- package/src/loops/status-rows.ts +118 -0
- package/src/loops/verdict.ts +17 -5
- package/src/maturity/bot-slash-catalog.ts +66 -0
- package/src/maturity/feature-maturity.ts +9 -5
- package/src/maturity/tui-slash-availability.ts +31 -0
- package/src/mss/logging/log-store.ts +35 -4
- package/src/nexus/api/dashboard.ts +6 -1
- package/src/nexus/api/http-server.ts +33 -3
- package/src/nexus/api/loop-edges.ts +173 -0
- package/src/nexus/api/merge-approvals-gate.ts +1 -1
- package/src/nexus/api/schedules-read.ts +18 -1
- package/src/nexus/api/seat-requests.ts +79 -56
- package/src/nexus/api/task-cards-api.ts +44 -5
- package/src/nexus/api/workflows.ts +2 -1
- package/src/prompt-enhance/enhance.ts +6 -1
- package/src/release-loop/auto-start.ts +51 -0
- package/src/release-loop/checklist.ts +22 -4
- package/src/release-loop/feature-store.ts +71 -32
- package/src/release-loop/landing-freeze.ts +121 -0
- package/src/release-loop/merged-pr-checklist.ts +125 -0
- package/src/release-loop/placement.ts +302 -0
- package/src/release-loop/release-schedule.ts +3 -1
- package/src/seat-dispatch/ceo-commands.ts +2 -2
- package/src/seat-dispatch/seat-ask.ts +16 -3
- package/src/seat-dispatch/seat-questions.ts +58 -0
- package/src/seat-dispatch/seat-request-eligibility.ts +19 -0
- package/src/seat-dispatch/seat-request-ledger.ts +133 -0
- package/src/seat-loop/seat-loop.ts +531 -40
- package/src/self-dev/dev-pipeline.ts +14 -6
- package/src/self-dev/draft-sweep.ts +162 -6
- package/src/self-dev/draft-triage-rules.ts +25 -8
- package/src/self-dev/orchestrate.ts +15 -1
- package/src/self-dev/review-provider-fallback.ts +6 -1
- package/src/self-dev/run-store.ts +73 -1
- package/src/self-dev/run-supervisor.ts +57 -2
- package/src/self-dev/self-orchestrate-runtime.ts +5 -1
- package/src/self-implement/budget-gate.ts +29 -0
- package/src/self-implement/expose-gate.ts +47 -0
- package/src/self-implement/frozen-merges.ts +295 -0
- package/src/self-implement/gate-cli.ts +10 -4
- package/src/self-implement/gate-scope.ts +46 -9
- package/src/self-implement/goal-archive.ts +222 -0
- package/src/self-implement/goal-author.ts +43 -5
- package/src/self-implement/goal-clarification-escalation.ts +5 -0
- package/src/self-implement/goal-lookup.ts +147 -0
- package/src/self-implement/heal-intake.ts +197 -0
- package/src/self-implement/host-regate.ts +32 -2
- package/src/self-implement/l8-merge-queue.ts +132 -0
- package/src/self-implement/orchestrator.ts +299 -48
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/revert-guard.ts +97 -0
- package/src/self-implement/run-ledger.ts +3 -1
- package/src/self-implement/run-status-mapping.ts +2 -0
- package/src/self-implement/seams.ts +29 -9
- package/src/self-implement/self-implement-cli.ts +1 -0
- package/src/self-implement/speed-claims.ts +338 -0
- package/src/session/index.ts +2 -0
- package/src/steward/triage.ts +74 -3
- package/src/steward/working-backwards.ts +4 -1
- package/src/task-cards/card-cli.ts +10 -2
- package/src/task-cards/card-store.ts +10 -6
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +63 -48
- package/src/task-orchestrator/surfaces/pod-command-job.ts +84 -9
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +5 -2
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +46 -6
- package/src/task-orchestrator/surfaces/pod-pool.ts +60 -8
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +224 -49
- package/src/task-orchestrator/surfaces/self-implement.ts +5 -1
- package/src/telegram-commands.ts +27 -3
- package/src/telegram-loops-command.ts +44 -0
- package/src/telegram.ts +25 -4
- package/src/user-config.ts +146 -18
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/nodes/bash.ts +9 -1
- package/src/workflow-runtime/storage.ts +31 -13
- package/apps/pwa/out/_next/static/D51l8jUBplJrIpWvENsDK/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1394-931c9827067b2276.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992-fe5c06d6b31f8b25.js +0 -25
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5250-c78ca295585bbf95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6511-ff8360be3d65aaa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6588-ba380869b67c4fa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7758-85c2b53f731da024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8605-9da4678f8a310d18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9269.d2a4795bc6812717.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9906-e7b8b5310a169dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-e5b4e1b256f41076.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e49b9b76c565a0b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b4f032c893b21cc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f14987d5850a31e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b433308aad13ceb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-4c1dbb21861beab2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c85b816e3b269dbb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f6bc66b919b2ea7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-60603c1e056c9b25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a0ea8f5a2341ee6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-45c5bf04b4a605e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-36c6c4183353ac9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-cb2eb0fd809980da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-31012264da8a341f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-50309aeb0bdd554a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-bc00e964e855f4df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-0696ee3fac9fe56c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66c27608f651b866.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6ddd2109b7fc3a80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-4e50b7298c1f69a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7a2bf830038a2264.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1f327f18694fabca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-e5cef2fe6e4028df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cf596128d2b420ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-f672536f14f0969f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-b52365662232db89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-e7a6c80f288b1948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-29a709616df9b050.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fee842d7c2151129.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-78b40a344ed22f24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-75d199f448171014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a011dd5b0bff29c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-d92e32d51ab5157e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-5f21aed6932ef375.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-1e1a53946804debf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-a1833cd43d832601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-2a511d320f762e06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1c3e03f88dac1e21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c4d5289c2ea97a89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b91f8952deaeaf27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-71b43a2588489987.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2b256feed331546f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-505bb96d69a8622c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +0 -1
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +0 -1
- /package/apps/pwa/out/_next/static/{D51l8jUBplJrIpWvENsDK → LZcstaO9_NXypPFmujolv}/_ssgManifest.js +0 -0
|
@@ -2,14 +2,16 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import { dlopen, FFIType } from 'bun:ffi';
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
|
-
import { constants as osConstants } from 'node:os';
|
|
6
|
-
import { resolve, sep } from 'node:path';
|
|
5
|
+
import { constants as osConstants, hostname } from 'node:os';
|
|
6
|
+
import { basename, dirname, resolve, sep } from 'node:path';
|
|
7
7
|
import { findGitDir } from '../git-fs/locate.js';
|
|
8
8
|
import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
|
|
9
9
|
import { loadSelfDevRun } from '../self-dev/run-store.js';
|
|
10
10
|
import { normalizeRunId } from './harness-space.js';
|
|
11
|
-
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
12
|
-
import {
|
|
11
|
+
import { effectiveInstanceRoot, prodInstanceRoot } from '../instance/resolve.js';
|
|
12
|
+
import { lookupGoal, type GoalLookupOptions, type GoalLookupResult } from '../self-implement/goal-lookup.js';
|
|
13
|
+
import { archiveGoals, type GoalArchiveOptions } from '../self-implement/goal-archive.js';
|
|
14
|
+
import { detectBursts, formatIncidentBurstWarning, incidentLastLines, readRunExits, recentBurst, recordRunExit } from './harness-incidents.js';
|
|
13
15
|
import { Command, Option } from 'commander';
|
|
14
16
|
import { runGitCommand } from '../git-fs/runner.js';
|
|
15
17
|
import { GOAL_TYPES, lintGoalFile, parseGoalId, parseGoalType, tracedPathReferences, type GoalType } from '../self-implement/goal-author.js';
|
|
@@ -19,7 +21,7 @@ import { resolveChildLlmEffort, resolveImplementationChildModel } from '../self-
|
|
|
19
21
|
import { resolveHarnessTarget } from '../self-implement/harness-target-options.js';
|
|
20
22
|
import { queryRunningRuns } from '../self-implement/running-runs.js';
|
|
21
23
|
import { DevPipelineError } from '../self-dev/dev-pipeline.js';
|
|
22
|
-
import { runDraftSweep, type DraftSweepAdapters, type DraftSweepResult, type SweepDraft, type SweepMergedPr } from '../self-dev/draft-sweep.js';
|
|
24
|
+
import { runDraftSweep, sweepFailureReason, type DraftSweepAdapters, type DraftSweepResult, type SweepDraft, type SweepMergedPr, type SweepReviewGate } from '../self-dev/draft-sweep.js';
|
|
23
25
|
import { debug } from '../debug/log.js';
|
|
24
26
|
import { dispatchTask, type DispatchTaskInput, type DispatchTaskDeps } from '../execution-loop/dispatch-task.js';
|
|
25
27
|
import { launchRequestId, preLaunchGate, type PreLaunchGateDeps } from '../execution-loop/launch-gate.js';
|
|
@@ -28,8 +30,10 @@ import { CODEX_PROVIDER, GROK_PROVIDER, decideBudget, decideLaunchBudget, readBu
|
|
|
28
30
|
import { DEFAULT_FALLBACK_CHAIN } from '../oauth/fallback-chain.js';
|
|
29
31
|
import { installDeliverableVerifyCliCommand, type InstallDeliverableVerifyCliDeps } from './deliverable-verify-cli.js';
|
|
30
32
|
import { getUserConfig } from '../user-config.js';
|
|
33
|
+
import { resolveRepositoryName } from './repository-name.js';
|
|
31
34
|
import { installHarnessCliSinkHook } from './harness-cli-sink.js';
|
|
32
|
-
import { addHarnessQueue, listHarnessQueue, reconcileHarnessQueue, removeHarnessQueue, tickHarnessQueue, type HarnessQueueDeps } from './harness-queue.js';
|
|
35
|
+
import { addHarnessQueue, listHarnessQueue, queueSeatForCwd, reconcileHarnessQueue, removeHarnessQueue, tickHarnessQueue, type HarnessQueueDeps, type QueueSeat } from './harness-queue.js';
|
|
36
|
+
import { parseDoorSince, queryLaunchDoors, renderLaunchDoors, type DoorTable } from './launch-stamp.js';
|
|
33
37
|
import { resolveHarnessSubstrate, type ResolvedHarnessSubstrate } from './harness-substrate-default.js';
|
|
34
38
|
import { runHarnessPlanRfc } from './harness-plan-rfc.js';
|
|
35
39
|
import { classifyGarbage, isGarbageProcessTarget, type GarbageProcess } from './process-garbage.js';
|
|
@@ -92,6 +96,7 @@ export class HarnessCliInputError extends Error {
|
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
export interface HarnessAskSayOptions {
|
|
99
|
+
seat?: QueueSeat;
|
|
95
100
|
json?: boolean;
|
|
96
101
|
base?: string;
|
|
97
102
|
target?: string;
|
|
@@ -253,6 +258,7 @@ function registerHarnessAskSayOptions(command: Command): Command {
|
|
|
253
258
|
.option('--target <path>', 'self: harness가 작업할 레포 또는 디렉터리(self-mission 전용)')
|
|
254
259
|
.option('--yes', 'git 아닌 프로젝트에 git init 및 첫 커밋을 만들도록 동의')
|
|
255
260
|
.option('--correlation <id>', '요청과 런을 잇는 불투명 correlation 값')
|
|
261
|
+
.addOption(new Option('--seat <seat>', '런 귀속 자리 (OP|TC|MK|UX)').choices(['OP', 'TC', 'MK', 'UX']))
|
|
256
262
|
.addOption(new Option('--goal-type <type>', `골 종류 (${GOAL_TYPES.join('|')})`).choices([...GOAL_TYPES]))
|
|
257
263
|
.option('--force-preflight', '전제 검사 막힘을 명시 요청으로 우회(관측에 남음)')
|
|
258
264
|
.option('--force-gate', '같은 골 실행 중 막힘을 명시 요청으로 우회(관측에 남음; 예산 막힘은 우회 불가)')
|
|
@@ -284,6 +290,7 @@ function registerHarnessMissionOptions(command: Command): Command {
|
|
|
284
290
|
function normalizeHarnessCommonOptions(opts: HarnessAskSayOptions): HarnessAskSayOptions {
|
|
285
291
|
return {
|
|
286
292
|
...(opts.json ? { json: true } : {}),
|
|
293
|
+
...(opts.seat !== undefined ? { seat: opts.seat } : {}),
|
|
287
294
|
...(opts.base !== undefined ? { base: opts.base } : {}),
|
|
288
295
|
...(opts.target !== undefined ? { target: opts.target } : {}),
|
|
289
296
|
...(opts.yes === true ? { yes: true } : {}),
|
|
@@ -328,7 +335,7 @@ function assertHarnessChildLlmModel(opts: HarnessAskSayChildLlmOptions): void {
|
|
|
328
335
|
}
|
|
329
336
|
|
|
330
337
|
/** Shared post-parse gate: validate child model before any ask/say early return (including `--dry-run`). */
|
|
331
|
-
type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?:
|
|
338
|
+
type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?: 'lite' | 'standard' | 'high'; after?: string; autoMerge?: boolean; base?: string; json?: boolean; target?: string; source?: string; seat?: QueueSeat };
|
|
332
339
|
function resolveLaunchSubstrate(opts: HarnessSubstrateOpts): ResolvedHarnessSubstrate {
|
|
333
340
|
const resolved = resolveHarnessSubstrate({ flag: opts, config: getUserConfig(), env: process.env });
|
|
334
341
|
debug.log('harness.substrate', 'resolved', resolved);
|
|
@@ -338,7 +345,17 @@ function resolveLaunchSubstrate(opts: HarnessSubstrateOpts): ResolvedHarnessSubs
|
|
|
338
345
|
return resolved;
|
|
339
346
|
}
|
|
340
347
|
type PodExit = { status: number | null; signal?: string | null };
|
|
341
|
-
type PodExitReason = 'signal' | 'human-stop' | 'supervisor' | 'no-launch' | 'unknown'
|
|
348
|
+
type PodExitReason = 'signal' | 'human-stop' | 'supervisor' | 'no-launch' | 'unknown'
|
|
349
|
+
| 'pod-error' | 'launch-gate-blocked' | 'ENOBUFS' | 'OOMKilled';
|
|
350
|
+
|
|
351
|
+
function unknownPodExitTailReason(output: string): PodExitReason | undefined {
|
|
352
|
+
const tail = output.slice(-16_000);
|
|
353
|
+
if (/\bOOMKilled\b/i.test(tail)) return 'OOMKilled';
|
|
354
|
+
if (/\bENOBUFS\b/i.test(tail)) return 'ENOBUFS';
|
|
355
|
+
if (/launch gate[^\r\n]*blocked|blocked[^\r\n]*launch gate/i.test(tail)) return 'launch-gate-blocked';
|
|
356
|
+
if (/\bpod-error\b/i.test(tail)) return 'pod-error';
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
342
359
|
/** GitHub lists at most this many files for one pull request; a list that reaches it is not provably complete. */
|
|
343
360
|
export const GITHUB_PR_FILES_LIST_CAP = 3000;
|
|
344
361
|
const STOPPING_SUPERVISOR_VERDICTS = new Set(['UNCONVERGEABLE', 'CONTRACT-CONFLICT']);
|
|
@@ -441,34 +458,47 @@ export function classifyHarnessPodExit(
|
|
|
441
458
|
try { applied = (deps.hasJobApplied ?? hasHarnessPodJobApplied)(runId, output); } catch { /* unknown */ }
|
|
442
459
|
const noLaunch = ledgerReadable && !ledger?.some((entry) => LAUNCH_EVIDENCE_EVENTS.has(entry.event))
|
|
443
460
|
&& applied === false && !pr;
|
|
444
|
-
reason = noLaunch ? 'no-launch' : 'unknown';
|
|
461
|
+
reason = noLaunch ? 'no-launch' : unknownPodExitTailReason(output) ?? 'unknown';
|
|
445
462
|
line = noLaunch
|
|
446
463
|
? 'Pod 실행에 닿지 못했다 — 풀·컨텍스트·SSH 연결을 확인하거나 `--substrate local` 로 명시하라'
|
|
447
|
-
: 'Pod 실행 여부 또는 종료 이유를 확인하지 못했다'
|
|
464
|
+
: reason === 'unknown' ? 'Pod 실행 여부 또는 종료 이유를 확인하지 못했다'
|
|
465
|
+
: `Pod 종료 출력에서 확인한 원인: ${reason}`;
|
|
448
466
|
}
|
|
449
467
|
try { debug.log('harness.pod', 'exit-classified', { runId, reason, status: exit.status, signal: signal ?? null }); } catch { /* observation is fail-soft */ }
|
|
450
468
|
return { reason, lines: [line, ...(pr ? [`PR 이 남아 있다: ${pr}`] : [])] };
|
|
451
469
|
}
|
|
452
470
|
|
|
453
471
|
/** The classified status is the same exit handed to the launcher; ledger failure is never an exit failure. */
|
|
454
|
-
export function recordClassifiedHarnessPodExit(runId: string | undefined, reason: string, status: number
|
|
472
|
+
export function recordClassifiedHarnessPodExit(runId: string | undefined, reason: string, status: number,
|
|
473
|
+
context: { entrance?: string; seat?: string; output?: string } = {}): void {
|
|
455
474
|
if (!runId) return;
|
|
456
475
|
try {
|
|
457
476
|
const signal = status > 128
|
|
458
477
|
? Object.entries(osConstants.signals).find(([, number]) => number === status - 128)?.[0] ?? null : null;
|
|
459
|
-
|
|
478
|
+
const cwd = process.cwd();
|
|
479
|
+
const seat = context.seat ?? process.env.ELANOUS_HARNESS_SEAT;
|
|
480
|
+
recordRunExit({ runId, reason, status, signal, at: new Date().toISOString(),
|
|
481
|
+
...(context.entrance ? { entrance: context.entrance } : {}),
|
|
482
|
+
...(['OP', 'TC', 'MK', 'UX'].includes(seat ?? '') ? { seat } : {}),
|
|
483
|
+
cwd: `${basename(dirname(cwd))}/${basename(cwd)}`, hostname: hostname().split('.')[0]!, pid: process.pid,
|
|
484
|
+
...(context.output ? { lastLines: incidentLastLines(context.output) } : {}),
|
|
485
|
+
}, effectiveInstanceRoot());
|
|
460
486
|
} catch { /* incident writes cannot change Pod output or exit */ }
|
|
461
487
|
}
|
|
462
488
|
|
|
463
489
|
/** Every Pod launch entrance (harness ask/say · dev ask --substrate pod) warns once after a recent burst; it never blocks the launch. */
|
|
464
490
|
export function warnRecentIncidentBurst(
|
|
465
491
|
root: string = effectiveInstanceRoot(), now: Date = new Date(), write: (line: string) => void = (line) => console.error(line),
|
|
492
|
+
context: { seat?: string; entrance?: string } = {},
|
|
466
493
|
): boolean {
|
|
467
494
|
try {
|
|
468
|
-
const
|
|
495
|
+
const seat = context.seat ?? process.env.ELANOUS_HARNESS_SEAT;
|
|
496
|
+
const burst = recentBurst(root, now, { entrance: context.entrance,
|
|
497
|
+
...(['OP', 'TC', 'MK', 'UX'].includes(seat ?? '') ? { seat } : {}) });
|
|
469
498
|
if (!burst) return false;
|
|
470
499
|
write(formatIncidentBurstWarning(burst));
|
|
471
|
-
try { debug.log('harness.incident', 'burst', { reason: burst.reason, count: burst.count
|
|
500
|
+
try { debug.log('harness.incident', 'burst', { reason: burst.reason, count: burst.count,
|
|
501
|
+
...(burst.seat ? { seat: burst.seat } : {}), ...(burst.entrance ? { entrance: burst.entrance } : {}) }); } catch { /* observation is fail-soft */ }
|
|
472
502
|
return true;
|
|
473
503
|
} catch { return false; /* incident reads cannot block a launch */ }
|
|
474
504
|
}
|
|
@@ -524,9 +554,23 @@ function hasHarnessPodJobApplied(runId: string | undefined, output: string): boo
|
|
|
524
554
|
} finally { store.close(); }
|
|
525
555
|
}
|
|
526
556
|
|
|
557
|
+
/** 10-05 PODPROVIDER — say which child provider a local run will use (an unnamed choice follows config). */
|
|
558
|
+
function announceLocalChildProvider(opts: unknown): void {
|
|
559
|
+
const child = opts as HarnessAskSayChildLlmOptions;
|
|
560
|
+
if (!child.childLlmProvider?.trim()) return;
|
|
561
|
+
console.error(`child provider 요청 = ${child.childLlmProvider.trim()}${child.childLlmModel?.trim() ? `/${child.childLlmModel.trim()}` : ''} (local)`);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/** `harness.authorOnPod` — 명시 true 만 켠다. 읽기 실패는 끔(호스트 저작)으로 둔다. */
|
|
565
|
+
function harnessAuthorOnPod(): boolean {
|
|
566
|
+
try { return getUserConfig().harness?.authorOnPod === true; }
|
|
567
|
+
catch { return false; }
|
|
568
|
+
}
|
|
569
|
+
|
|
527
570
|
/** ⭐ 런 계약의 실행 칸 = pod — 호스트는 그래프를 안 돌리고 Pod 로 보낸다(harness-pod-dispatch.ts). */
|
|
528
571
|
async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-say', input: string, pool: string,
|
|
529
|
-
recordDispatch: (input: DispatchTaskInput, deps?: DispatchTaskDeps) => ReturnType<typeof dispatchTask> = dispatchTask
|
|
572
|
+
recordDispatch: (input: DispatchTaskInput, deps?: DispatchTaskDeps) => ReturnType<typeof dispatchTask> = dispatchTask,
|
|
573
|
+
authorOnPod = false): Promise<void> {
|
|
530
574
|
const o = opts as HarnessSubstrateOpts;
|
|
531
575
|
if (o.target !== undefined) {
|
|
532
576
|
debug.log('harness.pod', 'target-refused', { target: o.target });
|
|
@@ -540,7 +584,8 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
540
584
|
process.exitCode = 2;
|
|
541
585
|
return;
|
|
542
586
|
}
|
|
543
|
-
warnRecentIncidentBurst()
|
|
587
|
+
warnRecentIncidentBurst(effectiveInstanceRoot(), new Date(), (line) => console.error(line),
|
|
588
|
+
{ entrance, seat: o.seat });
|
|
544
589
|
let dispatchRecorded = false;
|
|
545
590
|
try {
|
|
546
591
|
const goalText = entrance === 'cli-harness-ask' ? readFileSync(input, 'utf8') : input;
|
|
@@ -559,14 +604,21 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
559
604
|
const { dispatchHarnessOnPod } = await import('./harness-pod-dispatch.js');
|
|
560
605
|
let output = '';
|
|
561
606
|
let runId: string | undefined;
|
|
562
|
-
const
|
|
607
|
+
const child = opts as HarnessAskSayChildLlmOptions;
|
|
608
|
+
// 10-05 PODPROVIDER: say which child provider the Pod will use when the launch named one.
|
|
609
|
+
if (child.childLlmProvider?.trim()) console.error(`child provider 요청 = ${child.childLlmProvider.trim()}${child.childLlmModel?.trim() ? `/${child.childLlmModel.trim()}` : ''} (pod · 자격 없으면 발사 전 거부)`);
|
|
610
|
+
const status = await dispatchHarnessOnPod({ entrance, input, podPool: pool, ...(authorOnPod && entrance === 'cli-harness-say' ? { authorOnPod: true } : {}),
|
|
611
|
+
...(child.childLlmProvider?.trim() ? { childLlmProvider: child.childLlmProvider.trim() } : {}),
|
|
612
|
+
...(child.childLlmModel?.trim() ? { childLlmModel: child.childLlmModel.trim() } : {}),
|
|
613
|
+
...(child.childLlmEffort?.trim() ? { childLlmEffort: child.childLlmEffort.trim() } : {}), ...(dispatchRecorded ? { dispatchRecorded: true } : {}), ...(o.podMemory ? { podMemory: o.podMemory } : {}), ...((opts as HarnessAskSayChildLlmOptions).goalType ? { goalType: (opts as HarnessAskSayChildLlmOptions).goalType } : {}), ...(o.after ? { after: o.after } : {}), ...(o.autoMerge === false ? { autoMerge: false } : {}), ...(o.base ? { base: o.base } : {}), ...(o.json ? { json: true } : {}), ...(o.source ? { source: o.source } : {}), ...(o.seat ? { seat: o.seat } : {}) },
|
|
563
614
|
{ onOutput: (text) => {
|
|
564
615
|
runId ??= harnessPodRunId(output + text);
|
|
565
616
|
output = (output + text).slice(-16_000);
|
|
566
617
|
} });
|
|
567
618
|
if (status !== 0) {
|
|
568
619
|
const classified = classifyHarnessPodExit({ status }, output, { ...(runId ? { runId } : {}) });
|
|
569
|
-
recordClassifiedHarnessPodExit(runId ?? harnessPodRunId(output), classified.reason, status
|
|
620
|
+
recordClassifiedHarnessPodExit(runId ?? harnessPodRunId(output), classified.reason, status,
|
|
621
|
+
{ entrance, seat: o.seat, output });
|
|
570
622
|
for (const line of classified.lines) console.error(line);
|
|
571
623
|
process.exitCode = status;
|
|
572
624
|
}
|
|
@@ -634,7 +686,7 @@ async function dispatchHarnessAskSay(
|
|
|
634
686
|
readonly wouldStart: string;
|
|
635
687
|
readonly goalPath?: string;
|
|
636
688
|
},
|
|
637
|
-
dispatch: (resolved: ResolvedHarnessSubstrate) => Promise<void>,
|
|
689
|
+
dispatch: (resolved: ResolvedHarnessSubstrate, stampedOpts: HarnessAskSayChildLlmOptions & HarnessDryRunOpts) => Promise<void>,
|
|
638
690
|
gate: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> } = {},
|
|
639
691
|
): Promise<void> {
|
|
640
692
|
await runInjectedHarnessHandler(async () => {
|
|
@@ -644,6 +696,25 @@ async function dispatchHarnessAskSay(
|
|
|
644
696
|
printHarnessLaunchDryRun(dryRunPreview);
|
|
645
697
|
return;
|
|
646
698
|
}
|
|
699
|
+
// Resolve the launch directory once; descendants and the checkpoint retain the same identity.
|
|
700
|
+
const queued = process.env.ELANOUS_HARNESS_QUEUE_LAUNCH && process.env.ELANOUS_HARNESS_SEAT;
|
|
701
|
+
const queueSeat = queued === 'OP' || queued === 'TC' || queued === 'MK' || queued === 'UX' ? queued : undefined;
|
|
702
|
+
const assigned = opts.seat ?? queueSeat ?? queueSeatForCwd(process.cwd(), getUserConfig().loops?.orchestrator?.seatTrees);
|
|
703
|
+
const inheritedSeat = process.env.ELANOUS_HARNESS_SEAT;
|
|
704
|
+
const podSeat = resolved.substrate === 'pod' && ['OP', 'TC', 'MK', 'UX'].includes(inheritedSeat ?? '')
|
|
705
|
+
? inheritedSeat as QueueSeat : undefined;
|
|
706
|
+
const stampedSeat = resolved.substrate === 'pod' ? opts.seat ?? queueSeat ?? podSeat ?? assigned : assigned;
|
|
707
|
+
const stampedOpts = stampedSeat ? { ...opts, seat: stampedSeat } : opts;
|
|
708
|
+
const launch = async () => {
|
|
709
|
+
const previous = process.env.ELANOUS_HARNESS_SEAT;
|
|
710
|
+
if (stampedSeat) process.env.ELANOUS_HARNESS_SEAT = stampedSeat;
|
|
711
|
+
else delete process.env.ELANOUS_HARNESS_SEAT;
|
|
712
|
+
try { await dispatch(resolved, stampedOpts); }
|
|
713
|
+
finally {
|
|
714
|
+
if (previous === undefined) delete process.env.ELANOUS_HARNESS_SEAT;
|
|
715
|
+
else process.env.ELANOUS_HARNESS_SEAT = previous;
|
|
716
|
+
}
|
|
717
|
+
};
|
|
647
718
|
// Without a GoalId, match the request to a live run's exact verbatim original ask; still check budget.
|
|
648
719
|
let identity = dryRunPreview.input;
|
|
649
720
|
let goalId: string | null = null;
|
|
@@ -658,7 +729,7 @@ async function dispatchHarnessAskSay(
|
|
|
658
729
|
// CLI wiring tests time out on them. Gate tests inject deps or opt in with ELANOUS_LAUNCH_GATE_LIVE=1.
|
|
659
730
|
if (process.env.NODE_ENV === 'test' && Object.keys(gate).length === 0 && process.env.ELANOUS_LAUNCH_GATE_LIVE !== '1') {
|
|
660
731
|
try { debug.log('execution-loop.launch-gate', 'skipped-test-env', { goalId }); } catch { /* observation is fail-soft */ }
|
|
661
|
-
await
|
|
732
|
+
await launch();
|
|
662
733
|
return;
|
|
663
734
|
}
|
|
664
735
|
const budget = await (gate.readBudget ?? (() => readHarnessLaunchBudget(opts)))();
|
|
@@ -673,7 +744,7 @@ async function dispatchHarnessAskSay(
|
|
|
673
744
|
...(decision.budget === 'unknown' ? ['budget unknown'] : decision.budget.action === 'next-provider' ? [decision.budget.reasons.join(' · ') || 'next-provider'] : []),
|
|
674
745
|
];
|
|
675
746
|
if (warnings.length > 0) console.error(`⚠️ launch gate: ${warnings.join(' · ').split(/\r?\n/, 1)[0]}`);
|
|
676
|
-
await
|
|
747
|
+
await launch();
|
|
677
748
|
});
|
|
678
749
|
}
|
|
679
750
|
|
|
@@ -1582,6 +1653,12 @@ export async function runHarnessBudget(opts: { json?: boolean } = {}, io: {
|
|
|
1582
1653
|
|
|
1583
1654
|
const DRAFT_SWEEP_REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
1584
1655
|
|
|
1656
|
+
/** A review body still names a must-fix. «must-fix 0» and «must-fix: 0» are a cleared list, not a remaining one. */
|
|
1657
|
+
function mustFixRemains(text: string): boolean {
|
|
1658
|
+
if (!/(?:^|\n)\s*(?:[-*]\s*)?(?:must-fix|must fix)\b/i.test(text)) return false;
|
|
1659
|
+
return !/(?:^|\n)\s*(?:[-*]\s*)?(?:must-fix|must fix)\s*[:=]?\s*0\b/i.test(text);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1585
1662
|
type GithubPull = {
|
|
1586
1663
|
number: number;
|
|
1587
1664
|
title: string;
|
|
@@ -1606,6 +1683,30 @@ const executeGh: GhExecute = (args) => execFileSync('gh', args, {
|
|
|
1606
1683
|
stdio: ['ignore', 'pipe', 'pipe'], env: process.env,
|
|
1607
1684
|
});
|
|
1608
1685
|
|
|
1686
|
+
/** Merge-time adapter: reuse the sweep's GitHub inventory and worktree liveness without a second triage implementation. */
|
|
1687
|
+
export async function supersedeMergedGoalDrafts(
|
|
1688
|
+
number: number, cwd: string,
|
|
1689
|
+
execute: GhExecute = executeGh, git: DraftSweepGitExecute = runGitCommand,
|
|
1690
|
+
): Promise<void> {
|
|
1691
|
+
const remote = git(cwd, ['config', '--get', 'remote.origin.url']);
|
|
1692
|
+
const repository = remote.status === 0 ? githubRemoteRepository(remote.stdout) : undefined;
|
|
1693
|
+
if (!repository) throw new Error('Merge repository unavailable');
|
|
1694
|
+
// The PR can change between open and merge; never authorize a close using locally reconstructed metadata.
|
|
1695
|
+
const pr = ghJson<GithubPull>(['api', `repos/${repository}/pulls/${number}`], execute);
|
|
1696
|
+
if (!pr || pr.number !== number || pr.state !== 'closed' || !pr.merged_at || !pr.title?.trim()
|
|
1697
|
+
|| !pr.head?.ref?.trim() || !pr.created_at || !Array.isArray(pr.labels)
|
|
1698
|
+
|| !Number.isFinite(Date.parse(pr.created_at)) || !Number.isFinite(Date.parse(pr.merged_at))
|
|
1699
|
+
|| Date.parse(pr.merged_at) < Date.parse(pr.created_at)) {
|
|
1700
|
+
throw new Error('Merged PR metadata unavailable');
|
|
1701
|
+
}
|
|
1702
|
+
const merged: SweepMergedPr & { createdAt: string; mergedAt: string } = {
|
|
1703
|
+
number: pr.number, title: pr.title, body: pr.body ?? undefined, branch: pr.head.ref,
|
|
1704
|
+
createdAt: pr.created_at, mergedAt: pr.merged_at,
|
|
1705
|
+
};
|
|
1706
|
+
const { supersedeDraftsOnMerge } = await import('../self-dev/draft-sweep.js');
|
|
1707
|
+
await supersedeDraftsOnMerge({ repository, merged, adapters: githubDraftSweepAdapters(execute, git, cwd) });
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1609
1710
|
function ghJson<T>(args: string[], execute: GhExecute): T {
|
|
1610
1711
|
return JSON.parse(execute(args)) as T;
|
|
1611
1712
|
}
|
|
@@ -1670,7 +1771,7 @@ function githubRemoteRepository(url: string): string | undefined {
|
|
|
1670
1771
|
return match?.[1];
|
|
1671
1772
|
}
|
|
1672
1773
|
|
|
1673
|
-
export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: DraftSweepGitExecute = runGitCommand): DraftSweepAdapters {
|
|
1774
|
+
export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: DraftSweepGitExecute = runGitCommand, cwd = process.cwd()): DraftSweepAdapters {
|
|
1674
1775
|
const inventory = async (repository: string, state: 'open' | 'closed'): Promise<GithubPull[]> => {
|
|
1675
1776
|
// ⛔ A large repository has tens of thousands of closed PRs (2026-09-28: 21k → «exceeded pagination limit», no sweep at all).
|
|
1676
1777
|
// Merged twins only matter after the oldest open draft was opened, so the closed listing stops at that time.
|
|
@@ -1741,6 +1842,36 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
|
|
|
1741
1842
|
}
|
|
1742
1843
|
return undefined;
|
|
1743
1844
|
};
|
|
1845
|
+
const reviewGateForDraft = (draft: SweepDraft, repository: string): SweepReviewGate | undefined => {
|
|
1846
|
+
const head = ghJson<{ head?: { sha?: string } }>(['api', `repos/${repository}/pulls/${draft.number}`], execute);
|
|
1847
|
+
const sha = head?.head?.sha;
|
|
1848
|
+
if (!sha) return undefined;
|
|
1849
|
+
const comments: string[] = [];
|
|
1850
|
+
for (let page = 1; page <= 100; page++) {
|
|
1851
|
+
const batch = ghJson<Array<{ body?: string }>>(['api', `repos/${repository}/issues/${draft.number}/comments?per_page=100&page=${page}`], execute);
|
|
1852
|
+
if (!Array.isArray(batch) || batch.length > 100) throw new Error('Incomplete review comment inventory');
|
|
1853
|
+
comments.push(...batch.map((comment) => comment.body ?? ''));
|
|
1854
|
+
if (batch.length < 100) break;
|
|
1855
|
+
if (page === 100) throw new Error('Review comment inventory exceeded pagination limit');
|
|
1856
|
+
}
|
|
1857
|
+
const reviews = ghJson<Array<{ state?: string; body?: string }>>(['api', `repos/${repository}/pulls/${draft.number}/reviews?per_page=100`], execute);
|
|
1858
|
+
if (!Array.isArray(reviews) || reviews.length > 100) throw new Error('Incomplete review inventory');
|
|
1859
|
+
const text = [...comments, ...reviews.map((review) => review.body ?? '')].join('\n');
|
|
1860
|
+
const status = ghJson<{ state?: string }>(['api', `repos/${repository}/commits/${sha}/status`], execute);
|
|
1861
|
+
const checkRuns = ghJson<{ check_runs?: Array<{ conclusion?: string | null }> }>(
|
|
1862
|
+
['api', `repos/${repository}/commits/${sha}/check-runs?per_page=100`], execute);
|
|
1863
|
+
if (!checkRuns || !Array.isArray(checkRuns.check_runs)) throw new Error('Incomplete check-run inventory');
|
|
1864
|
+
const conclusions = checkRuns.check_runs.map((run) => run.conclusion ?? null);
|
|
1865
|
+
const gatePass = (status?.state === 'success' || status?.state === undefined)
|
|
1866
|
+
&& conclusions.length > 0 && conclusions.every((conclusion) => conclusion === 'success' || conclusion === 'skipped' || conclusion === 'neutral');
|
|
1867
|
+
const gateFail = status?.state === 'failure' || status?.state === 'error'
|
|
1868
|
+
|| conclusions.some((conclusion) => conclusion === 'failure' || conclusion === 'cancelled' || conclusion === 'timed_out' || conclusion === 'action_required');
|
|
1869
|
+
return {
|
|
1870
|
+
...(reviews.some((review) => review.state === 'APPROVED') || /(?:^|\n)\s*VERDICT:\s*PASS\b/i.test(text) ? { review: 'pass' as const } : {}),
|
|
1871
|
+
...(mustFixRemains(text) ? { mustFix: true } : {}),
|
|
1872
|
+
...(gatePass && !gateFail ? { gate: 'pass' as const } : gateFail ? { gate: 'fail' as const } : {}),
|
|
1873
|
+
};
|
|
1874
|
+
};
|
|
1744
1875
|
const landingCommentsFor = (repository: string, number: number): string[] => {
|
|
1745
1876
|
const comments: string[] = [];
|
|
1746
1877
|
for (let page = 1; page <= 100; page++) {
|
|
@@ -1763,6 +1894,7 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
|
|
|
1763
1894
|
return draftSweepRunStatus(ledgerMatches, running, repository, draft.number);
|
|
1764
1895
|
};
|
|
1765
1896
|
return {
|
|
1897
|
+
getPrFiles: async (repository, number) => filesFor(repository, number),
|
|
1766
1898
|
listDrafts: async (page, perPage, repository): Promise<SweepDraft[]> =>
|
|
1767
1899
|
(await listed(open, repository, 'open')).filter((pr) => pr.draft)
|
|
1768
1900
|
.slice((page - 1) * perPage, page * perPage)
|
|
@@ -1811,7 +1943,6 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
|
|
|
1811
1943
|
} finally { store.close(); }
|
|
1812
1944
|
},
|
|
1813
1945
|
listLiveBranches: async (repository) => {
|
|
1814
|
-
const cwd = process.cwd();
|
|
1815
1946
|
const remote = git(cwd, ['config', '--get', 'remote.origin.url']);
|
|
1816
1947
|
if (remote.status !== 0 || githubRemoteRepository(remote.stdout)?.toLowerCase() !== repository.toLowerCase()) {
|
|
1817
1948
|
return undefined;
|
|
@@ -1829,6 +1960,7 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
|
|
|
1829
1960
|
execute(['pr', 'close', String(number), '--repo', repository, '--comment', comment]);
|
|
1830
1961
|
},
|
|
1831
1962
|
getClaimOwner: async (repository, number) => claimCommentOwner(repository, number, execute),
|
|
1963
|
+
getReviewGate: async (draft, repository) => reviewGateForDraft(draft, repository),
|
|
1832
1964
|
};
|
|
1833
1965
|
}
|
|
1834
1966
|
|
|
@@ -1863,7 +1995,10 @@ function installHarnessDraftSweepCommand(harnessCmd: Command, deps: HarnessDraft
|
|
|
1863
1995
|
.action(async (number: string, opts: { owner?: string; note?: string; release?: boolean; repo?: string }) => {
|
|
1864
1996
|
try {
|
|
1865
1997
|
const execute = deps.execute ?? executeGh;
|
|
1866
|
-
const repository =
|
|
1998
|
+
const repository = resolveRepositoryName({
|
|
1999
|
+
repo: opts.repo ?? deps.repository?.(),
|
|
2000
|
+
executeGh: (args) => execute(args),
|
|
2001
|
+
});
|
|
1867
2002
|
if (!DRAFT_SWEEP_REPOSITORY.test(repository) || repository.includes('..')) throw new HarnessCliInputError(`invalid --repo (expected owner/name): ${repository}`);
|
|
1868
2003
|
if (!/^[1-9]\d*$/.test(number) || !Number.isSafeInteger(Number(number))) throw new HarnessCliInputError(`invalid PR number: ${number}`);
|
|
1869
2004
|
const owner = opts.owner?.trim();
|
|
@@ -1900,26 +2035,86 @@ function installHarnessDraftSweepCommand(harnessCmd: Command, deps: HarnessDraft
|
|
|
1900
2035
|
.action(async (opts: { apply?: boolean; json?: boolean; repo?: string }) => {
|
|
1901
2036
|
try {
|
|
1902
2037
|
const write = deps.write ?? console.log;
|
|
1903
|
-
const
|
|
1904
|
-
|
|
2038
|
+
const execute = deps.execute ?? executeGh;
|
|
2039
|
+
const repository = resolveRepositoryName({
|
|
2040
|
+
repo: opts.repo ?? deps.repository?.(),
|
|
2041
|
+
executeGh: (args) => execute(args),
|
|
2042
|
+
});
|
|
1905
2043
|
if (!DRAFT_SWEEP_REPOSITORY.test(repository) || repository.includes('..')) {
|
|
1906
2044
|
throw new HarnessCliInputError(`invalid --repo (expected owner/name): ${repository}`);
|
|
1907
2045
|
}
|
|
1908
2046
|
const result: DraftSweepResult = await runDraftSweep({ repository, apply: opts.apply === true, adapters: deps.adapters ?? githubDraftSweepAdapters(deps.execute) });
|
|
1909
|
-
|
|
2047
|
+
const reason = result.error ? sweepFailureReason(result.error) : undefined;
|
|
2048
|
+
if (opts.json) write(JSON.stringify(reason ? { ...result, error: reason } : result));
|
|
1910
2049
|
else {
|
|
1911
|
-
write(`draft sweep ${result.repository}: ${result.complete ? 'complete' : `incomplete (${
|
|
1912
|
-
for (const entry of result.entries) write(`#${entry.number} ${entry.action}: ${entry.reason}${entry.statusLabel ? ` → ${entry.statusLabel}` : ''}${entry.error ? ` ERROR: ${entry.error}` : ''}`);
|
|
1913
|
-
if (result.complete)
|
|
2050
|
+
write(`draft sweep ${result.repository}: ${result.complete ? 'complete' : `incomplete (${reason})`} · ${result.apply ? 'apply' : 'dry-run'}`);
|
|
2051
|
+
for (const entry of result.entries) write(`#${entry.number} ${entry.action}: ${entry.reason}${entry.statusLabel ? ` → ${entry.statusLabel}` : ''}${entry.error ? ` ERROR: ${sweepFailureReason(entry.error)}` : ''}`);
|
|
2052
|
+
if (result.complete) {
|
|
2053
|
+
const daily = result.daily
|
|
2054
|
+
? ` · 24h 넘음 ${result.daily.over24h} · 정리 대상 ${result.daily.closable} · 수확 대기 ${result.daily.harvestable} · 막힘 ${result.daily.blocked}`
|
|
2055
|
+
: '';
|
|
2056
|
+
write(`못 본 초안 ${result.unobserved ?? 0} · 이번에 닫음 ${result.closed ?? 0}${result.apply ? '' : '(dry-run)'} · 처리 중 ${result.claimed ?? 0} · 표식 만료 ${result.claimExpired ?? 0}${daily}`);
|
|
2057
|
+
}
|
|
2058
|
+
if (reason) write(reason);
|
|
1914
2059
|
}
|
|
1915
2060
|
if (!result.complete || result.entries.some((entry) => entry.error)) process.exitCode = 1;
|
|
1916
2061
|
} catch (error) {
|
|
1917
2062
|
console.error(humanErrorLine(error));
|
|
2063
|
+
try { debug.log('drafts.cleanup', 'failed', { reason: sweepFailureReason(error) }); } catch { /* observation is fail-soft */ }
|
|
1918
2064
|
process.exitCode = 1;
|
|
1919
2065
|
}
|
|
1920
2066
|
});
|
|
1921
2067
|
}
|
|
1922
2068
|
|
|
2069
|
+
function renderHarnessGoal(result: GoalLookupResult, universe: '운영' | '시험'): string {
|
|
2070
|
+
const matchedRun = result.runState?.results.find((entry) => entry.runId === result.runId);
|
|
2071
|
+
return [
|
|
2072
|
+
`골: ${result.goalBody?.split(/\r?\n/, 1)[0] || '골 문서에 없음'}`,
|
|
2073
|
+
`runId: ${result.runId ?? '원장에 없음'}`,
|
|
2074
|
+
`칸 id: ${result.kanId ?? '기록 없음'}`,
|
|
2075
|
+
`PR: ${result.record?.prNumber != null ? `#${result.record.prNumber}` : '기록 없음'}`,
|
|
2076
|
+
`stage/결과: ${result.record?.stage ?? '기록 없음'} / ${result.record?.outcome ?? '기록 없음'}`,
|
|
2077
|
+
`종결 사유: ${result.runState?.supervisorStopReason ?? matchedRun?.error?.message ?? '기록 없음'}`,
|
|
2078
|
+
`찾은 우주: ${universe}`,
|
|
2079
|
+
`원장: ${result.runState ? '찾음' : '원장에 없음'}`,
|
|
2080
|
+
`골 문서: ${result.goalFile ? '찾음' : '골 문서에 없음'}`,
|
|
2081
|
+
].join('\n');
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
function installHarnessGoalCommand(harnessCmd: Command, options?: GoalLookupOptions, archiveOptions?: GoalArchiveOptions): Command {
|
|
2085
|
+
const goal = harnessCmd.command('goal').usage('<reference> | archive [--before <date>] [--apply]')
|
|
2086
|
+
.description('골 문서와 실행 결과를 조회하거나 보관한다');
|
|
2087
|
+
goal.command('archive')
|
|
2088
|
+
.description('종료된 골 문서를 미리 보거나 상태 루트에 보관한다 — 저장소는 건드리지 않고 지울 목록(filesForPr)만 낸다')
|
|
2089
|
+
.option('--before <date>', '완료 시각이 이 YYYY-MM-DD 이전인 골만')
|
|
2090
|
+
.option('--apply', '상태 루트에 보관 복사·색인 (저장소 삭제·스테이지·커밋 없음 · 지우기는 filesForPr 로 사람이 PR)')
|
|
2091
|
+
.option('--trust-doc-record', '런 원장이 없을 때 문서에 적힌 종료 실행 기록을 신뢰')
|
|
2092
|
+
.action((opts: { before?: string; apply?: boolean; trustDocRecord?: boolean }) => {
|
|
2093
|
+
try {
|
|
2094
|
+
const result = archiveGoals({ ...archiveOptions, before: opts.before, apply: opts.apply, trustDocRecord: opts.trustDocRecord });
|
|
2095
|
+
console.log(JSON.stringify(result));
|
|
2096
|
+
} catch (error) {
|
|
2097
|
+
console.error(humanErrorLine(error));
|
|
2098
|
+
process.exitCode = 1;
|
|
2099
|
+
}
|
|
2100
|
+
});
|
|
2101
|
+
goal.command('show <reference>', { isDefault: true })
|
|
2102
|
+
.description('PR 번호 또는 runId 로 골 문서와 실행 결과를 조회한다 (읽기 전용)')
|
|
2103
|
+
.option('--json', 'GoalLookupResult 그대로 출력')
|
|
2104
|
+
.action((reference: string, opts: { json?: boolean }) => {
|
|
2105
|
+
try {
|
|
2106
|
+
const result = lookupGoal(reference, options);
|
|
2107
|
+
const universe = effectiveInstanceRoot() === prodInstanceRoot() ? '운영' : '시험';
|
|
2108
|
+
console.log(opts.json ? JSON.stringify(result) : renderHarnessGoal(result, universe));
|
|
2109
|
+
if (!result.goalFile || !result.runState) process.exitCode = 1;
|
|
2110
|
+
} catch (error) {
|
|
2111
|
+
console.error(humanErrorLine(error));
|
|
2112
|
+
process.exitCode = 1;
|
|
2113
|
+
}
|
|
2114
|
+
});
|
|
2115
|
+
return goal;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
1923
2118
|
function installHarnessBudgetCommand(harnessCmd: Command): Command {
|
|
1924
2119
|
return harnessCmd
|
|
1925
2120
|
.command('budget')
|
|
@@ -2106,6 +2301,8 @@ export interface HarnessCliCommandDeps {
|
|
|
2106
2301
|
processObservation?: HarnessProcessObservationDeps;
|
|
2107
2302
|
draftSweep?: HarnessDraftSweepDeps;
|
|
2108
2303
|
queue?: HarnessQueueDeps;
|
|
2304
|
+
goalLookup?: GoalLookupOptions;
|
|
2305
|
+
goalArchive?: GoalArchiveOptions;
|
|
2109
2306
|
ask?: HarnessAskHandler;
|
|
2110
2307
|
say?: HarnessSayHandler;
|
|
2111
2308
|
/** Observe-only Pod host dispatch seam. */
|
|
@@ -2124,6 +2321,27 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2124
2321
|
.command('harness')
|
|
2125
2322
|
.description('dev-harness worktree 수명 — 워크트리 생성(worktree add)·조회(worktrees)·정리(clean)·프로세스 관찰(processes)');
|
|
2126
2323
|
installHarnessCliSinkHook(harnessCmd, deps.registerSink, deps.resolveSurface);
|
|
2324
|
+
harnessCmd.command('doors').description('기간 안 런을 입구×대기열 경유 표로 읽는다')
|
|
2325
|
+
.option('--since <window>', '조회 창 (30m · 12h · 1d, 기본 1d)', '1d')
|
|
2326
|
+
.option('--json', '구조화 출력')
|
|
2327
|
+
.action((opts: { since?: string; json?: boolean }) => {
|
|
2328
|
+
const parsed = parseDoorSince(opts.since);
|
|
2329
|
+
if ('error' in parsed) {
|
|
2330
|
+
console.error(`❌ ${parsed.error}`);
|
|
2331
|
+
process.exitCode = 2;
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
let table: DoorTable;
|
|
2335
|
+
try {
|
|
2336
|
+
table = queryLaunchDoors({ sinceMs: parsed.sinceMs });
|
|
2337
|
+
} catch (error) {
|
|
2338
|
+
console.error(`❌ doors: ${error instanceof Error ? error.message : String(error)}`);
|
|
2339
|
+
process.exitCode = 1;
|
|
2340
|
+
return;
|
|
2341
|
+
}
|
|
2342
|
+
if (opts.json) console.log(JSON.stringify(table));
|
|
2343
|
+
else console.log(renderLaunchDoors(table));
|
|
2344
|
+
});
|
|
2127
2345
|
harnessCmd.command('incidents').description('최근 하니스 Pod 종료 사고 원장을 읽는다')
|
|
2128
2346
|
.option('--since <minutes>', '최근 몇 분의 종료를 볼지 (기본 15분)', '15')
|
|
2129
2347
|
.option('--json', '구조화 출력')
|
|
@@ -2146,8 +2364,8 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2146
2364
|
const bursts = detectBursts(rows).filter((burst) => Date.parse(burst.lastAt) >= now - since * 60_000 && Date.parse(burst.lastAt) <= now);
|
|
2147
2365
|
if (opts.json) console.log(JSON.stringify({ rows: selected, bursts }));
|
|
2148
2366
|
else {
|
|
2149
|
-
for (const row of selected) console.log(`${row.at} run ${row.runId} ·
|
|
2150
|
-
for (const burst of bursts) console.log(`${burst.firstAt}–${burst.lastAt} 묶음 ${burst.reason} ×${burst.count} · ${burst.runIds.join(', ')}`);
|
|
2367
|
+
for (const row of selected) console.log(`${row.at} run ${row.runId} · seat=${row.seat ?? '-'} entrance=${row.entrance ?? '-'} reason=${row.reason} · status=${row.status} signal=${row.signal ?? '-'}`);
|
|
2368
|
+
for (const burst of bursts) console.log(`${burst.firstAt}–${burst.lastAt} 묶음 ${burst.reason} ×${burst.count} · seat=${burst.seat ?? '-'} entrance=${burst.entrance ?? '-'} · ${burst.runIds.join(', ')}`);
|
|
2151
2369
|
}
|
|
2152
2370
|
} catch (error) {
|
|
2153
2371
|
console.error(humanErrorLine(error));
|
|
@@ -2157,6 +2375,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2157
2375
|
installDeliverableVerifyCliCommand(harnessCmd, deps.deliverableVerify);
|
|
2158
2376
|
installHarnessProcessObservationCommand(harnessCmd, deps.processObservation);
|
|
2159
2377
|
installHarnessBudgetCommand(harnessCmd);
|
|
2378
|
+
installHarnessGoalCommand(harnessCmd, deps.goalLookup, deps.goalArchive);
|
|
2160
2379
|
installHarnessDraftSweepCommand(harnessCmd, deps.draftSweep);
|
|
2161
2380
|
const queue = harnessCmd.command('queue').description('자리별 영속 발사 대기열');
|
|
2162
2381
|
const queueDeps = deps.queue ?? {};
|
|
@@ -2169,7 +2388,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2169
2388
|
console.log(`${row.id} ${row.seat} ${row.kind} queued`);
|
|
2170
2389
|
}));
|
|
2171
2390
|
queue.command('list').description('대기·발사 원장 조회').action(() => queueAction(async () => {
|
|
2172
|
-
for (const row of listHarnessQueue(queueDeps)) console.log(`${row.id} ${row.seat} ${row.status} ${row.kind} ${row.input}`);
|
|
2391
|
+
for (const row of listHarnessQueue(queueDeps)) console.log(`${row.id} ${row.seat} ${row.status} ${row.kind} ${row.input}${row.waitingReason ? ` · ${row.waitingReason}` : ''}`);
|
|
2173
2392
|
}));
|
|
2174
2393
|
queue.command('remove <id>').description('대기 중 또는 종료 확인된 항목 제거').action((id: string) => queueAction(async () => {
|
|
2175
2394
|
if (!await removeHarnessQueue(id, queueDeps)) throw new Error(`queue item active or not found: ${id}`);
|
|
@@ -2178,7 +2397,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2178
2397
|
queue.command('reconcile <id>').description('불확정 발사를 확인하고 종료 또는 미발사 증거가 있으면 예약 해소').action((id: string) => queueAction(async () => {
|
|
2179
2398
|
console.log(`${id} ${await reconcileHarnessQueue(id, queueDeps)}`);
|
|
2180
2399
|
}));
|
|
2181
|
-
queue.command('tick').description('맨 앞 한
|
|
2400
|
+
queue.command('tick').description('자리별 맨 앞 한 건을 라운드로빈으로 돌며 자리 몫·Pod 풀 여유·마무리 관문을 확인하고 한 건 발사').action(() => queueAction(async () => {
|
|
2182
2401
|
const result = await tickHarnessQueue(queueDeps);
|
|
2183
2402
|
console.log(`${result.outcome}${result.item ? ` ${result.item.id}` : ''}: ${result.reason}`);
|
|
2184
2403
|
}));
|
|
@@ -2197,13 +2416,13 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2197
2416
|
...(opts.goalType !== undefined ? { goalType: opts.goalType } : {}),
|
|
2198
2417
|
...(opts.target !== undefined ? { target: opts.target } : {}),
|
|
2199
2418
|
},
|
|
2200
|
-
(resolved) => {
|
|
2419
|
+
(resolved, stampedOpts) => {
|
|
2201
2420
|
if (resolved.substrate !== 'pod' && (opts as { source?: string }).source !== undefined) {
|
|
2202
2421
|
console.error('`--source` 는 `--substrate pod` 와 함께');
|
|
2203
2422
|
process.exitCode = 2;
|
|
2204
2423
|
return Promise.resolve();
|
|
2205
2424
|
}
|
|
2206
|
-
return resolved.substrate === 'pod' ? onPod(
|
|
2425
|
+
return resolved.substrate === 'pod' ? onPod(stampedOpts, 'cli-harness-ask', goalPath, resolved.pool!, deps.podDispatchTask) : (announceLocalChildProvider(stampedOpts), ask(goalPath, normalizeHarnessAskSayOptions(stampedOpts)));
|
|
2207
2426
|
},
|
|
2208
2427
|
deps.launchGate,
|
|
2209
2428
|
);
|
|
@@ -2222,13 +2441,15 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
2222
2441
|
wouldStart: '골 문서 · 워크트리 · 브랜치 · 자식 · 파이프라인',
|
|
2223
2442
|
...(opts.target !== undefined ? { target: opts.target } : {}),
|
|
2224
2443
|
},
|
|
2225
|
-
(resolved) => {
|
|
2444
|
+
(resolved, stampedOpts) => {
|
|
2226
2445
|
if (resolved.substrate !== 'pod' && (opts as { source?: string }).source !== undefined) {
|
|
2227
2446
|
console.error('`--source` 는 `--substrate pod` 와 함께');
|
|
2228
2447
|
process.exitCode = 2;
|
|
2229
2448
|
return Promise.resolve();
|
|
2230
2449
|
}
|
|
2231
|
-
return resolved.substrate === 'pod'
|
|
2450
|
+
return resolved.substrate === 'pod'
|
|
2451
|
+
? onPod(stampedOpts, 'cli-harness-say', sentence.join(' '), resolved.pool!, deps.podDispatchTask, harnessAuthorOnPod())
|
|
2452
|
+
: (announceLocalChildProvider(stampedOpts), say(sentence, normalizeHarnessAskSayOptions(stampedOpts)));
|
|
2232
2453
|
},
|
|
2233
2454
|
deps.launchGate,
|
|
2234
2455
|
);
|