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
|
@@ -491,6 +491,8 @@ export interface AgentMissionSpec {
|
|
|
491
491
|
memory?: boolean;
|
|
492
492
|
/** PTY 닉네임(휴먼 리더블·goto 로 나중 접근). 기본 branch. */
|
|
493
493
|
nickname?: string;
|
|
494
|
+
/** Concurrent missions may share one decision stream alias without sharing a PTY or worktree. */
|
|
495
|
+
decisionMissionId?: string;
|
|
494
496
|
/** ⭐⭐ 그 브랜치를 이미 쥔 «소유» 워크트리가 있으면 지우지 말고 그대로 재사용하라고 요청한다
|
|
495
497
|
* (`createWorktree` 의 같은 이름 인자로 그대로 내려간다 · 판정은 거기 `gateWorktreeReuse` 가 한다).
|
|
496
498
|
*
|
|
@@ -513,11 +515,14 @@ export interface AgentMissionResult {
|
|
|
513
515
|
paths?: string[];
|
|
514
516
|
rounds: number;
|
|
515
517
|
evidencePath: string | null;
|
|
518
|
+
/** The evidence check outcome, independent of the final mission and DRIVE-OK verdicts. */
|
|
519
|
+
evidenceSatisfied?: boolean;
|
|
516
520
|
committed: boolean;
|
|
517
521
|
usedOmniCrawl: boolean;
|
|
518
522
|
detail: string;
|
|
519
523
|
ptyId?: string;
|
|
520
524
|
webUrl?: string | null;
|
|
525
|
+
driveVerdict?: ReturnType<typeof verdictForFinalPtyScreen>['kind'];
|
|
521
526
|
}
|
|
522
527
|
/** @deprecated codex 특정 이름 — AgentMissionResult 을 쓰라. */
|
|
523
528
|
export type CodexMissionResult = AgentMissionResult;
|
|
@@ -1609,7 +1614,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1609
1614
|
const finalEv = verifyEvidence(wt.path, spec.evidence);
|
|
1610
1615
|
if (!finalEv.ok) return {
|
|
1611
1616
|
ok: false, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
|
|
1612
|
-
evidencePath: null, committed: false, usedOmniCrawl: false,
|
|
1617
|
+
evidencePath: null, evidenceSatisfied: false, committed: false, usedOmniCrawl: false,
|
|
1613
1618
|
detail: `미완(증거 부족): ${finalEv.retry ?? '증거가 아직 부족하다.'}`,
|
|
1614
1619
|
};
|
|
1615
1620
|
if (checklist.length) {
|
|
@@ -1627,13 +1632,13 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1627
1632
|
if (!c.ok) {
|
|
1628
1633
|
debug.log('agent-mission', 'result', { ok: false, rounds: result.numTurns ?? 0, evidencePath: finalEv.path, committed: false, usedOmni: false });
|
|
1629
1634
|
return { ok: false, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
|
|
1630
|
-
evidencePath: finalEv.path, committed: false, usedOmniCrawl: false,
|
|
1635
|
+
evidencePath: finalEv.path, evidenceSatisfied: true, committed: false, usedOmniCrawl: false,
|
|
1631
1636
|
detail: `미완(자동 커밋 실패): ${c.out.slice(0, 120)}` };
|
|
1632
1637
|
}
|
|
1633
1638
|
}
|
|
1634
1639
|
debug.log('agent-mission', 'result', { ok: true, rounds: result.numTurns ?? 0, evidencePath: finalEv.path, committed, usedOmni: false });
|
|
1635
1640
|
return { ok: true, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
|
|
1636
|
-
evidencePath: finalEv.path, committed, usedOmniCrawl: false, detail: '완료(증거 충족)' };
|
|
1641
|
+
evidencePath: finalEv.path, evidenceSatisfied: true, committed, usedOmniCrawl: false, detail: '완료(증거 충족)' };
|
|
1637
1642
|
}
|
|
1638
1643
|
env.TERM = 'xterm-256color';
|
|
1639
1644
|
// ⭐run-identity — runId was resolved before either headless or PTY spawn.
|
|
@@ -1713,7 +1718,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1713
1718
|
process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
|
|
1714
1719
|
debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
|
|
1715
1720
|
|
|
1716
|
-
const decisionIdentity = { missionId: runId, sessionId: runId, terminalId: h.id, agent: backend.name };
|
|
1721
|
+
const decisionIdentity = { missionId: spec.decisionMissionId ?? runId, sessionId: runId, terminalId: h.id, agent: backend.name };
|
|
1717
1722
|
const decisionEvent = (event: Omit<DecisionInput, keyof typeof decisionIdentity>): void => {
|
|
1718
1723
|
try { (deps.emitPtyDecision ?? emitPtyDecision)({ ...decisionIdentity, ...event } as DecisionInput); }
|
|
1719
1724
|
catch { /* Observation must not change mission control or handoff. */ }
|
|
@@ -2142,7 +2147,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2142
2147
|
try { h.kill(); } catch { /* noop */ }
|
|
2143
2148
|
return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni,
|
|
2144
2149
|
...(handoffPrSkipped ? { pr: 'skipped' as const, reason: 'origin-not-github' as const } : {}),
|
|
2145
|
-
detail: handoffPrSkipped ? '완료(증거 게이트·push·PR 생략)' : '완료(증거 게이트·PR)' };
|
|
2150
|
+
evidenceSatisfied: true, detail: handoffPrSkipped ? '완료(증거 게이트·push·PR 생략)' : '완료(증거 게이트·PR)' };
|
|
2146
2151
|
}
|
|
2147
2152
|
const done = control.termination.kind === 'success';
|
|
2148
2153
|
const round = control.steps;
|
|
@@ -2197,8 +2202,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2197
2202
|
rounds: round, evidencePath: null, committed: false, usedOmniCrawl: usedOmni, detail: 'aborted' };
|
|
2198
2203
|
const finalEv = verifyEvidence(wt.path, spec.evidence);
|
|
2199
2204
|
const finalScreen = await h.renderScreen();
|
|
2200
|
-
const driveVerdict = verdictForFinalPtyScreen({ screen: finalScreen, inputHistory: submittedInputs, exitCode: h.exitCode ?? null });
|
|
2201
|
-
debug.log('agent-mission', 'drive-
|
|
2205
|
+
const driveVerdict = verdictForFinalPtyScreen({ screen: finalScreen, inputHistory: submittedInputs, exitCode: h.exitCode ?? null, artifactEvidence: finalEv.ok });
|
|
2206
|
+
debug.log('agent-mission', 'drive-ok', { verdict: driveVerdict.kind, reason: driveVerdict.reason.slice(0, 200), evidence: finalEv.ok });
|
|
2202
2207
|
const recoverExhausted = control.termination.kind === 'stuck' && control.termination.reason.startsWith('사람 필요');
|
|
2203
2208
|
const accepted = finalEv.ok && !recoverExhausted && driveVerdict.kind !== 'done-but-failed';
|
|
2204
2209
|
const evidencePath = accepted ? finalEv.path : null;
|
|
@@ -2216,9 +2221,9 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2216
2221
|
|
|
2217
2222
|
return {
|
|
2218
2223
|
ok: accepted, worktree: wt.path, branch: wt.branch, rounds: round,
|
|
2219
|
-
evidencePath, committed, usedOmniCrawl: usedOmni,
|
|
2220
|
-
ptyId: h.id, webUrl: webAddress.webUrl,
|
|
2221
|
-
detail: recoverExhausted ? control.termination.reason : driveVerdict.kind === 'done-but-failed' ? `미완(DRIVE-OK: ${driveVerdict.reason})` : done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
|
|
2224
|
+
evidencePath, evidenceSatisfied: finalEv.ok, committed, usedOmniCrawl: usedOmni,
|
|
2225
|
+
ptyId: h.id, webUrl: webAddress.webUrl, driveVerdict: driveVerdict.kind,
|
|
2226
|
+
detail: recoverExhausted ? control.termination.reason : driveVerdict.kind === 'done-but-failed' ? `미완(DRIVE-OK: ${driveVerdict.reason})` : driveVerdict.kind === 'success-unverified' && finalEv.ok ? '완료(증거)' : done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
|
|
2222
2227
|
};
|
|
2223
2228
|
} finally { stopLive(); finishContext(false); }
|
|
2224
2229
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { runAgentMission, resolveBackend, type AgentBackend, type AgentMissionResult, type AgentMissionSpec, type EvidenceMode } from './driver.js';
|
|
4
|
+
|
|
5
|
+
export interface DuoOptions {
|
|
6
|
+
left: string;
|
|
7
|
+
right: string;
|
|
8
|
+
branch: string;
|
|
9
|
+
base?: string;
|
|
10
|
+
missionFile?: string;
|
|
11
|
+
evidence?: string;
|
|
12
|
+
docDir?: string;
|
|
13
|
+
docGlob?: string;
|
|
14
|
+
testPath?: string;
|
|
15
|
+
file?: string;
|
|
16
|
+
maxRounds?: string;
|
|
17
|
+
commit?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface DuoSide {
|
|
21
|
+
side: 'left' | 'right';
|
|
22
|
+
backend: string;
|
|
23
|
+
branch: string;
|
|
24
|
+
finished: number;
|
|
25
|
+
result?: AgentMissionResult;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface DuoResult {
|
|
30
|
+
missionId: string;
|
|
31
|
+
sides: [DuoSide, DuoSide];
|
|
32
|
+
lines: [string, string];
|
|
33
|
+
exitCode: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface DuoDeps {
|
|
37
|
+
resolveBackend?: typeof resolveBackend;
|
|
38
|
+
runMission?: typeof runAgentMission;
|
|
39
|
+
readFile?: (path: string) => string;
|
|
40
|
+
id?: () => string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function evidenceFor(opts: DuoOptions): EvidenceMode {
|
|
44
|
+
if (opts.evidence === 'doc') return { kind: 'doc', dirRel: opts.docDir ?? 'docs/plans', glob: new RegExp(opts.docGlob ?? '^PLAN-.*[.]md$', 'i') };
|
|
45
|
+
if (opts.evidence === 'test') {
|
|
46
|
+
if (!opts.testPath) throw new Error('test 모드엔 --test-path 필요');
|
|
47
|
+
return { kind: 'test', testPath: opts.testPath, ...(opts.file ? { fileRel: opts.file } : {}) };
|
|
48
|
+
}
|
|
49
|
+
if (opts.evidence === undefined || opts.evidence === 'tsc') return { kind: 'tsc' };
|
|
50
|
+
throw new Error('--evidence 는 doc|tsc|test 여야 합니다');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function render(side: DuoSide, first: DuoSide | undefined): string {
|
|
54
|
+
const evidence = side.result?.evidenceSatisfied === true
|
|
55
|
+
? side.result.evidencePath ? `충족(${side.result.evidencePath})` : '충족'
|
|
56
|
+
: side.result?.evidenceSatisfied === false ? '미충족' : '미측정';
|
|
57
|
+
const drive = side.result?.driveVerdict ?? '미측정';
|
|
58
|
+
const detail = side.error ?? (!side.result?.ok ? side.result?.detail : undefined);
|
|
59
|
+
return `${side.side} ${side.backend} · branch=${side.branch} · terminalId=${side.result?.ptyId ?? '없음'} · ${first === side ? '먼저' : '나중'} · 증거 ${evidence} · DRIVE-OK ${drive} · ${side.result?.ok ? '완료' : '실패'}${detail ? ` (${detail})` : ''}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Run two independent existing agent missions; neither branch waits for or cancels its peer. */
|
|
63
|
+
export async function runAgentMissionDuo(textParts: string[], opts: DuoOptions, deps: DuoDeps = {}): Promise<DuoResult> {
|
|
64
|
+
if (!opts.branch?.trim()) throw new Error('--branch 필요');
|
|
65
|
+
if (opts.left !== 'codex' && opts.left !== 'claude') throw new Error('--left 는 codex|claude 여야 합니다');
|
|
66
|
+
if (opts.right !== 'codex' && opts.right !== 'claude') throw new Error('--right 는 codex|claude 여야 합니다');
|
|
67
|
+
if (opts.left === opts.right) throw new Error('duo 에는 서로 다른 backend 둘이 필요합니다');
|
|
68
|
+
const mission = opts.missionFile ? (deps.readFile ?? ((path) => readFileSync(path, 'utf8')))(opts.missionFile) : textParts.join(' ');
|
|
69
|
+
if (!mission.trim()) throw new Error('미션 텍스트가 비었다 — <text...> 또는 --mission-file 필요');
|
|
70
|
+
const evidence = evidenceFor(opts);
|
|
71
|
+
const rounds = opts.maxRounds === undefined ? 16 : Number(opts.maxRounds);
|
|
72
|
+
if (!Number.isSafeInteger(rounds) || rounds <= 0) throw new Error('--max-rounds 는 양의 정수여야 합니다');
|
|
73
|
+
const resolve = deps.resolveBackend ?? resolveBackend;
|
|
74
|
+
const backends: [AgentBackend, AgentBackend] = [resolve(opts.left), resolve(opts.right)];
|
|
75
|
+
if (backends[0].name !== opts.left || backends[1].name !== opts.right) throw new Error('backend 선택이 요청과 다릅니다');
|
|
76
|
+
const id = `duo-${(deps.id ?? randomUUID)()}`;
|
|
77
|
+
const run = deps.runMission ?? runAgentMission;
|
|
78
|
+
let completed = 0;
|
|
79
|
+
const branches = [`${opts.branch}-${opts.left}`, `${opts.branch}-${opts.right}`] as const;
|
|
80
|
+
const tasks = backends.map(async (backend, index): Promise<DuoSide> => {
|
|
81
|
+
const side = index === 0 ? 'left' : 'right';
|
|
82
|
+
const branch = branches[index]!;
|
|
83
|
+
const spec: AgentMissionSpec = {
|
|
84
|
+
mission, branch, agent: backend, decisionMissionId: id, evidence, maxRounds: rounds,
|
|
85
|
+
...(opts.base ? { base: opts.base } : {}), commit: opts.commit !== false,
|
|
86
|
+
enhance: false, memory: false, resources: 'off', entry: 'external-verbatim',
|
|
87
|
+
};
|
|
88
|
+
try { return { side, backend: backend.name, branch, result: await run(spec), finished: ++completed }; }
|
|
89
|
+
catch (error) { return { side, backend: backend.name, branch, error: error instanceof Error ? error.message : String(error), finished: ++completed }; }
|
|
90
|
+
});
|
|
91
|
+
const sides = await Promise.all(tasks) as [DuoSide, DuoSide];
|
|
92
|
+
const first = sides[0].finished <= sides[1].finished ? sides[0] : sides[1];
|
|
93
|
+
return { missionId: id, sides, lines: [render(sides[0], first), render(sides[1], first)], exitCode: sides.every((s) => s.result?.ok) ? 0 : 2 };
|
|
94
|
+
}
|
|
@@ -44,7 +44,7 @@ function safe(value: string): string {
|
|
|
44
44
|
export function emitPtyDecision(input: DecisionInput, log: typeof debug.log = (category, event, data) => debug.log(category, event, data)): PtyDecision {
|
|
45
45
|
let stream = missionStreams.get(input.missionId);
|
|
46
46
|
if (!stream) {
|
|
47
|
-
stream = { alias:
|
|
47
|
+
stream = { alias: `${input.missionId.startsWith('duo-') ? 'duo' : 'mission'}-${missionStreams.size + 1}`, seq: -1 };
|
|
48
48
|
missionStreams.set(input.missionId, stream);
|
|
49
49
|
}
|
|
50
50
|
stream.seq += 1;
|
|
@@ -10,6 +10,9 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
10
10
|
import { runGitCommand } from '../../git-fs/runner.js';
|
|
11
11
|
import { countTestDeclarations } from '../../self-implement/test-declarations.js';
|
|
12
12
|
import { NEXT_MD_PATH, resolveNextMdConflict } from '../../release-loop/next-md-merge.js';
|
|
13
|
+
import { getUserConfig } from '../../user-config.js';
|
|
14
|
+
import { debug } from '../../debug/log.js';
|
|
15
|
+
import { collectMergeIntent, defaultIntentGit, type IntentGit } from './merge-intent.js';
|
|
13
16
|
|
|
14
17
|
function deterministicNextMd(git: MergeGitSeam, worktreePath: string, file: string): string | null {
|
|
15
18
|
try {
|
|
@@ -328,27 +331,61 @@ export function defaultGitMergeSeam(): MergeGitSeam {
|
|
|
328
331
|
}
|
|
329
332
|
|
|
330
333
|
/** 실 LLM 충돌 해결 어댑터(streamLLM·sol). 코드펜스/설명 제거해 완결 파일만. */
|
|
331
|
-
export async function defaultLlmResolve(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
334
|
+
export async function defaultLlmResolve(
|
|
335
|
+
filePath: string, conflicted: string, mergeTarget: string,
|
|
336
|
+
options: { worktreePath?: string; mode?: 'off' | 'shadow' | 'on'; git?: IntentGit; stream?: typeof import('../../llm.js')['streamLLM'] } = {},
|
|
337
|
+
): Promise<string> {
|
|
338
|
+
let rawMode: unknown = options.mode;
|
|
339
|
+
if (rawMode === undefined) {
|
|
340
|
+
try { rawMode = (getUserConfig().raw.selfImplement as { mergeIntent?: unknown } | undefined)?.mergeIntent; }
|
|
341
|
+
catch { /* unreadable config keeps the old resolver */ }
|
|
342
|
+
}
|
|
343
|
+
const mode = rawMode === 'shadow' || rawMode === 'on' ? rawMode : 'off';
|
|
344
|
+
const streamLLM = options.stream ?? (await import('../../llm.js')).streamLLM;
|
|
345
|
+
const resolve = async (intent?: { ours: string | null; theirs: string[] }): Promise<string> => {
|
|
346
|
+
const out = await streamLLM([{ role: 'user', content: conflictResolvePrompt(filePath, conflicted, mergeTarget, intent) }], () => {}, { model: process.env.ELANOUS_CONFLICT_MODEL || tierModel('better'), reasoningEffort: 'medium' });
|
|
347
|
+
// ⛔ 라우터는 공급자가 전부 막히면 던지지 않고 오류 문구를 돌려준다 — 그것은 파일 내용이 아니다.
|
|
348
|
+
if (PROVIDER_FAILURE_TEXT.test(out)) throw new Error(`conflict resolve: LLM provider failure for ${filePath}`);
|
|
349
|
+
return `${out.replace(/^```[\w.-]*\n?/, '').replace(/\n?```\s*$/, '').trimEnd()}\n`;
|
|
350
|
+
};
|
|
351
|
+
if (mode === 'off') return resolve();
|
|
352
|
+
const collect = () => collectMergeIntent({ worktreePath: options.worktreePath ?? process.cwd(), filePath, mergeTarget, git: options.git ?? defaultIntentGit });
|
|
353
|
+
if (mode === 'on') return resolve(collect());
|
|
354
|
+
const plain = await resolve();
|
|
355
|
+
try {
|
|
356
|
+
const intent = collect();
|
|
357
|
+
const withIntent = await resolve(intent);
|
|
358
|
+
debug.log('self-dev.merge', 'intent-shadow', {
|
|
359
|
+
file: filePath, same: plain === withIntent,
|
|
360
|
+
plainMarkers: hasConflictMarkers(plain), intentMarkers: hasConflictMarkers(withIntent),
|
|
361
|
+
plainLines: lineCount(plain), intentLines: lineCount(withIntent),
|
|
362
|
+
oursIntent: intent.ours !== null, theirsCount: intent.theirs.length,
|
|
363
|
+
});
|
|
364
|
+
} catch (error) {
|
|
365
|
+
try { debug.log('self-dev.merge', 'intent-shadow-failed', { file: filePath, error: String(error) }); }
|
|
366
|
+
catch { /* shadow observation must not affect the adopted result */ }
|
|
367
|
+
}
|
|
368
|
+
return plain;
|
|
337
369
|
}
|
|
338
370
|
|
|
339
371
|
/** 편의 — 실 git+LLM 으로 호출부가 해석한 ref를 worktree 에 지능 정합한다. */
|
|
340
372
|
export async function mergeMainIntoWorktreeWithLlm(worktreePath: string, mergeTarget: string): Promise<LlmMergeOutcome> {
|
|
341
|
-
return mergeMainWithLlmResolve(worktreePath, mergeTarget, (filePath, conflicted) => defaultLlmResolve(filePath, conflicted, mergeTarget), defaultGitMergeSeam());
|
|
373
|
+
return mergeMainWithLlmResolve(worktreePath, mergeTarget, (filePath, conflicted) => defaultLlmResolve(filePath, conflicted, mergeTarget, { worktreePath }), defaultGitMergeSeam());
|
|
342
374
|
}
|
|
343
375
|
|
|
344
376
|
/** LLM 충돌 해결 프롬프트(순수·테스트) — ours(walker)·theirs(호출자가 전달한 정합 대상) 종합 지시. */
|
|
345
|
-
export function conflictResolvePrompt(filePath: string, conflictedContent: string, mergeTarget: string): string {
|
|
377
|
+
export function conflictResolvePrompt(filePath: string, conflictedContent: string, mergeTarget: string, intent?: { ours: string | null; theirs: string[] }): string {
|
|
346
378
|
return [
|
|
347
379
|
'너는 git merge 충돌을 지능적으로 해결하는 엔지니어다. 아래 파일은 3-way merge 충돌 마커를 포함한다:',
|
|
348
380
|
' <<<<<<< ours = 현재 브랜치(walker 가 이 미션에서 만든 산출물)',
|
|
349
381
|
' ======= 사이 = 양쪽 버전',
|
|
350
382
|
` >>>>>>> theirs = ${mergeTarget}(호출자가 해석해 전달한 정합 대상)`,
|
|
351
383
|
'',
|
|
384
|
+
...(intent ? [
|
|
385
|
+
`ours 의 의도: ${intent.ours ?? '(확인 불가)'}`,
|
|
386
|
+
`theirs 에 먼저 착지한 변경: ${intent.theirs.length ? intent.theirs.join(' · ') : '(확인 불가)'}`,
|
|
387
|
+
'',
|
|
388
|
+
] : []),
|
|
352
389
|
'해결 원칙:',
|
|
353
390
|
'- 양쪽의 의도를 **모두 보존**하며 종합한다(한쪽을 통째로 버리지 않는다).',
|
|
354
391
|
`- 같은 목적의 중복(예: 같은 테스트·같은 함수)은 **theirs(${mergeTarget}) 버전을 채택**하고 ours 의 중복은 제거.`,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { runGitCommand } from '../../git-fs/runner.js';
|
|
4
|
+
|
|
5
|
+
export interface MergeIntent {
|
|
6
|
+
ours: string | null;
|
|
7
|
+
theirs: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type IntentGit = (worktreePath: string, args: string[]) => { status: number | null; stdout: string };
|
|
11
|
+
|
|
12
|
+
export const defaultIntentGit: IntentGit = (worktreePath, args) => {
|
|
13
|
+
const result = runGitCommand(worktreePath, args, { encoding: 'utf8' });
|
|
14
|
+
return { status: result.status, stdout: result.stdout ?? '' };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Read only commits introduced on each side of the merge base; a missing ref/document never blocks resolution. */
|
|
18
|
+
export function collectMergeIntent({ worktreePath, filePath, mergeTarget, git }: {
|
|
19
|
+
worktreePath: string;
|
|
20
|
+
filePath: string;
|
|
21
|
+
mergeTarget: string;
|
|
22
|
+
git: IntentGit;
|
|
23
|
+
}): MergeIntent {
|
|
24
|
+
const read = (...args: string[]): string | null => {
|
|
25
|
+
try {
|
|
26
|
+
const result = git(worktreePath, args);
|
|
27
|
+
return result.status === 0 ? result.stdout.trim() : null;
|
|
28
|
+
} catch { return null; }
|
|
29
|
+
};
|
|
30
|
+
const base = read('merge-base', 'HEAD', mergeTarget);
|
|
31
|
+
if (!base) return { ours: null, theirs: [] };
|
|
32
|
+
|
|
33
|
+
let ours: string | null = null;
|
|
34
|
+
const added = read('log', '--reverse', '--diff-filter=A', '--format=', '--name-only', '-z', `${base}..HEAD`, '--', 'docs/goals/');
|
|
35
|
+
for (const goal of added?.split('\0').map((file) => file.trim()).filter((file) => /^docs\/goals\/[^/]+$/.test(file)) ?? []) {
|
|
36
|
+
try {
|
|
37
|
+
const content = readFileSync(join(worktreePath, goal), 'utf8');
|
|
38
|
+
const lines = content.split(/\r?\n/);
|
|
39
|
+
const title = lines.find((line) => /^#\s+\S/.test(line))?.replace(/^#\s+/, '').trim()
|
|
40
|
+
?? lines.find((line) => line.trim().length > 0)?.trim();
|
|
41
|
+
const situation = lines.find((line) => /^Situation:/.test(line))?.trim();
|
|
42
|
+
const complication = lines.find((line) => /^Complication:/.test(line))?.trim();
|
|
43
|
+
ours = [title, situation, complication].filter(Boolean).join('\n') || null;
|
|
44
|
+
if (ours) break;
|
|
45
|
+
} catch { /* missing goal: try the next added document */ }
|
|
46
|
+
}
|
|
47
|
+
if (!ours) {
|
|
48
|
+
const subjects = read('log', '-3', '--format=%s', `${base}..HEAD`);
|
|
49
|
+
ours = subjects || null;
|
|
50
|
+
}
|
|
51
|
+
const subjects = read('log', '-5', '--format=%s', `${base}..${mergeTarget}`, '--', filePath);
|
|
52
|
+
return { ours, theirs: subjects ? subjects.split('\n') : [] };
|
|
53
|
+
}
|
|
@@ -2,6 +2,7 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { appendFileSync, mkdirSync, readFileSync, rmdirSync } from 'node:fs';
|
|
3
3
|
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
|
+
import { stateDirSourceForChild } from '../agent/identity-env.js';
|
|
5
6
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
6
7
|
import type { TrackAgentDecision, TrackAgentInput, TrackAgentResult } from './track-agent.js';
|
|
7
8
|
|
|
@@ -127,7 +128,7 @@ export async function launchTrackAgentShadow(input: TrackAgentInput, options: Sh
|
|
|
127
128
|
const instanceRoot = effectiveInstanceRoot();
|
|
128
129
|
const { stdout } = await exec('bun', ['bin/elanous.mjs', '--config-dir', instanceRoot, ...values], {
|
|
129
130
|
cwd: process.env.ELANOUS_TOOL_CWD?.trim() || resolve(import.meta.dir, '../..'),
|
|
130
|
-
env: { ...process.env, ELANOUS_STATE_DIR: instanceRoot },
|
|
131
|
+
env: { ...process.env, ELANOUS_STATE_DIR: instanceRoot, ELANOUS_STATE_DIR_SOURCE: stateDirSourceForChild(instanceRoot) },
|
|
131
132
|
encoding: 'utf8', maxBuffer: 1024 * 1024,
|
|
132
133
|
});
|
|
133
134
|
return { stdout };
|
|
@@ -2,6 +2,7 @@ import { execFile, spawn } from 'node:child_process';
|
|
|
2
2
|
import { readdirSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
|
+
import { stateDirSourceForChild } from '../agent/identity-env.js';
|
|
5
6
|
import { debug, redactSecretText } from '../debug/log.js';
|
|
6
7
|
import { getOrCreatePersonaSession } from '../session/index.js';
|
|
7
8
|
import { getUserConfig } from '../user-config.js';
|
|
@@ -38,7 +39,9 @@ const log = (event: string, data: Record<string, unknown>) => {
|
|
|
38
39
|
};
|
|
39
40
|
/** The daemon's own universe, resolved once and pinned on the child (config ⊕ state) — the harness isolates its own workers. */
|
|
40
41
|
export function universeLaunch(args: readonly string[], root: string = effectiveInstanceRoot()): { argv: string[]; env: NodeJS.ProcessEnv } {
|
|
41
|
-
return { argv: ['bin/elanous.mjs', '--config-dir', root, ...args], env: {
|
|
42
|
+
return { argv: ['bin/elanous.mjs', '--config-dir', root, ...args], env: {
|
|
43
|
+
...process.env, ELANOUS_STATE_DIR: root, ELANOUS_STATE_DIR_SOURCE: stateDirSourceForChild(root),
|
|
44
|
+
} };
|
|
42
45
|
}
|
|
43
46
|
const runCli = async (args: string[]): Promise<{ stdout: string }> => {
|
|
44
47
|
const { argv, env } = universeLaunch(args);
|
|
@@ -38,6 +38,7 @@ export interface DaemonPromptBody {
|
|
|
38
38
|
* (`none` · `readonly` · `chat` · `webterm`); invalid values reject
|
|
39
39
|
* the request rather than silently falling back. */
|
|
40
40
|
tools?: DaemonToolSurfaceKind;
|
|
41
|
+
personaId?: string;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export interface DaemonPromptRequest {
|
|
@@ -53,6 +54,7 @@ export interface DaemonPromptRequest {
|
|
|
53
54
|
* not opt in; the caller-side (`handlePromptStreamPost`) interprets
|
|
54
55
|
* null as "use the daemon's boot-time surface". */
|
|
55
56
|
tools: DaemonToolSurfaceKind | null;
|
|
57
|
+
personaId?: string;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
export type DaemonPromptRequestParseResult =
|
|
@@ -117,6 +119,7 @@ export function parseDaemonPromptBody(
|
|
|
117
119
|
body.source ? writeInputSourceMeta(body.source) : undefined,
|
|
118
120
|
),
|
|
119
121
|
tools: body.tools ?? null,
|
|
122
|
+
...(typeof body.personaId === 'string' && body.personaId.trim() ? { personaId: body.personaId } : {}),
|
|
120
123
|
},
|
|
121
124
|
};
|
|
122
125
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
appendUserPromptBlocksAndBuildMessages,
|
|
11
11
|
} from './daemon-history-helper.js';
|
|
12
12
|
import type { ContentBlock as AcpContentBlock } from '@agentclientprotocol/sdk';
|
|
13
|
-
import type
|
|
13
|
+
import { personaPromptForChat, type DaemonSessionHistory } from './daemon-runtime.js';
|
|
14
14
|
import type { DaemonPromptRequest } from './daemon-prompt-request.js';
|
|
15
15
|
import type { DaemonToolSurface } from './daemon-tools/types.js';
|
|
16
16
|
import type { ConfirmChannel } from '../hitl/confirm.js';
|
|
@@ -199,8 +199,9 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
199
199
|
// …" + active terminals) to the system prompt so the LLM has the
|
|
200
200
|
// session id + terminal ids without an extra discovery call. Helper
|
|
201
201
|
// returns the original prompt unchanged when there's nothing to add.
|
|
202
|
+
const personaPrompt = await personaPromptForChat(request.personaId);
|
|
202
203
|
const augmentedSystemPrompt = appendWebtermContext(
|
|
203
|
-
request.effectiveSystemPrompt,
|
|
204
|
+
personaPrompt ? [personaPrompt, request.effectiveSystemPrompt].filter(Boolean).join('\n\n') : request.effectiveSystemPrompt,
|
|
204
205
|
request.sessionId,
|
|
205
206
|
activeToolSurface,
|
|
206
207
|
);
|
|
@@ -291,6 +292,9 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
291
292
|
if (!isFirstTurn && opts.projectInstructions) {
|
|
292
293
|
messages.unshift({ role: 'system', content: opts.projectInstructions });
|
|
293
294
|
}
|
|
295
|
+
if (!isFirstTurn && personaPrompt) {
|
|
296
|
+
messages.unshift({ role: 'system', content: personaPrompt });
|
|
297
|
+
}
|
|
294
298
|
const result = await runCoreTurn({
|
|
295
299
|
sessionId: request.sessionId,
|
|
296
300
|
userText: request.userText,
|
|
@@ -55,6 +55,33 @@ import { elanousSelfAccessPrompt } from '../agent/self-ambient.js';
|
|
|
55
55
|
import { createToolCwdResolver, type ToolCwdResolver } from './tool-cwd.js';
|
|
56
56
|
import { resolveSessionProjectContext } from '../project/session-context.js';
|
|
57
57
|
import { debug } from '../debug/log.js';
|
|
58
|
+
import { resolvePersonaAddress } from '../intake-plane/persona-answer.js';
|
|
59
|
+
import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../persona/global-registry.js';
|
|
60
|
+
|
|
61
|
+
const turnPersonaPrompt = new AsyncLocalStorage<string | undefined>();
|
|
62
|
+
|
|
63
|
+
export function withChatPersonaPrompt<T>(prompt: string | undefined, run: () => T): T {
|
|
64
|
+
return turnPersonaPrompt.run(prompt, run);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function prependChatPersonaOnLaterTurn(
|
|
68
|
+
messages: LLMMessage[], isFirstTurn: boolean,
|
|
69
|
+
): LLMMessage[] {
|
|
70
|
+
const prompt = turnPersonaPrompt.getStore();
|
|
71
|
+
if (!isFirstTurn && prompt) messages.unshift({ role: 'system', content: prompt });
|
|
72
|
+
return messages;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function personaPromptForChat(
|
|
76
|
+
id: unknown,
|
|
77
|
+
deps: { load: () => Promise<unknown>; registry: () => Parameters<typeof resolvePersonaAddress>[1] } = {
|
|
78
|
+
load: awaitGlobalPersonaLoad, registry: getGlobalPersonaRegistry,
|
|
79
|
+
},
|
|
80
|
+
): Promise<string | undefined> {
|
|
81
|
+
if (typeof id !== 'string' || !id.trim()) return undefined;
|
|
82
|
+
await deps.load();
|
|
83
|
+
return resolvePersonaAddress(id, deps.registry())?.systemPrompt;
|
|
84
|
+
}
|
|
58
85
|
|
|
59
86
|
/** C4 (2026-07-12) — arm the non-detached-PTY kill ONCE per turn signal.
|
|
60
87
|
* Multiple tool calls in one turn share the same AbortSignal instance;
|
|
@@ -135,7 +162,7 @@ export function composeDaemonSystemPrompt(
|
|
|
135
162
|
promptMeta: Readonly<Record<string, unknown>> | undefined,
|
|
136
163
|
sessionId?: string,
|
|
137
164
|
): string {
|
|
138
|
-
return [basePrompt, buildDaemonInputSourceLine(promptMeta), elanousSelfAccessPrompt(sessionId)]
|
|
165
|
+
return [turnPersonaPrompt.getStore(), basePrompt, buildDaemonInputSourceLine(promptMeta), elanousSelfAccessPrompt(sessionId)]
|
|
139
166
|
.filter((part): part is string => typeof part === 'string' && part.trim().length > 0)
|
|
140
167
|
.join('\n\n');
|
|
141
168
|
}
|
|
@@ -604,12 +631,11 @@ export function createDaemonRunTurn(
|
|
|
604
631
|
const hasNonTextBlock = !!promptBlocks?.some(
|
|
605
632
|
(b) => (b as { type?: string }).type !== 'text',
|
|
606
633
|
);
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
return appendUserAndBuildMessages(history, sessionId, userText, systemPrompt);
|
|
634
|
+
const isFirstTurn = history.get(sessionId).length === 0;
|
|
635
|
+
const messages = hasNonTextBlock
|
|
636
|
+
? appendUserPromptBlocksAndBuildMessages(history, sessionId, promptBlocks!, systemPrompt)
|
|
637
|
+
: appendUserAndBuildMessages(history, sessionId, userText, systemPrompt);
|
|
638
|
+
return prependChatPersonaOnLaterTurn(messages, isFirstTurn);
|
|
613
639
|
},
|
|
614
640
|
getTools: () => surface.specs,
|
|
615
641
|
dispatchTool: terminalCapableDispatch(surfaceHasPtyShell, async (name, args, ctx) => {
|
|
@@ -723,15 +749,21 @@ export function createDaemonRunTurn(
|
|
|
723
749
|
});
|
|
724
750
|
debugBridge.activate();
|
|
725
751
|
}
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
752
|
+
const elanousMeta = turnCtx.promptMeta?.elanous;
|
|
753
|
+
const personaId = elanousMeta && typeof elanousMeta === 'object' && !Array.isArray(elanousMeta)
|
|
754
|
+
&& 'pwaPersonaId' in elanousMeta ? elanousMeta.pwaPersonaId : undefined;
|
|
755
|
+
const personaPrompt = await personaPromptForChat(personaId);
|
|
756
|
+
await withChatPersonaPrompt(personaPrompt, async () => {
|
|
757
|
+
const projectCwd = resolveSessionProjectContext(turnCtx.sessionId)?.cwd;
|
|
758
|
+
if (projectCwd || opts.acpSessionCwd) {
|
|
759
|
+
// An ACP session's explicit cwd wins; the project folder is only the default when none was given (IA3 review).
|
|
760
|
+
const explicitCwd = opts.acpSessionCwd && turnCtx.cwd ? turnCtx.cwd : undefined;
|
|
761
|
+
const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: explicitCwd ?? projectCwd ?? turnCtx.cwd });
|
|
762
|
+
await turnToolCwd.run(resolver, () => inner(turnCtx));
|
|
763
|
+
} else {
|
|
764
|
+
await inner(turnCtx);
|
|
765
|
+
}
|
|
766
|
+
});
|
|
735
767
|
} finally {
|
|
736
768
|
debugBridge?.dispose();
|
|
737
769
|
}
|
package/src/chat/index.ts
CHANGED
|
@@ -452,6 +452,7 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
452
452
|
{ name: 'reasoning', aliases: ['r', 'think'], description: 'Reasoning level (codex effort + summary, anthropic extended-thinking budget) — /reasoning [off|low|medium|high|xhigh] (cycle when no arg · xhigh 는 모델 상한이 xhigh 이상일 때만 wire 에 실린다, 아니면 high 로 깎인다)', subcommands: ['off', 'low', 'medium', 'high', 'xhigh'] },
|
|
453
453
|
{ name: 'local', aliases: ['ll'], description: 'Local OpenAI-compatible LLM — ping / models / test / use', subcommands: ['ping', 'models', 'test', 'use', 'status'] },
|
|
454
454
|
{ name: 'session', aliases: ['sess'], description: 'Session resume — list / load / sync / new (handoff from mobile)', subcommands: ['list', 'load', 'sync', 'new'] },
|
|
455
|
+
{ name: 'persona', aliases: [], description: '이 대화의 페르소나 보기·고르기·빼기 — /persona [이름|-]', subcommands: ['-'] },
|
|
455
456
|
{ name: 'fork', aliases: [], description: 'Copy this session into a new one' },
|
|
456
457
|
{ name: 'rewind', aliases: [], description: 'Rewind — 과거 user 턴 픽커로 되감기 (원본 보존 · 새 세션 분기 · /rewind <n> 숏컷)' },
|
|
457
458
|
// TUI 부활 C-a (2026-07-12): autopilot 미션 TUI 표면 — CLI 동등 단일 창구 소비.
|
|
@@ -463,6 +464,7 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
463
464
|
{ name: 'plugin', aliases: ['plugins'], description: 'Manage plugins', subcommands: ['list', 'activate', 'deactivate', 'reload'] },
|
|
464
465
|
{ name: 'widget', aliases: ['widgets'], description: 'Manage widgets', subcommands: ['list', 'reload', 'instances'] },
|
|
465
466
|
{ name: 'log', aliases: [], description: 'Chat Log controls — size / clear / filter / search / freeze / solo / turn / fold / help', subcommands: ['size', 'clear', 'filter', 'search', 'freeze', 'solo', 'turn', 'fold', 'help'] },
|
|
467
|
+
{ name: 'loops', aliases: [], description: '루프와 크론 상태 표 — /loops [owner]' },
|
|
466
468
|
{ name: 'memory', aliases: ['mem'], description: 'Memory ops — list / show / search / add / delete (see `elanous memory --help`)', subcommands: ['list', 'show', 'search', 'add', 'delete', 'index'] },
|
|
467
469
|
{ name: 'export', aliases: [], description: 'Export this conversation transcript to a markdown file — /export [path] (default ~/temp/elanous-transcript-<stamp>.md)' },
|
|
468
470
|
{ name: 'delta', aliases: ['diffs'], description: 'Source delta browser — open the latest turn-scoped file diff popup', subcommands: ['open', 'help'] },
|