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
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
2
4
|
import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
5
|
+
import { surfaceEventsDbPath } from '../domains/surface-events.js';
|
|
3
6
|
import { listCoordEvents, type CoordEvent } from './coord-events.js';
|
|
4
7
|
|
|
5
8
|
export interface MemoryItem {
|
|
@@ -27,15 +30,50 @@ export interface MemorySummary {
|
|
|
27
30
|
claim?: { key: string; value: string };
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
type CondenseEvent = CoordEvent & { surface?: string };
|
|
34
|
+
|
|
30
35
|
export interface MemoryDeps {
|
|
31
36
|
summarize: (source: MemorySource) => Promise<MemorySummary>;
|
|
32
|
-
events?: (since: string) =>
|
|
37
|
+
events?: (since: string) => CondenseEvent[];
|
|
33
38
|
decisions?: () => DecisionEntry[];
|
|
34
39
|
}
|
|
35
40
|
|
|
41
|
+
export type CondenseSkipReason = 'no-seat' | 'no-project' | 'no-topic' | 'no-summary' | 'bad-link' | 'bad-claim' | 'no-claim' | 'summarize-failed';
|
|
42
|
+
export type CondenseSkipped = Partial<Record<CondenseSkipReason, number>>;
|
|
43
|
+
export interface FunnelCount { total: number; bySeat: Record<string, number> }
|
|
44
|
+
export interface CondenseFunnel {
|
|
45
|
+
read: FunnelCount & { bySurface: Record<string, number> };
|
|
46
|
+
sources: FunnelCount & { folded: FunnelCount; droppedHarnessChild: FunnelCount; noSeat: FunnelCount };
|
|
47
|
+
summarized: FunnelCount & { accepted: FunnelCount; summarizeFailed: FunnelCount;
|
|
48
|
+
skipped: Partial<Record<CondenseSkipReason, FunnelCount>> };
|
|
49
|
+
collapsed: FunnelCount;
|
|
50
|
+
cards: FunnelCount & { carried: FunnelCount; supersededByPrevious: FunnelCount };
|
|
51
|
+
}
|
|
52
|
+
export interface CondenseWindowReport {
|
|
53
|
+
cards: MemoryItem[];
|
|
54
|
+
funnel: CondenseFunnel;
|
|
55
|
+
skipped: CondenseSkipped;
|
|
56
|
+
folded: number;
|
|
57
|
+
droppedHarnessChild: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
36
60
|
const DAY_MS = 86_400_000;
|
|
37
61
|
const oneLine = (text: string) => redactSecretText(text.split(/\r?\n/, 1)[0] ?? '').trim();
|
|
38
62
|
|
|
63
|
+
/** Keep the reader's event selection unchanged; attach surfaces from the same read-only snapshot. */
|
|
64
|
+
export function readCondenseEvents(since: string): CondenseEvent[] {
|
|
65
|
+
const path = surfaceEventsDbPath();
|
|
66
|
+
if (!existsSync(path)) return [];
|
|
67
|
+
const db = new Database(path, { readonly: true, strict: true });
|
|
68
|
+
try {
|
|
69
|
+
const surfaces = db.prepare(`SELECT id, surface FROM events
|
|
70
|
+
WHERE surface IN ('coord:channel', 'context:external', 'context:session') AND direction='outbound' AND ts>=?`)
|
|
71
|
+
.all(since) as Array<{ id: string; surface: string }>;
|
|
72
|
+
const byEvent = new Map(surfaces.map(row => [row.id, row.surface]));
|
|
73
|
+
return listCoordEvents({ since }, { db }).map(event => ({ ...event, surface: byEvent.get(event.id) }));
|
|
74
|
+
} finally { db.close(); }
|
|
75
|
+
}
|
|
76
|
+
|
|
39
77
|
/** Condense one UTC day; callers persist the returned snapshot, not raw transcripts. Read-only ledger access. */
|
|
40
78
|
export async function condenseContextDay(
|
|
41
79
|
day: string, previous: readonly MemoryItem[], deps: MemoryDeps, now: Date = new Date(),
|
|
@@ -43,47 +81,176 @@ export async function condenseContextDay(
|
|
|
43
81
|
if (!/^\d{4}-\d\d-\d\d$/.test(day) || new Date(`${day}T00:00:00.000Z`).toISOString().slice(0, 10) !== day) {
|
|
44
82
|
throw new Error('day must be a valid UTC YYYY-MM-DD');
|
|
45
83
|
}
|
|
46
|
-
|
|
84
|
+
return condenseContextWindow(`${day}T00:00:00.000Z`, new Date(Date.parse(`${day}T00:00:00.000Z`) + DAY_MS).toISOString(), previous, deps, now);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Read-only condensation over an exact rolling UTC window; the caller owns any persistence. */
|
|
88
|
+
export async function condenseContextWindow(
|
|
89
|
+
since: string, until: string, previous: readonly MemoryItem[], deps: MemoryDeps, now: Date = new Date(),
|
|
90
|
+
): Promise<MemoryItem[]> {
|
|
91
|
+
return (await condenseContextWindowWithReport(since, until, previous, deps, now)).cards;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function condenseContextWindowWithReport(
|
|
95
|
+
since: string, until: string, previous: readonly MemoryItem[], deps: MemoryDeps, now: Date = new Date(),
|
|
96
|
+
): Promise<CondenseWindowReport> {
|
|
47
97
|
const start = Date.parse(since);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
98
|
+
const end = Date.parse(until);
|
|
99
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) throw new Error('invalid context window');
|
|
100
|
+
// Fetch the previous local day as well: the store compares timestamp text rather than instants.
|
|
101
|
+
const events = (deps.events ?? readCondenseEvents)(new Date(start - DAY_MS).toISOString());
|
|
51
102
|
const decisions = (deps.decisions ?? (() => new DecisionLedger().list({ status: 'all' })))();
|
|
103
|
+
const inWindow = (at: string) => {
|
|
104
|
+
const time = Date.parse(at);
|
|
105
|
+
return Number.isFinite(time) && time >= start && time < end;
|
|
106
|
+
};
|
|
107
|
+
const count = (): FunnelCount => ({ total: 0, bySeat: {} });
|
|
108
|
+
const bump = (bucket: FunnelCount, seat: string | undefined) => {
|
|
109
|
+
const key = seat || '(unknown)';
|
|
110
|
+
bucket.total++;
|
|
111
|
+
bucket.bySeat[key] = (bucket.bySeat[key] ?? 0) + 1;
|
|
112
|
+
};
|
|
113
|
+
const funnel: CondenseFunnel = {
|
|
114
|
+
read: { ...count(), bySurface: {} },
|
|
115
|
+
sources: { ...count(), folded: count(), droppedHarnessChild: count(), noSeat: count() },
|
|
116
|
+
summarized: { ...count(), accepted: count(), summarizeFailed: count(), skipped: {} },
|
|
117
|
+
collapsed: count(), cards: { ...count(), carried: count(), supersededByPrevious: count() },
|
|
118
|
+
};
|
|
119
|
+
const harnessRuns: Array<{ events: CoordEvent[]; locators: Set<string> }> = [];
|
|
120
|
+
const earlierStarts: CoordEvent[] = [];
|
|
121
|
+
const otherEvents: CoordEvent[] = [];
|
|
122
|
+
let harnessEvents = 0;
|
|
123
|
+
let droppedHarnessChild = 0;
|
|
124
|
+
for (const event of events) {
|
|
125
|
+
if (!inWindow(event.at)) {
|
|
126
|
+
const time = Date.parse(event.at);
|
|
127
|
+
if (event.kind === 'started' && event.refs.seat !== 'harness-child'
|
|
128
|
+
&& Number.isFinite(time) && time >= start - DAY_MS && time < start) {
|
|
129
|
+
earlierStarts.push(event);
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
bump(funnel.read, event.refs.seat);
|
|
134
|
+
const surface = event.surface ?? '(unknown)';
|
|
135
|
+
funnel.read.bySurface[surface] = (funnel.read.bySurface[surface] ?? 0) + 1;
|
|
136
|
+
if (event.refs.seat === 'harness-child' && event.kind !== '보고') {
|
|
137
|
+
droppedHarnessChild++;
|
|
138
|
+
bump(funnel.sources.droppedHarnessChild, event.refs.seat);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const isLifecycle = event.kind === 'started' || event.kind === 'finished';
|
|
142
|
+
if (!isLifecycle) {
|
|
143
|
+
otherEvents.push(event);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
harnessEvents++;
|
|
147
|
+
const locators = new Set([event.refs.source, event.refs.url].filter((ref): ref is string => !!ref));
|
|
148
|
+
const group = { events: [event], locators };
|
|
149
|
+
// Either locator can identify the run, including a bridge through a third event.
|
|
150
|
+
for (let i = 0; i < harnessRuns.length;) {
|
|
151
|
+
const prior = harnessRuns[i]!;
|
|
152
|
+
if (locators.size && [...prior.locators].some(ref => locators.has(ref))) {
|
|
153
|
+
group.events.push(...prior.events);
|
|
154
|
+
for (const ref of prior.locators) locators.add(ref);
|
|
155
|
+
harnessRuns.splice(i, 1);
|
|
156
|
+
i = 0;
|
|
157
|
+
} else i++;
|
|
158
|
+
}
|
|
159
|
+
harnessRuns.push(group);
|
|
160
|
+
}
|
|
161
|
+
const eventSource = (event: CoordEvent): MemorySource => ({ kind: 'event', at: event.at, seat: event.refs.seat,
|
|
162
|
+
text: event.summary, source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}` });
|
|
163
|
+
const foldedSources: MemorySource[] = [];
|
|
164
|
+
for (const group of harnessRuns) {
|
|
165
|
+
group.events.sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.id.localeCompare(b.id));
|
|
166
|
+
const finish = group.events.filter(event => event.kind === 'finished').at(-1);
|
|
167
|
+
const inWindowStart = group.events.find(event => event.kind === 'started');
|
|
168
|
+
const begin = inWindowStart ?? (finish ? earlierStarts.filter(event =>
|
|
169
|
+
(group.locators.has(event.refs.source ?? '') || group.locators.has(event.refs.url ?? '')))
|
|
170
|
+
.sort((a, b) => Date.parse(b.at) - Date.parse(a.at)).at(0) : undefined);
|
|
171
|
+
const winner = finish ?? inWindowStart ?? group.events.at(-1)!;
|
|
172
|
+
for (const event of group.events) if (event !== winner) bump(funnel.sources.folded, event.refs.seat);
|
|
173
|
+
const frequency = (ref: string) => group.events.filter(event => event.refs.source === ref || event.refs.url === ref).length;
|
|
174
|
+
const run = [...group.locators].sort((a, b) => frequency(b) - frequency(a))[0] ?? eventSource(winner).source;
|
|
175
|
+
const duration = finish && begin && Date.parse(finish.at) >= Date.parse(begin.at)
|
|
176
|
+
? `${Math.floor((Date.parse(finish.at) - Date.parse(begin.at)) / 60_000)}m ${Math.floor(((Date.parse(finish.at) - Date.parse(begin.at)) % 60_000) / 1_000)}s`
|
|
177
|
+
: '알 수 없음';
|
|
178
|
+
const result = finish ? oneLine(finish.summary).replace(/^Harness child finished:\s*/i, '') || '종료'
|
|
179
|
+
: '진행 중';
|
|
180
|
+
foldedSources.push({ ...eventSource(winner), seat: winner.refs.seat || begin?.refs.seat || '',
|
|
181
|
+
source: run, text: `${run} ${result} · ${duration}` });
|
|
182
|
+
}
|
|
183
|
+
const folded = harnessEvents - foldedSources.length;
|
|
184
|
+
try { debug.log('context.condense', 'folded', { harnessEvents, kept: foldedSources.length, droppedHarnessChild }); }
|
|
185
|
+
catch { /* Observation must not stop condensation. */ }
|
|
52
186
|
const sources: MemorySource[] = [
|
|
53
|
-
...
|
|
54
|
-
text: event.summary, source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}` })),
|
|
187
|
+
...otherEvents.map(eventSource), ...foldedSources,
|
|
55
188
|
...decisions.map(decision => ({ kind: 'decision' as const,
|
|
56
189
|
at: decision.decidedAt ?? decision.raisedAt ?? decision.importedAt ?? '',
|
|
57
190
|
seat: decision.raisedBy.track ?? 'OP',
|
|
58
191
|
text: decision.status === 'decided' ? `${decision.title}: ${decision.options.find(o => o.key === decision.choice)?.label ?? decision.note ?? decision.scqa.a ?? '결정됨'}` : `${decision.title}: ${decision.status}`,
|
|
59
192
|
source: `elanous://decisions/${encodeURIComponent(decision.id)}` })),
|
|
60
|
-
].filter(source =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
193
|
+
].filter(source => inWindow(source.at))
|
|
194
|
+
.sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.source.localeCompare(b.source));
|
|
195
|
+
|
|
196
|
+
for (const source of sources) {
|
|
197
|
+
if (typeof source.seat !== 'string' || !oneLine(source.seat)) bump(funnel.sources.noSeat, source.seat);
|
|
198
|
+
else bump(funnel.sources, source.seat);
|
|
199
|
+
}
|
|
200
|
+
for (const decision of decisions) {
|
|
201
|
+
const at = decision.decidedAt ?? decision.raisedAt ?? decision.importedAt ?? '';
|
|
202
|
+
if (!inWindow(at)) continue;
|
|
203
|
+
bump(funnel.read, decision.raisedBy.track ?? 'OP');
|
|
204
|
+
funnel.read.bySurface['decision:ledger'] = (funnel.read.bySurface['decision:ledger'] ?? 0) + 1;
|
|
205
|
+
}
|
|
64
206
|
|
|
65
207
|
const items = new Map<string, MemoryItem>();
|
|
208
|
+
const skipped: CondenseSkipped = {};
|
|
209
|
+
let kept = 0;
|
|
210
|
+
const skip = (reason: CondenseSkipReason, source: MemorySource) => {
|
|
211
|
+
skipped[reason] = (skipped[reason] ?? 0) + 1;
|
|
212
|
+
bump(funnel.summarized.skipped[reason] ??= count(), source.seat);
|
|
213
|
+
if (reason === 'summarize-failed') bump(funnel.summarized.summarizeFailed, source.seat);
|
|
214
|
+
try {
|
|
215
|
+
debug.log('context.condense', 'source-skipped', { reason, kind: source.kind, at: source.at });
|
|
216
|
+
if (reason === 'no-claim') debug.log('context.condense', 'skipped', { reason, source: source.source });
|
|
217
|
+
} catch { /* Observation must not stop condensation. */ }
|
|
218
|
+
};
|
|
219
|
+
const safeLine = (value: unknown) => typeof value === 'string' ? oneLine(value) : '';
|
|
66
220
|
const keyFor = (item: Pick<MemoryItem, 'project' | 'seat' | 'topic'>) => JSON.stringify([item.project, item.seat, item.topic]);
|
|
67
221
|
for (const item of previous) items.set(keyFor(item), { ...item });
|
|
222
|
+
const candidateKeys = new Set<string>();
|
|
223
|
+
const updatedKeys = new Set<string>();
|
|
68
224
|
for (const source of sources) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
225
|
+
const seat = safeLine(source.seat);
|
|
226
|
+
if (!seat) { skip('no-seat', source); continue; }
|
|
227
|
+
let summary: MemorySummary;
|
|
228
|
+
try { summary = await deps.summarize(source); }
|
|
229
|
+
catch { skip('summarize-failed', source); continue; }
|
|
230
|
+
bump(funnel.summarized, source.seat);
|
|
231
|
+
const project = safeLine(summary?.project);
|
|
232
|
+
const topic = safeLine(summary?.topic);
|
|
233
|
+
const text = safeLine(summary?.summary);
|
|
234
|
+
const link = safeLine(source.source);
|
|
235
|
+
if (!project) { skip('no-project', source); continue; }
|
|
236
|
+
if (!topic) { skip('no-topic', source); continue; }
|
|
237
|
+
if (!text) { skip('no-summary', source); continue; }
|
|
238
|
+
if (!/^(?:https?:\/\/|elanous:\/\/)[^\s]+$/.test(link)) { skip('bad-link', source); continue; }
|
|
239
|
+
const claim = summary.claim && { key: safeLine(summary.claim.key), value: safeLine(summary.claim.value) };
|
|
240
|
+
if (claim && (!claim.key || !claim.value)) { skip('bad-claim', source); continue; }
|
|
241
|
+
if (source.kind === 'event' && !claim) { skip('no-claim', source); continue; }
|
|
242
|
+
kept++;
|
|
243
|
+
bump(funnel.summarized.accepted, source.seat);
|
|
80
244
|
const key = keyFor({ project, seat, topic });
|
|
245
|
+
if (candidateKeys.has(key)) bump(funnel.collapsed, source.seat);
|
|
246
|
+
else candidateKeys.add(key);
|
|
81
247
|
const old = items.get(key);
|
|
82
248
|
// Equal timestamps are resolved by the source link, so shuffled input does not change the winner.
|
|
83
249
|
if (old && (Date.parse(old.updatedAt) > Date.parse(source.at)
|
|
84
250
|
|| (Date.parse(old.updatedAt) === Date.parse(source.at) && old.source >= link))) continue;
|
|
85
251
|
items.set(key, { project, seat, topic, summary: text, source: link, updatedAt: source.at,
|
|
86
252
|
status: 'active', ...(claim ? { claim } : {}) });
|
|
253
|
+
updatedKeys.add(key);
|
|
87
254
|
}
|
|
88
255
|
const cutoff = now.getTime() - 30 * DAY_MS;
|
|
89
256
|
// Compare only the winning, non-retired assertions; a superseded claim cannot keep a decision candidate alive.
|
|
@@ -103,6 +270,16 @@ export async function condenseContextDay(
|
|
|
103
270
|
finalItems[index] = { ...item, conflict: { owner: 'OP', sources: [conflicting.source, item.source] } };
|
|
104
271
|
}
|
|
105
272
|
}
|
|
106
|
-
|
|
273
|
+
const cards = finalItems.sort((a, b) => a.project.localeCompare(b.project) || a.seat.localeCompare(b.seat)
|
|
107
274
|
|| a.topic.localeCompare(b.topic));
|
|
275
|
+
for (const card of cards) {
|
|
276
|
+
bump(funnel.cards, card.seat);
|
|
277
|
+
if (!candidateKeys.has(keyFor(card))) bump(funnel.cards.carried, card.seat);
|
|
278
|
+
else if (!updatedKeys.has(keyFor(card))) bump(funnel.cards.supersededByPrevious, card.seat);
|
|
279
|
+
}
|
|
280
|
+
try { debug.log('context.condense', 'window', { sources: sources.length, kept, skipped }); }
|
|
281
|
+
catch { /* Observation must not stop condensation. */ }
|
|
282
|
+
try { debug.log('context.condense', 'funnel', funnel); }
|
|
283
|
+
catch { /* Observation must not stop condensation. */ }
|
|
284
|
+
return { cards, skipped, folded, droppedHarnessChild, funnel };
|
|
108
285
|
}
|
|
@@ -64,7 +64,7 @@ function storedItems(root: string): MemoryItem[] {
|
|
|
64
64
|
return items;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
async function summarize(source: MemorySource, injected?: Record<string, MemorySummary>): Promise<MemorySummary> {
|
|
67
|
+
export async function summarize(source: MemorySource, injected?: Record<string, MemorySummary>): Promise<MemorySummary> {
|
|
68
68
|
if (injected) {
|
|
69
69
|
const result = injected[source.source];
|
|
70
70
|
if (!result) throw new Error(`missing test summary: ${source.source}`);
|
package/src/dashboard/index.ts
CHANGED
|
@@ -593,6 +593,8 @@ import { resolveDashboardChatMainSubmitIntent } from './input/chat-main-submit-r
|
|
|
593
593
|
import { maybeEmitDashboardSubmitQuickPass } from './input/chat-main-submit-control.js';
|
|
594
594
|
import { attachDashboardQuickPassConsumers } from './input/control-signal-consumers.js';
|
|
595
595
|
import { resolveDashboardChatMainSlashCommand } from './input/chat-main-slash-command.js';
|
|
596
|
+
import { TuiChatPersonaSelection, tuiChatPersonaMessages } from './slash-runtime/chat-persona.js';
|
|
597
|
+
import { awaitGlobalPersonaLoad } from '../persona/global-registry.js';
|
|
596
598
|
import { resolveDashboardChatMainCacheCommand } from './input/chat-main-cache-command.js';
|
|
597
599
|
import {
|
|
598
600
|
dashboardDeltaHelpLines,
|
|
@@ -956,6 +958,8 @@ import {
|
|
|
956
958
|
resetDashboardAcpTurnRef,
|
|
957
959
|
} from './turn-lifecycle-runtime.js';
|
|
958
960
|
import { runDashboardTurnPrelude } from './turn-prelude-runtime.js';
|
|
961
|
+
import { askSeat, deliverSeatAnswers, getTuiSeatAskClientId, parseSeatAsk } from '../seat-dispatch/seat-ask.js';
|
|
962
|
+
import { ceoTaskDeps } from '../seat-dispatch/ceo-intent.js';
|
|
959
963
|
import {
|
|
960
964
|
commitDashboardAssistantRenderState,
|
|
961
965
|
runDashboardTurnTailAutoCopy,
|
|
@@ -2136,6 +2140,7 @@ export function renderDashboardFirstScreenBand(input: {
|
|
|
2136
2140
|
}
|
|
2137
2141
|
|
|
2138
2142
|
export async function showDashboard(opts: ShowDashboardOptions = {}): Promise<DashboardAction> {
|
|
2143
|
+
await awaitGlobalPersonaLoad().catch(() => {});
|
|
2139
2144
|
const dashboardQuitConfirmationState = createQuitConfirmationState();
|
|
2140
2145
|
const signalQuitConfirmationState = createQuitConfirmationState();
|
|
2141
2146
|
let disposeDashboardEventLoopMonitor = (): void => {};
|
|
@@ -2639,6 +2644,19 @@ When a user's request matches an installed skill (they will see a "hint: /run-sk
|
|
|
2639
2644
|
Mode- and sync-specific instructions are injected per-turn when relevant — do not assume sync/diff context unless the current turn's Context: block explicitly mentions them.`,
|
|
2640
2645
|
);
|
|
2641
2646
|
let chatLines: string[] = []; // chat log — increasingly reserved for transcript / LLM speech
|
|
2647
|
+
const tuiSeatAskClientId = getTuiSeatAskClientId();
|
|
2648
|
+
const tuiSeatAskDeps = {
|
|
2649
|
+
channel: 'tui' as const, clientId: tuiSeatAskClientId,
|
|
2650
|
+
send: async (_origin: import('../seat-dispatch/seat-ask.js').AskOrigin, answer: string) => {
|
|
2651
|
+
chatLines.push(C.info(answer));
|
|
2652
|
+
chatScrollOffset = -1;
|
|
2653
|
+
draw();
|
|
2654
|
+
},
|
|
2655
|
+
};
|
|
2656
|
+
const pollTuiSeatAnswers = (): void => {
|
|
2657
|
+
void deliverSeatAnswers(tuiSeatAskDeps).catch((error) => debug.log('seat.ask', 'delivery-failed', { via: 'tui', error: String(error) }, { level: 'warn' }));
|
|
2658
|
+
};
|
|
2659
|
+
let tuiSeatAskTimer: ReturnType<typeof setInterval> | undefined;
|
|
2642
2660
|
let debugLines: string[] = [
|
|
2643
2661
|
C.muted('Dashboard ready. Press / for slash, Ctrl+L for plain input.'),
|
|
2644
2662
|
C.muted('Debug window ready. Use /debug window open.'),
|
|
@@ -3121,6 +3139,9 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
3121
3139
|
// the laptop left off. `/telegram attach` creates this, `/telegram
|
|
3122
3140
|
// detach` clears it. Lives for the dashboard lifetime.
|
|
3123
3141
|
let attachedSessionId: string | null = null;
|
|
3142
|
+
const chatPersonaSelection = new TuiChatPersonaSelection();
|
|
3143
|
+
let chatPersonaConversationId = crypto.randomUUID();
|
|
3144
|
+
const currentChatPersonaSessionId = () => attachedSessionId ?? chatPersonaConversationId;
|
|
3124
3145
|
let attachedChatId: number | null = null;
|
|
3125
3146
|
const forkableSessionHistory = (source: ChatMessage[] = chat.history): ForkableSessionTurn[] =>
|
|
3126
3147
|
flattenForkableSessionHistory(source);
|
|
@@ -3134,7 +3155,9 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
3134
3155
|
messages: forkableSessionHistory(),
|
|
3135
3156
|
});
|
|
3136
3157
|
const prev = attachedSessionId;
|
|
3158
|
+
const selectedPersona = chatPersonaSelection.get(currentChatPersonaSessionId());
|
|
3137
3159
|
attachedSessionId = forked.meta.id;
|
|
3160
|
+
if (selectedPersona) chatPersonaSelection.set(forked.meta.id, selectedPersona);
|
|
3138
3161
|
try { _setActive(forked.meta.id); } catch { /* best-effort */ }
|
|
3139
3162
|
chatLines.push('');
|
|
3140
3163
|
chatLines.push(prev
|
|
@@ -3174,7 +3197,9 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
3174
3197
|
messages: forkableSessionHistory(truncatedChat),
|
|
3175
3198
|
});
|
|
3176
3199
|
const prev = attachedSessionId;
|
|
3200
|
+
const selectedPersona = chatPersonaSelection.get(currentChatPersonaSessionId());
|
|
3177
3201
|
attachedSessionId = forked.meta.id;
|
|
3202
|
+
if (selectedPersona) chatPersonaSelection.set(forked.meta.id, selectedPersona);
|
|
3178
3203
|
try { setActiveForTimetravel(forked.meta.id); } catch { /* best-effort */ }
|
|
3179
3204
|
// in-memory 히스토리도 동일 경계로 절단 — 스토어와 문맥 일치 보장.
|
|
3180
3205
|
chat.history.length = 0;
|
|
@@ -15522,20 +15547,23 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
15522
15547
|
rich: false,
|
|
15523
15548
|
})
|
|
15524
15549
|
: [];
|
|
15525
|
-
return
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
|
|
15531
|
-
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15550
|
+
return [
|
|
15551
|
+
...tuiChatPersonaMessages(currentChatPersonaSessionId(), chatPersonaSelection),
|
|
15552
|
+
...buildDashboardTurnPreamble({
|
|
15553
|
+
userText,
|
|
15554
|
+
sessionId,
|
|
15555
|
+
cwd: getSessionCwd(),
|
|
15556
|
+
turnProfile: acpTurnRef.turnProfile,
|
|
15557
|
+
userConfig: getUserConfig(),
|
|
15558
|
+
// Resolved per-turn so a mid-session model switch (codex →
|
|
15559
|
+
// claude or vice-versa) takes effect immediately. Drives the
|
|
15560
|
+
// codex-only behavioral addendum (fix L-1) inside the
|
|
15561
|
+
// universal preamble.
|
|
15562
|
+
modelFamily: getModelFamily(inspectActiveProvider().model),
|
|
15563
|
+
rich: false,
|
|
15564
|
+
enabledTools: tools.map(t => t.name),
|
|
15565
|
+
}),
|
|
15566
|
+
];
|
|
15539
15567
|
},
|
|
15540
15568
|
getTools: ({ userText }) => {
|
|
15541
15569
|
const runtime = acpToolRuntime;
|
|
@@ -15819,6 +15847,9 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
15819
15847
|
observe: (data) => { try { debug.log('dashboard.first-screen-band', 'resolved', data); } catch { /* observation is best-effort */ } },
|
|
15820
15848
|
});
|
|
15821
15849
|
|
|
15850
|
+
tuiSeatAskTimer = setInterval(pollTuiSeatAnswers, 10_000);
|
|
15851
|
+
tuiSeatAskTimer.unref();
|
|
15852
|
+
pollTuiSeatAnswers();
|
|
15822
15853
|
while (true) {
|
|
15823
15854
|
draw();
|
|
15824
15855
|
let wdInputExited = false; // set true when the input-mode loop exits this iter
|
|
@@ -17571,6 +17602,18 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
17571
17602
|
const cmdText = submitIntent.kind === 'control-turn'
|
|
17572
17603
|
? (submitIntent.commandText ?? '')
|
|
17573
17604
|
: submitIntent.text;
|
|
17605
|
+
if (submitIntent.kind === 'submit-turn' && parseSeatAsk(submitIntent.text)) {
|
|
17606
|
+
try {
|
|
17607
|
+
const receipt = await askSeat(submitIntent.text, { channel: 'tui', clientId: tuiSeatAskClientId },
|
|
17608
|
+
ceoTaskDeps(getUserConfig(), null), tuiSeatAskDeps);
|
|
17609
|
+
chatLines.push(C.info(receipt));
|
|
17610
|
+
} catch (error) {
|
|
17611
|
+
chatLines.push(C.error(`CTO 질문 전송 실패: ${String(error)}`));
|
|
17612
|
+
}
|
|
17613
|
+
chatScrollOffset = -1;
|
|
17614
|
+
draw();
|
|
17615
|
+
continue;
|
|
17616
|
+
}
|
|
17574
17617
|
if (submitIntent.kind === 'submit-turn' && submitIntent.route === 'sticky-acp') {
|
|
17575
17618
|
await runDashboardChatMainSubmitIntent({
|
|
17576
17619
|
submit: createDashboardChatMainTurnSubmit(submitIntent),
|
|
@@ -18198,6 +18241,11 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
18198
18241
|
},
|
|
18199
18242
|
getAttachedSessionId: () => attachedSessionId,
|
|
18200
18243
|
setAttachedSessionId: (id) => { attachedSessionId = id; },
|
|
18244
|
+
chatPersona: {
|
|
18245
|
+
sessionId: currentChatPersonaSessionId,
|
|
18246
|
+
selection: chatPersonaSelection,
|
|
18247
|
+
newConversation: () => { chatPersonaConversationId = crypto.randomUUID(); },
|
|
18248
|
+
},
|
|
18201
18249
|
getAttachedChatId: () => attachedChatId,
|
|
18202
18250
|
setAttachedChatId: (id) => { attachedChatId = id; },
|
|
18203
18251
|
sessionSlash: {
|
|
@@ -19010,14 +19058,17 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
19010
19058
|
rich: false,
|
|
19011
19059
|
})
|
|
19012
19060
|
: [];
|
|
19013
|
-
return
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19018
|
-
|
|
19019
|
-
|
|
19020
|
-
|
|
19061
|
+
return [
|
|
19062
|
+
...tuiChatPersonaMessages(currentChatPersonaSessionId(), chatPersonaSelection),
|
|
19063
|
+
...buildDashboardTurnPreamble({
|
|
19064
|
+
userText: args.userText,
|
|
19065
|
+
cwd: args.cwd,
|
|
19066
|
+
turnProfile: args.turnProfile as SessionTurnProfile,
|
|
19067
|
+
userConfig: args.userConfig,
|
|
19068
|
+
rich: false,
|
|
19069
|
+
enabledTools: tools.map(t => t.name),
|
|
19070
|
+
}),
|
|
19071
|
+
];
|
|
19021
19072
|
},
|
|
19022
19073
|
runAutoCompact: async ({ preamble, chatHistory, userMsg }) => {
|
|
19023
19074
|
const compactMod = await import('../compact/index.js');
|
|
@@ -19427,5 +19478,7 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
19427
19478
|
} catch (err) {
|
|
19428
19479
|
closeDashboardTui();
|
|
19429
19480
|
throw err;
|
|
19481
|
+
} finally {
|
|
19482
|
+
if (tuiSeatAskTimer) clearInterval(tuiSeatAskTimer);
|
|
19430
19483
|
}
|
|
19431
19484
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../../persona/global-registry.js';
|
|
2
|
+
import { resolvePersonaAddress } from '../../intake-plane/persona-answer.js';
|
|
3
|
+
import { loadSession, updateSessionMeta } from '../../session/index.js';
|
|
4
|
+
import { assemblePersonaPrompt } from '../../persona/prompt-assembler.js';
|
|
5
|
+
import type { LLMMessage } from '../../llm.js';
|
|
6
|
+
|
|
7
|
+
/** Unattached conversations use a dashboard-local id; attached sessions use persisted metadata. */
|
|
8
|
+
export class TuiChatPersonaSelection {
|
|
9
|
+
private readonly selected = new Map<string, string>();
|
|
10
|
+
|
|
11
|
+
get(sessionId: string): string | undefined {
|
|
12
|
+
return loadSession(sessionId)?.meta.chatPersonaId ?? this.selected.get(sessionId);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
set(sessionId: string, personaId: string | undefined): void {
|
|
16
|
+
const meta = updateSessionMeta(sessionId, (m) => {
|
|
17
|
+
if (personaId) m.chatPersonaId = personaId;
|
|
18
|
+
else delete m.chatPersonaId;
|
|
19
|
+
});
|
|
20
|
+
if (!meta) {
|
|
21
|
+
if (personaId) this.selected.set(sessionId, personaId);
|
|
22
|
+
else this.selected.delete(sessionId);
|
|
23
|
+
} else {
|
|
24
|
+
this.selected.delete(sessionId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function handleTuiChatPersona(
|
|
30
|
+
args: readonly string[], sessionId: string,
|
|
31
|
+
selection: TuiChatPersonaSelection,
|
|
32
|
+
): Promise<string> {
|
|
33
|
+
if (args[0] === '-') {
|
|
34
|
+
if (args.length !== 1) return '쓰는 법: /persona [이름|-]';
|
|
35
|
+
selection.set(sessionId, undefined);
|
|
36
|
+
return '이 대화의 페르소나를 뺐습니다';
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
await awaitGlobalPersonaLoad();
|
|
40
|
+
const registry = getGlobalPersonaRegistry();
|
|
41
|
+
if (!args.length) {
|
|
42
|
+
const selected = selection.get(sessionId);
|
|
43
|
+
const personas = registry.list().sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
44
|
+
const current = personas.find(p => p.personaId === selected);
|
|
45
|
+
return `이 대화의 페르소나: ${current ? `${current.displayName} (${current.personaId})` : '없음'}\n고를 수 있는 페르소나: ${personas.map(p => `${p.displayName} (${p.personaId})${p.personaId === selected ? ' (지금)' : ''}`).join(' · ') || '없음'}\n고르기: /persona <이름> · 빼기: /persona -`;
|
|
46
|
+
}
|
|
47
|
+
const name = args.join(' ');
|
|
48
|
+
const persona = resolvePersonaAddress(name, registry);
|
|
49
|
+
if (!persona) return `그런 페르소나가 없습니다: ${name}`;
|
|
50
|
+
selection.set(sessionId, persona.personaId);
|
|
51
|
+
return `${persona.displayName} 페르소나를 이 대화에 골랐습니다`;
|
|
52
|
+
} catch {
|
|
53
|
+
return '페르소나 목록을 읽지 못했습니다';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function tuiChatPersonaMessages(
|
|
58
|
+
sessionId: string, selection: TuiChatPersonaSelection,
|
|
59
|
+
): LLMMessage[] {
|
|
60
|
+
const id = selection.get(sessionId);
|
|
61
|
+
if (!id) return [];
|
|
62
|
+
const persona = getGlobalPersonaRegistry().get(id);
|
|
63
|
+
if (!persona) return [];
|
|
64
|
+
const prompt = assemblePersonaPrompt(persona, '').systemPrompt;
|
|
65
|
+
return prompt ? [{ role: 'system', content: prompt }] : [];
|
|
66
|
+
}
|