elanous 0.2.12 → 0.2.14
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/chunks/{7334.a6679d9168f37aa8.js → 1268.0840ff91e083fcbd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-6e7e0377c1db0bdc.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/4562-071d8bac44a01069.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-2df489622a52a33a.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/{9906-482c6619b3fdda20.js → 8060-cc008cc6fedfa818.js} +1 -1
- 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/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-74383f890f075511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-7b2b4f378354869a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-c496bb16da85385f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-1abfe3aec3be6bdc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-1512d91c7491ed62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a627db94ec6904a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-fb260b9283dbf646.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-e6b84ab07d3567d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-61ec1d2e92bdd50a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fed69f9759d248d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-a67e11ba962337b5.js → page-15374909d8f1aebd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-012a742f81218b01.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-fd7e200d4d83fbd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-99effd9d893a43dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-938de57ae0315e46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-d47266766766d227.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-160089123a40dd91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-629e1ede482ec6eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-793fa536b3a6ef37.js → page-2ce5471926761fdd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-27e99b4e54a849d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e995d30f6800b6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-39f89c53038a51d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-32cde713be47cddb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-e7e10cd3386222e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-5a753bb4ec0cc511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-04250f0e2c0d03df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-341480ed8e3c1ea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-e64caff084f7ce21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-db07eaffba0df7e3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8ac8d71c2adf9c8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e1e47d8d940aba3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-86f91034bd5cabe5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-94dc383d3d54db1a.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-b3759cc14da80908.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-ce4d8a1215ce53a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-58043db78ba519ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-357750dfb91bf960.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-e297866051595d81.js → page-274703bc41b71333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-194dce4a83143fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-35bdeae2e2c17147.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-3b7e821dc492bdfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-16bef3da05a900c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-f8da5dc6f3752276.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2f810b18d89ecba6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-134c1bc762aee62c.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/2e33713c444d5b39.css +1 -0
- package/apps/pwa/out/_next/static/x6mjI6vqOkVVu0jFuDkz1/_buildManifest.js +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/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/examples/teams/personas/backend.yaml +4 -0
- package/examples/teams/personas/pm.yaml +4 -0
- package/examples/teams/personas/qa.yaml +4 -0
- package/examples/teams/small-product.yaml +20 -0
- package/graphs/lecture/lecture-note.yaml +28 -0
- package/graphs/lecture/recipes.yaml +17 -0
- package/graphs/orchestrator/orchestrator.yaml +59 -0
- package/graphs/orchestrator/recipes.yaml +18 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -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 +2 -1
- package/scripts/audit-test-state-writes.ts +72 -17
- package/scripts/brand/check.ts +186 -0
- package/scripts/context-hooks/emit.ts +36 -14
- package/scripts/coord-channel-watch.sh +1 -0
- package/scripts/coord-post.sh +11 -1
- package/scripts/discord-seat-probe.ts +144 -0
- package/scripts/docs-cli-check.ts +23 -6
- package/scripts/expose-rubric-check.ts +118 -0
- package/scripts/expose-rubric-suggest.ts +163 -0
- package/scripts/heal/run-role.ts +14 -0
- package/scripts/hq/hq-standby.sh +65 -0
- package/scripts/hq/standby-promote.ts +173 -0
- package/scripts/hq/standby-role.ts +59 -0
- package/scripts/hq/standby-snapshot.ts +226 -0
- package/scripts/hq/standby-verify.ts +223 -0
- package/scripts/lecture-note/node.ts +256 -0
- package/scripts/lessons/handbook-page.ts +85 -0
- package/scripts/release-loop/gate-node.ts +62 -15
- package/scripts/release-loop/ops-upgrade-node.ts +17 -5
- 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 +196 -0
- package/scripts/release-story/draft.ts +172 -0
- package/scripts/rhythm/daily.ts +383 -0
- package/scripts/rhythm/weekly.ts +294 -0
- package/scripts/skills/public-check.ts +169 -0
- package/scripts/test-deterministic.ts +57 -11
- 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/omni-crawl/SKILL.md +16 -16
- package/skills/omni-crawl/package-lock.json +1 -544
- package/skills/omni-crawl/package.json +3 -4
- package/skills/omni-crawl/scripts/main.ts +13 -13
- package/skills/omni-crawl/scripts/monitor.ts +8 -8
- package/skills/omni-crawl/src/apify.ts +13 -2
- package/skills/omni-crawl/src/capture.ts +6 -0
- package/skills/omni-crawl/src/registry.ts +2 -2
- package/skills/omni-crawl/src/stdout-json.ts +4 -0
- package/skills/omni-digest/SKILL.md +10 -11
- package/skills/omni-digest/package-lock.json +0 -545
- package/skills/omni-digest/package.json +2 -5
- package/skills/omni-digest/scripts/main.ts +3 -3
- package/skills/omni-digest/src/delegate.ts +5 -5
- package/skills/omni-digest/src/fetch.ts +2 -2
- package/skills/omni-digest/src/media.ts +25 -11
- package/skills/omni-digest/src/visual.ts +3 -2
- package/skills/omni-market/scripts/main.ts +1 -1
- package/skills/omni-market/scripts/stdout-json.ts +4 -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/identity-env.ts +11 -0
- package/src/agent-mission/driver.ts +15 -10
- package/src/agent-mission/duo.ts +94 -0
- package/src/agent-mission/pty-decision.ts +1 -1
- package/src/autopilot/build/llm-conflict-merge.ts +45 -8
- package/src/autopilot/build/merge-intent.ts +53 -0
- package/src/autopilot/track-agent-shadow.ts +2 -1
- package/src/autopilot/track-agent.ts +4 -1
- package/src/boot/daemon-prompt-request.ts +3 -0
- package/src/boot/daemon-prompt-turn.ts +6 -2
- package/src/boot/daemon-runtime.ts +48 -16
- package/src/chat/index.ts +2 -0
- package/src/claims/claims-ledger.ts +232 -0
- package/src/claims/claims-render.ts +157 -0
- package/src/cli/claims-cli.ts +94 -0
- package/src/cli/decisions-cli.ts +84 -20
- package/src/cli/docs-cli.ts +2 -0
- package/src/cli/flow-cli.ts +11 -0
- package/src/cli/freeze-cli.ts +45 -0
- 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/outputs-cli.ts +92 -0
- package/src/cli/persona-cli.ts +29 -0
- package/src/cli/pod-cli.ts +10 -3
- package/src/cli/pr-cli.ts +44 -2
- package/src/cli/private-ledger-commands.ts +54 -4
- package/src/cli/pty-drive-verdict.ts +11 -2
- package/src/cli/release-cli.ts +248 -45
- package/src/cli/rfc-status.ts +91 -0
- package/src/connectors/linear.ts +5 -3
- package/src/context-bus/condense.ts +189 -0
- package/src/context-bus/context-day.ts +82 -0
- package/src/context-bus/context-now-public.ts +86 -0
- package/src/context-bus/context-now-surfaces.ts +70 -4
- package/src/context-bus/context-now.ts +4 -3
- package/src/context-bus/long-term-memory.ts +201 -24
- package/src/context-bus/nightly-condense.ts +1 -1
- 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 +13 -7
- package/src/decisions/decision-ledger.ts +83 -18
- 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/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-kinds/registry.ts +2 -2
- package/src/graph-runner/graph-approval-card.ts +2 -2
- package/src/graph-runner/graph-grow.ts +64 -11
- package/src/graph-runner/graph-tick.ts +13 -2
- package/src/graph-runner/runner.ts +111 -22
- package/src/harness/harness-cli-command.ts +178 -27
- package/src/harness/harness-incidents.ts +43 -12
- package/src/harness/harness-pod-dispatch.ts +2 -0
- package/src/harness/harness-queue-child.ts +37 -0
- package/src/harness/harness-queue.ts +494 -0
- package/src/harness/helper-scan.ts +139 -0
- package/src/harness/model-input-observation.ts +37 -0
- package/src/hooks/github-shadow.ts +72 -2
- package/src/hooks/receiver.ts +4 -2
- package/src/hq/hq.ts +318 -0
- package/src/hq/lease.ts +210 -0
- package/src/hq/ledger-write-target.ts +41 -0
- package/src/hq/promote.ts +301 -0
- package/src/index.ts +281 -27
- package/src/intake-plane/discord-seat-work.ts +13 -6
- package/src/intake-plane/linear-wish.ts +72 -0
- package/src/intake-plane/persona-answer.ts +5 -0
- package/src/intake-plane/telegram-seat-work.ts +13 -6
- 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/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 +32 -0
- package/src/loops/checker.ts +180 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +1 -1
- package/src/loops/loop-cli.ts +72 -6
- package/src/loops/neighbors.ts +40 -0
- package/src/loops/observe.ts +59 -0
- package/src/loops/orchestrator/author-depth.ts +164 -0
- package/src/loops/orchestrator/author-input-check.ts +77 -0
- package/src/loops/orchestrator/author-ledger.ts +230 -0
- package/src/loops/orchestrator/finish-rate.ts +175 -0
- package/src/loops/orchestrator/overlap.ts +180 -0
- package/src/loops/orchestrator/resync-shadow.ts +227 -0
- package/src/loops/orchestrator/tick.ts +302 -0
- package/src/loops/orchestrator/traffic.ts +165 -0
- package/src/loops/package/verify.ts +125 -0
- package/src/loops/registry.ts +454 -9
- package/src/loops/status-rows.ts +118 -0
- package/src/loops/verdict.ts +34 -0
- package/src/maturity/bot-slash-catalog.ts +66 -0
- package/src/maturity/feature-maturity.ts +8 -5
- package/src/memory.ts +37 -4
- package/src/nexus/api/card-followup-route.ts +118 -0
- package/src/nexus/api/dashboard.ts +6 -1
- package/src/nexus/api/decisions-route.ts +68 -0
- package/src/nexus/api/http-server.ts +65 -2
- package/src/nexus/api/merge-approvals-gate.ts +1 -1
- package/src/nexus/api/personas.ts +2 -1
- package/src/nexus/api/schedules-read.ts +5 -1
- package/src/nexus/api/skill-exec-route.ts +97 -0
- package/src/nexus/api/task-cards-api.ts +44 -5
- package/src/nexus/api/workflows.ts +2 -1
- package/src/persona/loader.ts +18 -0
- package/src/persona/persona-todo.ts +14 -9
- package/src/persona/presets.ts +2 -1
- package/src/persona/team.ts +105 -0
- package/src/persona/types.ts +4 -0
- package/src/pod-lease/host-lease.ts +130 -20
- package/src/release-loop/auto-start.ts +48 -0
- package/src/release-loop/checklist.ts +13 -4
- package/src/release-loop/feature-store.ts +28 -16
- package/src/release-loop/landed-but-yellow.ts +12 -0
- package/src/release-loop/landing-freeze.ts +121 -0
- package/src/release-loop/placement.ts +242 -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 +73 -15
- package/src/seat-dispatch/seat-questions.ts +58 -0
- package/src/seat-loop/seat-loop.ts +495 -46
- package/src/seat-loop/seat-pack.ts +127 -0
- package/src/self-dev/ask-launch-flow.ts +3 -0
- package/src/self-dev/dev-pipeline.ts +6 -2
- package/src/self-dev/draft-sweep.ts +76 -0
- package/src/self-dev/run-store.ts +73 -1
- package/src/self-dev/run-supervisor.ts +8 -0
- 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 +294 -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-lookup.ts +147 -0
- package/src/self-implement/heal-intake.ts +79 -0
- package/src/self-implement/host-regate.ts +25 -2
- package/src/self-implement/l8-merge-queue.ts +157 -1
- package/src/self-implement/orchestrator.ts +114 -10
- package/src/self-implement/revert-guard.ts +62 -0
- package/src/self-implement/run-ledger.ts +1 -1
- package/src/self-implement/seams.ts +28 -8
- package/src/session/index.ts +2 -0
- package/src/steward/launch.ts +5 -1
- package/src/steward/readiness.ts +125 -0
- package/src/steward/rescue.ts +75 -0
- package/src/steward/triage.ts +48 -9
- package/src/task-cards/card-cli.ts +86 -0
- package/src/task-cards/card-store.ts +10 -6
- package/src/task-orchestrator/surfaces/pod-lease.ts +23 -8
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +46 -6
- package/src/task-orchestrator/surfaces/pod-pool.ts +27 -10
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +112 -18
- package/src/telegram-commands.ts +27 -3
- package/src/telegram-dispatch-forward.ts +1 -1
- package/src/telegram-fabric-plan.ts +90 -0
- package/src/telegram-loops-command.ts +44 -0
- package/src/telegram-project-command.ts +10 -4
- package/src/telegram.ts +5 -0
- package/src/tool-runtime/elanous-control-runtimes.ts +2 -1
- package/src/user-config.ts +204 -16
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/executor.ts +4 -0
- package/src/workflow-runtime/node-catalog.ts +13 -0
- package/src/workflow-runtime/nodes/knowledge.ts +38 -0
- package/src/workflow-runtime/schema.ts +17 -1
- package/src/workflow-runtime/storage.ts +31 -13
- package/src/workflow-runtime/types.ts +13 -1
- package/apps/pwa/out/_next/static/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.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-2e522a8ac5f2afde.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/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/6751-bb3595948b2e311b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.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-0259994816604c49.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/9920-5cfdc5e8fd209825.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-cb169620945d1952.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5c05b0da4bc1392c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.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-1efd0cb9e0ed9d13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.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-9547b5cec7cf76bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.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/{-6XrAoD3eU7NyMHAE4xPS → x6mjI6vqOkVVu0jFuDkz1}/_ssgManifest.js +0 -0
package/src/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ import { registerRepoCommands } from './cli/repo-cli.js';
|
|
|
41
41
|
import { registerAgentCommands, runChatTurnCli, emitDetachedProgress } from './cli/agent-cli.js';
|
|
42
42
|
export { runChatTurnCli, buildCliAgentTools, setCliAgentDispatchForTesting, emitDetachedProgress, emitHarnessFeedbackProgress } from './cli/agent-cli.js';
|
|
43
43
|
import { registerOpsCommands } from './cli/ops-cli.js';
|
|
44
|
+
import { registerOutputsCommands } from './cli/outputs-cli.js';
|
|
44
45
|
import { registerPublishCommands } from './cli/publish-cli.js';
|
|
45
46
|
import { registerAutopilotCommands } from './cli/autopilot-cli.js';
|
|
46
47
|
import { registerRoleCommands } from './cli/role-cli.js';
|
|
@@ -62,6 +63,8 @@ import { registerUsageCommand } from './cli/usage-cli.js';
|
|
|
62
63
|
import { registerLiveCommands } from './cli/live-cli.js';
|
|
63
64
|
import { registerResearchCommand } from './cli/research-cli.js';
|
|
64
65
|
import { registerReleaseCommands } from './cli/release-cli.js';
|
|
66
|
+
import { registerFreezeCommands } from './cli/freeze-cli.js';
|
|
67
|
+
import { registerFlowCommands } from './cli/flow-cli.js';
|
|
65
68
|
import { registerModelWatchCommand } from './cli/model-watch-cli.js';
|
|
66
69
|
import { registerIntakeCommands } from './cli/intake-cli.js';
|
|
67
70
|
import { registerTasksCommands } from './cli/tasks-cli.js';
|
|
@@ -103,7 +106,7 @@ import type { AcpPermissionApprover } from './acp/client.js';
|
|
|
103
106
|
import { runGitCommand } from './git-fs/runner.js';
|
|
104
107
|
import { debug, redactSecretText, redactSecrets } from './debug/log.js';
|
|
105
108
|
import { installHarnessCliCommand, type HarnessAskSayChildLlmOptions, type HarnessAskSayOptions, type HarnessPlanOptions } from './harness/harness-cli-command.js';
|
|
106
|
-
import { formatCliUserError, isCliUserError } from './cli/cli-user-error.js';
|
|
109
|
+
import { CliUserError, formatCliUserError, isCliUserError } from './cli/cli-user-error.js';
|
|
107
110
|
import { dispatchSolveMission } from './skills/tools/solve-mission.js';
|
|
108
111
|
import { performBrowserAction, type BrowserActionDeps, type BrowserActionResult } from './harness/browser-act.js';
|
|
109
112
|
import { decideTypeAction, type TypeActionDecision, type TypeTarget } from './harness/browser-act-type.js';
|
|
@@ -868,7 +871,90 @@ registerUsageCommand(program);
|
|
|
868
871
|
registerLiveCommands(program);
|
|
869
872
|
registerResearchCommand(program);
|
|
870
873
|
registerReleaseCommands(program);
|
|
874
|
+
registerFreezeCommands(program);
|
|
875
|
+
registerFlowCommands(program);
|
|
876
|
+
// HQ-HB · HQ-FENCE (10-04): one writer across mbp · node-b · cloud-vm — lease on the arbiter, 2-of-3 quorum, generation fencing.
|
|
877
|
+
const hqCmd = program.command('hq').description('본부 임대 — 하트비트·중재·단일 작성자 래퍼');
|
|
878
|
+
async function hqSink(): Promise<void> {
|
|
879
|
+
try { await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('hq'); } catch { /* observation is fail-soft */ }
|
|
880
|
+
}
|
|
881
|
+
hqCmd.command('host').description('이 머신의 HQ 호스트 이름 설정')
|
|
882
|
+
.command('set <name>').description('호스트 로컬 ~/.elanous-hq/host 에 한 줄로 기록')
|
|
883
|
+
.action(async (name: string) => {
|
|
884
|
+
try {
|
|
885
|
+
const { hqHostSet } = await import('./hq/hq.js');
|
|
886
|
+
const path = hqHostSet(name);
|
|
887
|
+
console.log(`hq host set: ${name} (${path})`);
|
|
888
|
+
} catch (error) { console.error(`hq host set: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
889
|
+
});
|
|
890
|
+
hqCmd.command('lease').argument('<action>', 'acquire|renew|status|release')
|
|
891
|
+
.option('--host <name>', '이 호스트 이름(기본 ~/.elanous-hq/host · hq.hostName · os.hostname)')
|
|
892
|
+
.option('--json', 'JSON 출력')
|
|
893
|
+
.action(async (action: string, opts: { host?: string; json?: boolean }) => {
|
|
894
|
+
try {
|
|
895
|
+
if (!['acquire', 'renew', 'status', 'release'].includes(action)) throw new CliUserError(`hq lease: unknown action ${action}`, 'acquire|renew|status|release');
|
|
896
|
+
await hqSink();
|
|
897
|
+
const { hqLease } = await import('./hq/hq.js');
|
|
898
|
+
const result = hqLease(action as 'acquire', {}, opts.host ? { host: opts.host } : {});
|
|
899
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
900
|
+
else console.log(result.ok ? `hq lease ${action}: ok${'record' in result && result.record ? ` · holder ${result.record.holder} · generation ${result.record.generation}` : ''}` : `hq lease ${action}: refused — ${'reason' in result ? result.reason : ''}`);
|
|
901
|
+
if (!result.ok) process.exitCode = 2;
|
|
902
|
+
} catch (error) { if (error instanceof CliUserError) throw error; console.error(`hq lease: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
903
|
+
});
|
|
904
|
+
hqCmd.command('promote').description('HQ 승격 런북 (기본 dry-run · --apply 일 때만 변경)')
|
|
905
|
+
.requiredOption('--to <host>', '승격 대상 호스트')
|
|
906
|
+
.option('--apply', '대기 사본을 승격 우주에 반영하고 넥서스·rescue 실행')
|
|
907
|
+
.option('--json', 'JSON 출력')
|
|
908
|
+
.action(async (opts: { to: string; apply?: boolean; json?: boolean }) => {
|
|
909
|
+
try {
|
|
910
|
+
const { promoteHq, formatPromote } = await import('./hq/promote.js');
|
|
911
|
+
const result = promoteHq(opts.to, opts.apply === true);
|
|
912
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
913
|
+
else console.log(formatPromote(result));
|
|
914
|
+
if (!result.ok) process.exitCode = 1;
|
|
915
|
+
} catch (error) { console.error(`hq promote: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
916
|
+
});
|
|
917
|
+
hqCmd.command('heartbeat').description('보유자는 갱신 · 아니면 대기(보유자에 닿는지 중재자에 보고)').option('--json', 'JSON 출력')
|
|
918
|
+
.action(async (opts: { json?: boolean }) => {
|
|
919
|
+
try {
|
|
920
|
+
await hqSink();
|
|
921
|
+
const result = (await import('./hq/hq.js')).hqHeartbeat();
|
|
922
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`); else console.log(`hq heartbeat: ${result.outcome}`);
|
|
923
|
+
} catch (error) { console.error(`hq heartbeat: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
924
|
+
});
|
|
925
|
+
hqCmd.command('arbiter-check').description('중재자(cloud-vm)에서: 보유자 탐침 · 연속 2회 이중 불통이면 대기 호스트 승격').option('--json', 'JSON 출력')
|
|
926
|
+
.action(async (opts: { json?: boolean }) => {
|
|
927
|
+
try {
|
|
928
|
+
await hqSink();
|
|
929
|
+
const result = (await import('./hq/hq.js')).hqArbiterCheck();
|
|
930
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`); else console.log(`hq arbiter-check: ${result.promoted ? `promoted ${result.holder} gen ${result.generation}` : `streak ${result.streak}`}`);
|
|
931
|
+
} catch (error) { console.error(`hq arbiter-check: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
932
|
+
});
|
|
933
|
+
hqCmd.command('seen').description('이 호스트가 본 가장 높은 임대 세대(한 번도 못 봤으면 exit 3 — 드릴 전 기본 원천 판단용)').option('--json', 'JSON 출력')
|
|
934
|
+
.action(async (opts: { json?: boolean }) => {
|
|
935
|
+
const result = (await import('./hq/hq.js')).hqSeen();
|
|
936
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
937
|
+
else console.log(result.seen ? `hq seen: generation ${result.generation}` : 'hq seen: never');
|
|
938
|
+
process.exitCode = result.seen ? 0 : 3;
|
|
939
|
+
});
|
|
940
|
+
hqCmd.command('fence').description('이 호스트가 임대를 쥐었을 때만 명령 실행(아니면 건너뜀 · exit 0)')
|
|
941
|
+
.requiredOption('--role <role>', 'telegram-poller|cron|seat-loop|release-run|conatus|git-push')
|
|
942
|
+
.argument('<command...>', '-- 뒤의 명령')
|
|
943
|
+
.action(async (command: string[], opts: { role: string }) => {
|
|
944
|
+
const { FENCE_ROLES, hqFenceRun } = await import('./hq/hq.js');
|
|
945
|
+
if (!(FENCE_ROLES as readonly string[]).includes(opts.role)) throw new CliUserError(`hq fence: unknown role ${opts.role}`, FENCE_ROLES.join('|'));
|
|
946
|
+
await hqSink();
|
|
947
|
+
process.exitCode = hqFenceRun(opts.role as 'cron', command);
|
|
948
|
+
});
|
|
871
949
|
const seatCmd = program.command('seat').description('분배된 자리의 하루 루프와 보고');
|
|
950
|
+
seatCmd.command('answer <askId> <answer>').description('자리 질문에 답을 남기고 원래 표면으로 회신 예약')
|
|
951
|
+
.action(async (askId: string, answer: string) => {
|
|
952
|
+
try {
|
|
953
|
+
const { answerSeatAsk } = await import('./seat-dispatch/seat-ask.js');
|
|
954
|
+
answerSeatAsk(askId, answer);
|
|
955
|
+
console.log(`자리 답변 기록: ${askId}`);
|
|
956
|
+
} catch (error) { console.error(`seat answer: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
957
|
+
});
|
|
872
958
|
seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
873
959
|
.requiredOption('--once', '한 번 실행')
|
|
874
960
|
.option('--json', 'JSON 출력')
|
|
@@ -893,6 +979,20 @@ seatCmd.command('report').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
|
893
979
|
else console.log(result.body);
|
|
894
980
|
} catch (error) { console.error(`seat report: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
895
981
|
});
|
|
982
|
+
seatCmd.command('pack').description('자리 묶음').command('export')
|
|
983
|
+
.requiredOption('--seat <SEAT>', '내보낼 자리')
|
|
984
|
+
.requiredOption('--out <dir>', '비어 있는 산출 폴더')
|
|
985
|
+
.action(async (opts: { seat: string; out: string }) => {
|
|
986
|
+
try {
|
|
987
|
+
const { exportSeatPack } = await import('./seat-loop/seat-pack.js');
|
|
988
|
+
const result = exportSeatPack(opts.seat, opts.out);
|
|
989
|
+
console.log(`seat pack ${result.name} ${result.version}: ${result.files.length} files → ${opts.out}`);
|
|
990
|
+
} catch (error) {
|
|
991
|
+
const { SeatPackLeakError } = await import('./seat-loop/seat-pack.js');
|
|
992
|
+
console.error(`seat pack export: ${error instanceof Error ? error.message : String(error)}`);
|
|
993
|
+
process.exitCode = error instanceof SeatPackLeakError ? 2 : 1;
|
|
994
|
+
}
|
|
995
|
+
});
|
|
896
996
|
registerModelWatchCommand(program);
|
|
897
997
|
registerDoctorCommand(program);
|
|
898
998
|
// runCli() → main() → program.parseAsync() dispatches control serve and resources where|list.
|
|
@@ -974,6 +1074,19 @@ marketCmd.command('keygen').description('Generate a local test index signing key
|
|
|
974
1074
|
console.log(`Generated local index key ${pair.keyId}`);
|
|
975
1075
|
});
|
|
976
1076
|
|
|
1077
|
+
const stewardCmd = program.command('steward').description('Steward loop controls');
|
|
1078
|
+
stewardCmd.command('readiness').description('Read-only shadow evidence for a live decision')
|
|
1079
|
+
.option('--since <duration>', 'Lookback duration, e.g. 24h', '24h')
|
|
1080
|
+
.option('--json', 'JSON output')
|
|
1081
|
+
.action(async (opts: { since: string; json?: boolean }) => {
|
|
1082
|
+
process.exitCode = (await import('./steward/readiness.js')).runStewardReadinessCli(opts);
|
|
1083
|
+
});
|
|
1084
|
+
stewardCmd.command('mode [mode]').description('Show or set the steward mode: off|shadow|live|rescue (rescue = HQ move: launch·harvest·alert·decision cards only)')
|
|
1085
|
+
.option('--json', 'JSON output')
|
|
1086
|
+
.action(async (mode: string | undefined, opts: { json?: boolean }) => {
|
|
1087
|
+
process.exitCode = await (await import('./steward/rescue.js')).runStewardModeCli(mode, opts);
|
|
1088
|
+
});
|
|
1089
|
+
|
|
977
1090
|
program.command('directive').description('Turn instructions into Linear issues')
|
|
978
1091
|
.command('add <text>').option('--source <source>', 'telegram|pwa|tui|cli', 'cli')
|
|
979
1092
|
.option('--dry-run', 'Preview the normalized directive without contacting Linear')
|
|
@@ -2938,6 +3051,8 @@ export async function runHarnessOrchestrateExecution(
|
|
|
2938
3051
|
prior,
|
|
2939
3052
|
goals,
|
|
2940
3053
|
pid,
|
|
3054
|
+
...(['OP', 'TC', 'MK', 'UX'].includes(process.env.ELANOUS_HARNESS_SEAT ?? '')
|
|
3055
|
+
? { seat: process.env.ELANOUS_HARNESS_SEAT as SelfDevRunState['seat'] } : {}),
|
|
2941
3056
|
runIdSource,
|
|
2942
3057
|
now,
|
|
2943
3058
|
onPersistenceFailure: reportPersistenceFailure,
|
|
@@ -3029,6 +3144,39 @@ const harnessOrchestrateCmd = registerHarnessOrchestrateCapabilityOptions(
|
|
|
3029
3144
|
});
|
|
3030
3145
|
|
|
3031
3146
|
const contextCmd = program.command('context').description('외부 에이전트 맥락 이벤트');
|
|
3147
|
+
contextCmd.command('day')
|
|
3148
|
+
.description('자리 넷과 외부 세션의 최근 맥락 이벤트 수·마지막 시각 (읽기 전용)')
|
|
3149
|
+
.option('--since <hours>', '최근 시간 창 (예: 24h)', '24h')
|
|
3150
|
+
.option('--json', '구조화된 JSON 출력')
|
|
3151
|
+
.action(async (opts: { since: string; json?: boolean }) => {
|
|
3152
|
+
try {
|
|
3153
|
+
const { contextDay, renderContextDay } = await import('./context-bus/context-day.js');
|
|
3154
|
+
const report = contextDay(opts.since);
|
|
3155
|
+
await writeStdoutJson(`${opts.json ? JSON.stringify(report) : renderContextDay(report)}\n`);
|
|
3156
|
+
} catch (error) {
|
|
3157
|
+
console.error(`context day: ${error instanceof Error ? error.message : String(error)}`);
|
|
3158
|
+
process.exitCode = 2;
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
3161
|
+
contextCmd.command('condense')
|
|
3162
|
+
.description('최근 맥락 이벤트·결정·조율 요약을 프로젝트/자리별 장기 기억 후보 JSON ⊕ Markdown 으로 응축')
|
|
3163
|
+
.option('--since <hours>', '최근 시간 창 (예: 24h)', '24h')
|
|
3164
|
+
.option('--dry-run', '읽고 stdout 에만 출력 (기본 동작)')
|
|
3165
|
+
.option('--apply', '충돌은 OP 결정 원장으로 올리고 비충돌 후보를 기존 프로젝트 기억에 저장 · 이전 버전 은퇴')
|
|
3166
|
+
.option('--json', '구조화된 JSON 출력')
|
|
3167
|
+
.action(async (opts: { since: string; dryRun?: boolean; apply?: boolean; json?: boolean }) => {
|
|
3168
|
+
try {
|
|
3169
|
+
if (opts.apply && opts.dryRun) throw new Error('--apply and --dry-run cannot be combined');
|
|
3170
|
+
if (!/^[1-9]\d*h$/.test(opts.since)) throw new Error('--since requires positive hours, e.g. 24h');
|
|
3171
|
+
const { runContextCondense } = await import('./context-bus/condense.js');
|
|
3172
|
+
const report = await runContextCondense({ hours: Number(opts.since.slice(0, -1)), apply: opts.apply === true });
|
|
3173
|
+
await writeStdoutJson(JSON.stringify({ since: report.since, until: report.until, cards: report.cards, conflicts: report.conflicts, skipped: report.skipped, folded: report.folded, droppedHarnessChild: report.droppedHarnessChild, funnel: report.funnel, ...(report.applied ? { applied: report.applied } : {}) }) + '\n');
|
|
3174
|
+
if (!opts.json) await writeStdoutFully(report.markdown);
|
|
3175
|
+
} catch (error) {
|
|
3176
|
+
console.error(`context condense: ${error instanceof Error ? error.message : String(error)}`);
|
|
3177
|
+
process.exitCode = 2;
|
|
3178
|
+
}
|
|
3179
|
+
});
|
|
3032
3180
|
contextCmd.command('hooks').description('Claude Code 맥락 훅 설정').command('install')
|
|
3033
3181
|
.requiredOption('--print', '설정 조각만 출력하고 설정 파일은 수정하지 않음')
|
|
3034
3182
|
.action(async () => {
|
|
@@ -4171,6 +4319,35 @@ selfCmd
|
|
|
4171
4319
|
} catch (e) { console.error(`⛔ ${(e as Error).message}`); process.exitCode = 1; }
|
|
4172
4320
|
});
|
|
4173
4321
|
|
|
4322
|
+
export async function announceLaunchQuotaPolicy(input: {
|
|
4323
|
+
runId: string;
|
|
4324
|
+
current: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy;
|
|
4325
|
+
universe: { kind: 'prod' | 'test'; root: string };
|
|
4326
|
+
production?: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy;
|
|
4327
|
+
}): Promise<{ line: string; warning?: string; quotaPolicy: {
|
|
4328
|
+
policy: import('./oauth/codex-quota-policy.js').CodexQuotaPolicy;
|
|
4329
|
+
source: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy['source'];
|
|
4330
|
+
universeKind: 'prod' | 'test';
|
|
4331
|
+
} }> {
|
|
4332
|
+
const { describeLaunchQuotaPolicy } = await import('./oauth/codex-quota-policy.js');
|
|
4333
|
+
const { appendRunLedgerEntry } = await import('./self-implement/run-ledger.js');
|
|
4334
|
+
const described = describeLaunchQuotaPolicy(input);
|
|
4335
|
+
const data = { policy: input.current.policy, source: input.current.source, universe: input.universe,
|
|
4336
|
+
...(described.warning ? { warning: described.warning } : {}) };
|
|
4337
|
+
try {
|
|
4338
|
+
appendRunLedgerEntry({ runId: input.runId, timestamp: new Date().toISOString(), event: 'launch-quota-policy', data });
|
|
4339
|
+
} catch (error) {
|
|
4340
|
+
debug.log('pod.quota-policy', 'ledger-unavailable', { runId: input.runId, error: String(error) }, { level: 'warn' });
|
|
4341
|
+
throw new Error(`pod launch quota policy ledger write failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
4342
|
+
}
|
|
4343
|
+
debug.log('pod.quota-policy', 'announced', data);
|
|
4344
|
+
return { ...described, quotaPolicy: { policy: input.current.policy, source: input.current.source, universeKind: input.universe.kind } };
|
|
4345
|
+
}
|
|
4346
|
+
|
|
4347
|
+
export function withLaunchQuotaPolicy<T extends object>(results: readonly T[], quotaPolicy: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] | undefined): (T & { quotaPolicy?: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] })[] {
|
|
4348
|
+
return quotaPolicy ? results.map((result) => ({ ...result, quotaPolicy })) : [...results];
|
|
4349
|
+
}
|
|
4350
|
+
|
|
4174
4351
|
// self orchestrate — 병렬 self-dev(S1·2026-07-21) — N개 독립 goal 을 각자 `elanous self implement` 서브프로세스로
|
|
4175
4352
|
// TOX 디스패처 위에서 동시성캡 병렬 실행. 각 잡=자기 프로세스=자기 harness-space(병렬안전). 엔진(그래프/
|
|
4176
4353
|
// 디스패처)은 기존 재사용·새 조각=self-implement surface 어댑터. [[PLAN-parallel-self-dev-orchestrator-2026-07-21]].
|
|
@@ -4329,6 +4506,8 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4329
4506
|
prior,
|
|
4330
4507
|
goals,
|
|
4331
4508
|
pid: process.pid,
|
|
4509
|
+
...(['OP', 'TC', 'MK', 'UX'].includes(process.env.ELANOUS_HARNESS_SEAT ?? '')
|
|
4510
|
+
? { seat: process.env.ELANOUS_HARNESS_SEAT as SelfDevRunState['seat'] } : {}),
|
|
4332
4511
|
runIdSource,
|
|
4333
4512
|
now: () => Date.now(),
|
|
4334
4513
|
});
|
|
@@ -4363,6 +4542,7 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4363
4542
|
// coordinator 해석(decompose·run-identity·checkpoint·board)은 액션에 유지·감독 콜백은 runtime 으로 주입.
|
|
4364
4543
|
// ☸️ 실행 칸 — pod 면 self-implement 자식을 k8s Job 으로(계약 동일 · 슈퍼바이저 무수정).
|
|
4365
4544
|
const substrate = (opts as { substrate?: string }).substrate ?? 'local';
|
|
4545
|
+
let launchQuotaPolicy: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] | undefined;
|
|
4366
4546
|
let podSpawn: import('./task-orchestrator/surfaces/self-implement.js').SelfImplementJobSpawn | undefined;
|
|
4367
4547
|
let podTargets: { context: string; namespace: string }[] | undefined;
|
|
4368
4548
|
if (substrate === 'pod') {
|
|
@@ -4445,30 +4625,39 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4445
4625
|
const resolvedQuota = resolveCodexQuotaPolicy(getUserConfig().llm);
|
|
4446
4626
|
const quotaPolicy = resolvedQuota.policy;
|
|
4447
4627
|
// POL1 — say which policy this launch uses and where it came from; warn when a test universe disagrees with production.
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4628
|
+
const { effectiveInstanceRoot, prodInstanceRoot } = await import('./instance/resolve.js');
|
|
4629
|
+
const root = effectiveInstanceRoot();
|
|
4630
|
+
const kind = root === prodInstanceRoot() ? 'prod' as const : 'test' as const;
|
|
4631
|
+
let production: ReturnType<typeof resolveCodexQuotaPolicy> | undefined;
|
|
4632
|
+
if (kind === 'test') {
|
|
4633
|
+
try {
|
|
4634
|
+
const { readFileSync } = await import('node:fs');
|
|
4635
|
+
const prodLlm = (JSON.parse(readFileSync(`${prodInstanceRoot()}/config.json`, 'utf8')) as { llm?: Record<string, unknown> }).llm;
|
|
4636
|
+
production = resolveCodexQuotaPolicy(prodLlm);
|
|
4637
|
+
} catch { /* no production config on this machine */ }
|
|
4638
|
+
}
|
|
4639
|
+
const described = await announceLaunchQuotaPolicy({ runId, current: resolvedQuota, universe: { kind, root }, ...(production ? { production } : {}) });
|
|
4640
|
+
launchQuotaPolicy = described.quotaPolicy;
|
|
4641
|
+
debug.log('self-implement.pod', 'quota-policy', { policy: resolvedQuota.policy, source: resolvedQuota.source, universe: kind, productionPolicy: production?.policy ?? null });
|
|
4642
|
+
if (!opts.json) { ui.info(described.line); if (described.warning) ui.warn(described.warning); }
|
|
4643
|
+
// GROK-OPTIONAL (10-05): an expiring grok subscription the host cannot refresh is dropped from the chain here,
|
|
4644
|
+
// so the launch goes on with codex instead of dying later in hostGrokCredentials.
|
|
4645
|
+
let grokSubscriptionUsable = credential?.kind === 'subscription';
|
|
4646
|
+
if (grokSubscriptionUsable && codexPolicyAllowsFallback(quotaPolicy)) {
|
|
4647
|
+
const { podGrokSubscriptionUsable, podGrokSkippedLine } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
|
|
4648
|
+
const grokCheck = podGrokSubscriptionUsable();
|
|
4649
|
+
if (!grokCheck.usable) {
|
|
4650
|
+
grokSubscriptionUsable = false;
|
|
4651
|
+
if (!opts.json) ui.warn(podGrokSkippedLine(grokCheck));
|
|
4460
4652
|
}
|
|
4461
|
-
|
|
4462
|
-
debug.log('self-implement.pod', 'quota-policy', { policy: resolvedQuota.policy, source: resolvedQuota.source, universe: kind, productionPolicy: production?.policy ?? null });
|
|
4463
|
-
if (!opts.json) { ui.info(described.line); if (described.warning) ui.warn(described.warning); }
|
|
4464
|
-
} catch { /* the line is advice; the launch goes on */ }
|
|
4653
|
+
}
|
|
4465
4654
|
const plan = planPodProvider({
|
|
4466
4655
|
codexCandidates: inspectCodexRotation().candidates,
|
|
4467
4656
|
// Per-account caps (대표 default:97) override the Pod default cap — without them default was dropped at 60%.
|
|
4468
4657
|
thresholdPercentByAccount: getUserConfig().llm?.codexAccountRotationThresholdPercentByAccount,
|
|
4469
4658
|
// 대표 한도 정책 한 값(`llm.codexQuotaPolicy`) — 크레딧·폴백을 같이 정한다.
|
|
4470
4659
|
creditsAllowed: codexPolicyAllowsCredits(quotaPolicy),
|
|
4471
|
-
grokSubscription: codexPolicyAllowsFallback(quotaPolicy) &&
|
|
4660
|
+
grokSubscription: codexPolicyAllowsFallback(quotaPolicy) && grokSubscriptionUsable,
|
|
4472
4661
|
grokApiKey: codexPolicyAllowsFallback(quotaPolicy) && credential?.kind === 'api_key',
|
|
4473
4662
|
grokApiKeyOptIn,
|
|
4474
4663
|
});
|
|
@@ -4585,7 +4774,7 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4585
4774
|
debug.log('self-dev.reduce', 'orchestrate-reduce', { runId, shards: shards.length, kind: r.kind });
|
|
4586
4775
|
}
|
|
4587
4776
|
}
|
|
4588
|
-
if (opts.json) { await writeStdoutJson(JSON.stringify(results) + '\n'); await reportRun(results); return; }
|
|
4777
|
+
if (opts.json) { await writeStdoutJson(JSON.stringify(withLaunchQuotaPolicy(results, launchQuotaPolicy)) + '\n'); await reportRun(results); return; }
|
|
4589
4778
|
const done = results.filter((r) => r.status === 'done').length;
|
|
4590
4779
|
const promoted = results.filter((r) => r.prUrl).length;
|
|
4591
4780
|
const incomplete = results.length - done;
|
|
@@ -5616,6 +5805,7 @@ registerFleetCommands(program);
|
|
|
5616
5805
|
|
|
5617
5806
|
// ── ops (운영 관측 — 지금 뭐 도나·이상 없나·상태 전이) ──
|
|
5618
5807
|
registerOpsCommands(program);
|
|
5808
|
+
registerOutputsCommands(program);
|
|
5619
5809
|
|
|
5620
5810
|
registerPublishCommands(program);
|
|
5621
5811
|
|
|
@@ -5794,6 +5984,33 @@ agentCmd
|
|
|
5794
5984
|
process.exit(outcome.exitCode);
|
|
5795
5985
|
});
|
|
5796
5986
|
|
|
5987
|
+
agentCmd.command('duo [text...]')
|
|
5988
|
+
.description('Run Codex and Claude Code concurrently on the same mission in separate worktrees; summarize both PTY decisions and evidence.')
|
|
5989
|
+
.requiredOption('--left <backend>', 'codex or claude')
|
|
5990
|
+
.requiredOption('--right <backend>', 'codex or claude')
|
|
5991
|
+
.requiredOption('--branch <name>', 'base name for two distinct worktree branches')
|
|
5992
|
+
.option('--base <ref>', 'common branch base (default HEAD)')
|
|
5993
|
+
.option('--mission-file <path>', 'read the same verbatim mission from a file')
|
|
5994
|
+
.option('--evidence <mode>', 'doc|tsc|test (default tsc)', 'tsc')
|
|
5995
|
+
.option('--doc-dir <rel>', 'doc evidence directory')
|
|
5996
|
+
.option('--doc-glob <re>', 'doc evidence filename pattern')
|
|
5997
|
+
.option('--test-path <p>', 'test evidence test path')
|
|
5998
|
+
.option('--file <rel>', 'test evidence output file')
|
|
5999
|
+
.option('--max-rounds <n>', 'maximum PTY control rounds', '16')
|
|
6000
|
+
.option('--no-commit', 'do not commit completed worktrees')
|
|
6001
|
+
.action(async (textParts: string[], opts: import('./agent-mission/duo.js').DuoOptions) => {
|
|
6002
|
+
try {
|
|
6003
|
+
delete process.env.OPENAI_API_KEY;
|
|
6004
|
+
const { runAgentMissionDuo } = await import('./agent-mission/duo.js');
|
|
6005
|
+
const result = await runAgentMissionDuo(textParts, opts);
|
|
6006
|
+
console.log(`[duo] missionId=${result.missionId}\n${result.lines.join('\n')}`);
|
|
6007
|
+
process.exitCode = result.exitCode;
|
|
6008
|
+
} catch (error) {
|
|
6009
|
+
console.error(`duo: ${error instanceof Error ? error.message : String(error)}`);
|
|
6010
|
+
process.exitCode = 1;
|
|
6011
|
+
}
|
|
6012
|
+
});
|
|
6013
|
+
|
|
5797
6014
|
// ★ 리뷰 반응 완결 루프 (L1) — PR 리뷰(OK/보강/거절)를 트리거로 codex 가 자율 rework→재제출.
|
|
5798
6015
|
// ⭐ 옵션 정의·opts 조립은 `agent-mission/review-loop-cli.ts`(테스트 가능 seam) — 액션은 I/O 만 한다.
|
|
5799
6016
|
registerReviewLoopOptions(
|
|
@@ -6515,6 +6732,12 @@ const selfDevCmd = program
|
|
|
6515
6732
|
let devRunId = '';
|
|
6516
6733
|
let devRunIdSource: import('./harness/harness-space.js').RunIdSource | undefined;
|
|
6517
6734
|
let preparedWorktree: import('./harness/harness-worktree-auto.js').PreparedDevWorktree | undefined;
|
|
6735
|
+
let authoringLease: import('./pod-lease/host-lease.js').HostLeaseHandle | undefined;
|
|
6736
|
+
const releaseAuthoringLease = () => {
|
|
6737
|
+
if (!authoringLease) return;
|
|
6738
|
+
authoringLease(); authoringLease = undefined;
|
|
6739
|
+
process.off('exit', releaseAuthoringLease);
|
|
6740
|
+
};
|
|
6518
6741
|
try {
|
|
6519
6742
|
// ⛔ raw 입력 배타성 검증은 try 안의 selectDevAuthorInput 하나가 소유한다 — 실패도 아래 catch가 관측한다.
|
|
6520
6743
|
const { buildDevCommandInput, selectDevAuthorInput } = await import('./self-dev/dev-cli.js');
|
|
@@ -6607,6 +6830,23 @@ const selfDevCmd = program
|
|
|
6607
6830
|
priorBlockSamples: () => askIo.priorBlockSamplesFrom(askLogRows),
|
|
6608
6831
|
recentAuthoringSamples: () => askIo.recentAuthoringSamplesFrom(askLogRows),
|
|
6609
6832
|
authorGoal: (args, options) => runGoalAuthorCli([...args], options as never),
|
|
6833
|
+
...(devAskSubstrate?.substrate === 'pod' ? { beforeAuthoring: async () => {
|
|
6834
|
+
const { parsePodPool, podPoolHostLease } = await import('./task-orchestrator/surfaces/pod-pool.js');
|
|
6835
|
+
const { measurePoolLease, recommendConcurrency } = await import('./task-orchestrator/surfaces/pod-lease.js');
|
|
6836
|
+
const members = parsePodPool(devAskSubstrate.pool!);
|
|
6837
|
+
const host = podPoolHostLease(members);
|
|
6838
|
+
while (!authoringLease) {
|
|
6839
|
+
const status = recommendConcurrency(measurePoolLease(members), { capacity: members.reduce((n, m) => n + m.capacity, 0), accounts: 0, perAccount: 0 });
|
|
6840
|
+
if (status.recommended !== null && status.recommended > 0) {
|
|
6841
|
+
const { leaseHasPendingPod } = await import('./pod-lease/host-lease.js');
|
|
6842
|
+
const pendingJobs = status.pendingJobs ?? [];
|
|
6843
|
+
authoringLease = host.tryReserve((others) =>
|
|
6844
|
+
others - host.live().filter((r) => leaseHasPendingPod(r, pendingJobs)).length < status.recommended!, true) ?? undefined;
|
|
6845
|
+
if (authoringLease) process.once('exit', releaseAuthoringLease);
|
|
6846
|
+
}
|
|
6847
|
+
if (!authoringLease) await new Promise((resolve) => setTimeout(resolve, 15_000));
|
|
6848
|
+
}
|
|
6849
|
+
} } : {}),
|
|
6610
6850
|
relativeToCwd: (file) => relativeToCwdPath(process.cwd(), file),
|
|
6611
6851
|
});
|
|
6612
6852
|
// ⛔ 종료는 «표면»이 한다 — 흐름은 세 값만 낸다.
|
|
@@ -6616,6 +6856,7 @@ const selfDevCmd = program
|
|
|
6616
6856
|
}
|
|
6617
6857
|
askAuthoredFile = flowResult.goalFile;
|
|
6618
6858
|
if (flowResult.kind === 'stopped-by-preflight') {
|
|
6859
|
+
releaseAuthoringLease();
|
|
6619
6860
|
completionGuard.conclude();
|
|
6620
6861
|
process.exit(1);
|
|
6621
6862
|
}
|
|
@@ -6630,18 +6871,29 @@ const selfDevCmd = program
|
|
|
6630
6871
|
const { dispatchHarnessOnPod } = await import('./harness/harness-pod-dispatch.js');
|
|
6631
6872
|
const { devAskPodDispatchInput } = await import('./harness/harness-substrate-default.js');
|
|
6632
6873
|
const { classifyHarnessPodExit, harnessPodRunId, recordClassifiedHarnessPodExit, warnRecentIncidentBurst } = await import('./harness/harness-cli-command.js');
|
|
6633
|
-
warnRecentIncidentBurst(
|
|
6874
|
+
warnRecentIncidentBurst(undefined, undefined, undefined,
|
|
6875
|
+
{ entrance: 'cli-dev-ask', seat: opts.seat });
|
|
6634
6876
|
let podOutput = '';
|
|
6635
6877
|
let podRunId: string | undefined;
|
|
6636
|
-
const
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6878
|
+
const previousLeaseId = process.env.ELANOUS_POD_RESERVED_LEASE;
|
|
6879
|
+
if (authoringLease) process.env.ELANOUS_POD_RESERVED_LEASE = authoringLease.id;
|
|
6880
|
+
let status: number;
|
|
6881
|
+
try {
|
|
6882
|
+
status = await dispatchHarnessOnPod(devAskPodDispatchInput(opts, askAuthoredFile!, devAskSubstrate.pool!), {
|
|
6883
|
+
onOutput: (text) => {
|
|
6884
|
+
podRunId ??= harnessPodRunId(podOutput + text);
|
|
6885
|
+
podOutput = (podOutput + text).slice(-16_000);
|
|
6886
|
+
},
|
|
6887
|
+
});
|
|
6888
|
+
} finally {
|
|
6889
|
+
releaseAuthoringLease();
|
|
6890
|
+
if (previousLeaseId === undefined) delete process.env.ELANOUS_POD_RESERVED_LEASE;
|
|
6891
|
+
else process.env.ELANOUS_POD_RESERVED_LEASE = previousLeaseId;
|
|
6892
|
+
}
|
|
6642
6893
|
if (status !== 0) {
|
|
6643
6894
|
const classified = classifyHarnessPodExit({ status }, podOutput, { ...(podRunId ? { runId: podRunId } : {}) });
|
|
6644
|
-
recordClassifiedHarnessPodExit(podRunId ?? harnessPodRunId(podOutput), classified.reason, status
|
|
6895
|
+
recordClassifiedHarnessPodExit(podRunId ?? harnessPodRunId(podOutput), classified.reason, status,
|
|
6896
|
+
{ entrance: 'cli-dev-ask', seat: opts.seat, output: podOutput });
|
|
6645
6897
|
for (const line of classified.lines) console.error(line);
|
|
6646
6898
|
}
|
|
6647
6899
|
completionGuard.conclude();
|
|
@@ -6940,9 +7192,11 @@ const selfDevCmd = program
|
|
|
6940
7192
|
completionGuard.conclude();
|
|
6941
7193
|
process.exit(r.result.exitCode);
|
|
6942
7194
|
}
|
|
7195
|
+
releaseAuthoringLease();
|
|
6943
7196
|
completionGuard.conclude();
|
|
6944
7197
|
process.exit(ok ? 0 : 2);
|
|
6945
7198
|
} catch (e) {
|
|
7199
|
+
releaseAuthoringLease();
|
|
6946
7200
|
const msg = e instanceof Error ? e.message : String(e);
|
|
6947
7201
|
// ⚠️ 관측은 결론을 막지 않는다(리뷰 should-fix 5R) — 여기서 로거가 던지면 아래 `console.error` 와
|
|
6948
7202
|
// 의도한 `exit(1)` 까지 통째로 우회해, 사용자는 이유도 모른 채 다른 종료코드를 받는다.
|
|
@@ -9,7 +9,7 @@ import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-a
|
|
|
9
9
|
import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
|
|
10
10
|
import { getUserConfig, type UserConfig } from '../user-config.js';
|
|
11
11
|
import { answerAsSeat } from './seat-answer.js';
|
|
12
|
-
import { answerAsPersona, resolvePersonaAddress, type PersonaAnswerDeps } from './persona-answer.js';
|
|
12
|
+
import { answerAsPersona, resolvePersonaAddress, seatOfPersona, type PersonaAnswerDeps } from './persona-answer.js';
|
|
13
13
|
import {
|
|
14
14
|
submitIntakeWork,
|
|
15
15
|
type SubmitIntakeWorkDeps,
|
|
@@ -72,14 +72,21 @@ export async function handleDiscordSeatWork(
|
|
|
72
72
|
return ['OP', 'TC', 'MK', 'UX'].includes(id) ? sendTask(id, text, auth!.cfg, auth!.id) : null;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const
|
|
76
|
-
const hasUnresolved =
|
|
75
|
+
const initialSeats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
|
|
76
|
+
const hasUnresolved = initialSeats.some(({ seat }) => !seat);
|
|
77
77
|
const auth = hasUnresolved ? owner() : null;
|
|
78
78
|
if (hasUnresolved && auth && !deps.personaSource) await awaitGlobalPersonaLoad();
|
|
79
79
|
const source = hasUnresolved && auth ? (deps.personaSource ?? getGlobalPersonaRegistry()) : null;
|
|
80
|
-
const addressed =
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
const addressed = initialSeats.map(({ name, seat }) => {
|
|
81
|
+
const persona = !seat && source ? resolvePersonaAddress(name, source) : null;
|
|
82
|
+
const personaSeat = persona ? seatOfPersona(persona) : null;
|
|
83
|
+
if (persona && personaSeat) {
|
|
84
|
+
debug.log('persona.address', 'seat-alias', { name, personaId: persona.personaId, seat: personaSeat.id, via: 'discord' });
|
|
85
|
+
return { name: personaSeat.id, seat: personaSeat, persona: null };
|
|
86
|
+
}
|
|
87
|
+
return { name, seat, persona };
|
|
88
|
+
});
|
|
89
|
+
const seats = addressed;
|
|
83
90
|
const unknown = addressed.filter(({ seat, persona }) => !seat && (!persona || !auth)).map(({ name }) => `@${name}`);
|
|
84
91
|
if (unknown.length) return `어느 좌석을 말씀하시나요? ${unknown.join(', ')}은(는) 등록된 좌석이 아닙니다. 좌석을 확인해 다시 보내 주세요.`;
|
|
85
92
|
const personas = addressed.filter(({ persona }) => persona);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { fetchLinearIssues } from '../connectors/linear.js';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
import { getSecretAsync } from '../nexus/config/secrets/index.js';
|
|
4
|
+
import { CardStore } from '../task-cards/card-store.js';
|
|
5
|
+
import { createWishCard } from './wish-card.js';
|
|
6
|
+
|
|
7
|
+
export const LINEAR_WISH_KEY_MISSING = 'Linear 키가 없습니다 — elanous connector linear 로 먼저 등록하세요';
|
|
8
|
+
|
|
9
|
+
type LinearWishDeps = {
|
|
10
|
+
getApiKey?: () => Promise<string | undefined>;
|
|
11
|
+
fetchIssues?: typeof fetchLinearIssues;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
async function readLinearWishes(teamKey: string, options: { labelOrPrefix?: string; excludeLabel?: string }, deps: LinearWishDeps) {
|
|
15
|
+
const apiKey = await (deps.getApiKey ?? (() => getSecretAsync('connector.linear.apiKey')))();
|
|
16
|
+
if (!apiKey?.trim()) throw new Error(LINEAR_WISH_KEY_MISSING);
|
|
17
|
+
try {
|
|
18
|
+
return await (deps.fetchIssues ?? fetchLinearIssues)({ apiKey, teamKey, ...options });
|
|
19
|
+
} catch (error) {
|
|
20
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
21
|
+
throw new Error(message.replaceAll(apiKey, '[redacted]'));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LinearWishSuggestion { identifier: string; title: string; reason: string }
|
|
26
|
+
|
|
27
|
+
const WISH_PHRASES = [
|
|
28
|
+
{ pattern: /해\s*줘(?:요|라)?/, reason: '요청' },
|
|
29
|
+
{ pattern: /만들어(?:\s*줘(?:요)?)?/, reason: '제작' },
|
|
30
|
+
{ pattern: /원해(?:요)?/, reason: '희망' },
|
|
31
|
+
{ pattern: /있으면\s*좋겠다/, reason: '희망' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export async function suggestLinearWishes({ teamKey, deps = {} }: {
|
|
35
|
+
teamKey: string;
|
|
36
|
+
deps?: LinearWishDeps;
|
|
37
|
+
}): Promise<LinearWishSuggestion[]> {
|
|
38
|
+
const issues = await readLinearWishes(teamKey, { excludeLabel: 'wish' }, deps);
|
|
39
|
+
return issues.flatMap(issue => {
|
|
40
|
+
const match = WISH_PHRASES.find(({ pattern }) => pattern.test(`${issue.title}\n${issue.body}`));
|
|
41
|
+
return match && issue.identifier
|
|
42
|
+
? [{ identifier: issue.identifier, title: Array.from(issue.title).slice(0, 40).join(''), reason: match.reason }]
|
|
43
|
+
: [];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function scanLinearWishes({ teamKey, label = 'wish', store, deps = {} }: {
|
|
48
|
+
teamKey: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
store: CardStore;
|
|
51
|
+
deps?: LinearWishDeps;
|
|
52
|
+
}): Promise<{ added: number; duplicate: number; failed: number }> {
|
|
53
|
+
const issues = await readLinearWishes(teamKey, { labelOrPrefix: label }, deps);
|
|
54
|
+
let added = 0;
|
|
55
|
+
let duplicate = 0;
|
|
56
|
+
let failed = 0;
|
|
57
|
+
for (const issue of issues) {
|
|
58
|
+
try {
|
|
59
|
+
const result = createWishCard({
|
|
60
|
+
text: `${issue.title}\n\n${issue.body}\n\n${issue.url}`,
|
|
61
|
+
source: 'linear', ref: issue.identifier ?? '',
|
|
62
|
+
replyTo: { surface: 'linear', issueId: issue.ref },
|
|
63
|
+
}, store);
|
|
64
|
+
if (result.created) added++;
|
|
65
|
+
else duplicate++;
|
|
66
|
+
} catch {
|
|
67
|
+
failed++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
debug.log('intake.linear-wish', 'scanned', { teamKey, label, added, duplicate, failed });
|
|
71
|
+
return { added, duplicate, failed };
|
|
72
|
+
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { debug } from '../debug/log.js';
|
|
2
2
|
import { resolveMention, type PersonaSource } from '../persona/mention-parser.js';
|
|
3
3
|
import type { PersonaProfile } from '../persona/types.js';
|
|
4
|
+
import { resolveSeat, type SeatEntry } from '../seat-address/seat-address.js';
|
|
4
5
|
|
|
5
6
|
export interface PersonaAnswerDeps {
|
|
6
7
|
complete?: (prompt: string) => Promise<string>;
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
export function seatOfPersona(persona: PersonaProfile, resolve = resolveSeat): SeatEntry | null {
|
|
11
|
+
return persona.seat ? resolve(persona.seat) ?? null : null;
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
/** Resolve the registry mention first, then an exact display name. */
|
|
10
15
|
export function resolvePersonaAddress(name: string, source: PersonaSource): PersonaProfile | null {
|
|
11
16
|
const mention = resolveMention(name, source);
|
|
@@ -9,7 +9,7 @@ import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-a
|
|
|
9
9
|
import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
|
|
10
10
|
import { getUserConfig, type UserConfig } from '../user-config.js';
|
|
11
11
|
import { answerAsSeat } from './seat-answer.js';
|
|
12
|
-
import { answerAsPersona, resolvePersonaAddress, type PersonaAnswerDeps } from './persona-answer.js';
|
|
12
|
+
import { answerAsPersona, resolvePersonaAddress, seatOfPersona, type PersonaAnswerDeps } from './persona-answer.js';
|
|
13
13
|
import {
|
|
14
14
|
submitIntakeWork,
|
|
15
15
|
type SubmitIntakeWorkDeps,
|
|
@@ -66,16 +66,23 @@ export async function handleTelegramSeatWork(
|
|
|
66
66
|
const address = parseSeatAddress(text.replace(/^(@[A-Za-z][A-Za-z0-9_-]*(?:,@?[A-Za-z][A-Za-z0-9_-]*)*)/, (prefix) => prefix.replaceAll(',@', ',')));
|
|
67
67
|
if (!address) return null;
|
|
68
68
|
|
|
69
|
-
const
|
|
69
|
+
const initialSeats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
|
|
70
70
|
const names = address.seats;
|
|
71
71
|
debug.log('seat-address.telegram', 'parsed', { seats: names });
|
|
72
|
-
const hasUnresolved =
|
|
72
|
+
const hasUnresolved = initialSeats.some(({ seat }) => !seat);
|
|
73
73
|
const auth = hasUnresolved ? owner() : null;
|
|
74
74
|
if (hasUnresolved && auth && !deps.personaSource) await awaitGlobalPersonaLoad();
|
|
75
75
|
const source = hasUnresolved && auth ? (deps.personaSource ?? getGlobalPersonaRegistry()) : null;
|
|
76
|
-
const addressed =
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
const addressed = initialSeats.map(({ name, seat }) => {
|
|
77
|
+
const persona = !seat && source ? resolvePersonaAddress(name, source) : null;
|
|
78
|
+
const personaSeat = persona ? seatOfPersona(persona) : null;
|
|
79
|
+
if (persona && personaSeat) {
|
|
80
|
+
debug.log('persona.address', 'seat-alias', { name, personaId: persona.personaId, seat: personaSeat.id, via: 'telegram' });
|
|
81
|
+
return { name: personaSeat.id, seat: personaSeat, persona: null };
|
|
82
|
+
}
|
|
83
|
+
return { name, seat, persona };
|
|
84
|
+
});
|
|
85
|
+
const seats = addressed;
|
|
79
86
|
const unknown = addressed.filter(({ seat, persona }) => !seat && (!persona || !auth)).map(({ name }) => `@${name}`);
|
|
80
87
|
if (unknown.length) {
|
|
81
88
|
debug.log('seat-address.telegram', 'rejected', { seats: names, reason: 'unknown-seat' });
|