elanous 0.2.13 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/LZcstaO9_NXypPFmujolv/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7334.a6679d9168f37aa8.js → 1268.0840ff91e083fcbd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-33ffcc49ab45123b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9656-c1540088f5859c80.js → 1844-9ec4b1d12f6e80eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{390.c373e31b3b9d0c41.js → 1948.15f356b15a625597.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4685-c3c1c625b71accd1.js → 4614-21403aac730d4586.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8039-df92e08fede5de8f.js → 4795-f372490b178583fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1452.93700483b9d4fc61.js → 6110.1297d4093fdfbb0d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6158.9c0449a9a8d0064b.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6877-7c6208705c284124.js +1 -0
- package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1829-b453a1b22d3999bb.js → 7327-2d69fb321ba73389.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8827-e2f5b09a8d37e83b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +25 -0
- package/apps/pwa/out/_next/static/chunks/{8421-1c4acfb1395a0edf.js → 8949-ecb4128a0858b911.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9103-7a3ae7f60af3b99f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3869-3cd46526879f454c.js → 9247-29d889b809288e65.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{79f8be9e-957d68913b590b08.js → a9f2b54d-7865aba0f4d2ee49.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-0e2c57fe6add4b2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e05a77df7e005b04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-f544338193a9a762.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5491c115b1f9a923.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b8c49f6b4fa2df91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-96398e364fbd4548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-976813c91d7394ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-28b9448091776c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1d4901eb7c2d8822.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-72d3e7ff35a8c954.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-60c7a8e1a4fe62ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-2a52b316cb143d9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c3ce483c8d5db370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-13c7b53e0c2519a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-96f074f6538e8a2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e97be5334d83a9f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-65e484302921a932.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-34d08facaf08f556.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-955ec2da3be4c560.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-9f88fbc15d9058d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-c1343f9499d86f3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-8739a2e0ae793130.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-c9fc5706b8abaa11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-d23b12bb92242558.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8d47f45a0dc044ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c7fea475488201a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e2ee2896811e98d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-83b19dae8619de05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-5efbf81124c474ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f1a1fc0a82738c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-da6c08aae0f92768.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-06ee266953d9c879.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-153c2b3bcc89e8de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-87a11e6a05f15199.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-7d4182964407c09c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-0d6d23b40263a7ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-7e8c39241f8eb6d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-008c1a96618a4887.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-63d14a4d8fe1e1c1.js → page-f5597e894c02cd33.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-0337fdf7fb5e37b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-73735b64bfe1ae67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8fcec4c9ea2e7f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f7e631e9b4daf66e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-4881b8f9f63694b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-9817c7f9007466cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-97f9f43172a3a90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5cd7e3a9-404fd6b8d0ecd44c.js → f6231284-45726550aba08fca.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f48170cc-d05d28bf87a43bf4.js → f6b7c9ba.64a895b8b2fedbdc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-539cde99554be20f.js +1 -0
- package/apps/pwa/out/_next/static/css/1f7c958c41ffa3b9.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -0
- package/apps/pwa/out/ceo/index.txt +33 -0
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -0
- package/apps/pwa/out/loops/index.txt +30 -0
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/heal/heal-loop.yaml +1 -1
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/orchestrator/orchestrator.yaml +59 -0
- package/graphs/orchestrator/recipes.yaml +18 -0
- package/graphs/release/recipes.yaml +6 -0
- package/graphs/release/release-loop.yaml +6 -1
- package/graphs/rhythm/daily.yaml +38 -0
- package/graphs/rhythm/recipes.yaml +18 -0
- package/graphs/rhythm/weekly.yaml +39 -0
- package/graphs/video/recipes.yaml +3 -0
- package/graphs/video/youtube-summary.yaml +17 -0
- package/package.json +1 -1
- package/scripts/audit-test-state-writes.ts +72 -17
- package/scripts/brand/check.ts +188 -0
- package/scripts/ci-typecheck-changed.ts +50 -18
- package/scripts/coord-post.sh +11 -1
- package/scripts/docs/generate-graph-anatomy.ts +315 -0
- package/scripts/docs-cli-check.ts +23 -6
- package/scripts/expose-rubric-check.ts +118 -0
- package/scripts/expose-rubric-suggest.ts +169 -0
- package/scripts/heal/run-role.ts +14 -0
- package/scripts/hq/standby-verify.ts +11 -7
- package/scripts/lecture-note/node.ts +31 -11
- package/scripts/lessons/handbook-page.ts +112 -0
- package/scripts/marketing/generate-ax-brief.ts +140 -0
- package/scripts/marketing/generate-feature-map.ts +118 -0
- package/scripts/release-loop/checklist-gate-node.ts +53 -14
- package/scripts/release-loop/gate-node.ts +89 -14
- package/scripts/release-loop/publish-node.ts +14 -1
- package/scripts/release-loop/unattended-release.ts +23 -1
- package/scripts/release-loop/vault-note-node.ts +428 -0
- package/scripts/release-story/draft.ts +220 -0
- package/scripts/rhythm/daily.ts +570 -0
- package/scripts/rhythm/weekly.ts +315 -0
- package/scripts/skills/public-check.ts +169 -0
- package/scripts/smart-merge/resync-shadow.ts +147 -0
- package/scripts/test-deterministic.ts +4 -8
- package/scripts/test-diet/effectiveness.ts +195 -0
- package/scripts/test-diet/lib.ts +16 -8
- package/scripts/test-diet/node.ts +77 -9
- package/scripts/ux/demo-rehearsal.ts +2 -2
- package/scripts/ux/lib/rehearsal-verdict.ts +1 -0
- package/scripts/video/youtube-summary.ts +133 -0
- package/skills/diagram-master/SKILL.md +42 -49
- package/skills/diagram-master/references/pyproject.toml +4 -1
- package/skills/diagram-master/references/routing-guide.md +4 -2
- package/skills/grill-me/SKILL.md +1 -0
- package/skills/youtube-master/SKILL.md +13 -13
- package/skills/youtube-master/package-lock.json +0 -545
- package/skills/youtube-master/package.json +2 -5
- package/skills/youtube-master/scripts/main.ts +2 -2
- package/skills/youtube-master/scripts/transcribe-local.ts +1 -1
- package/skills/youtube-master/src/util.ts +30 -7
- package/src/agent-env/profile.ts +161 -0
- package/src/agent-mission/driver.ts +3 -3
- package/src/agent-substrate/pr-reviewer.ts +2 -0
- package/src/ask-user-question/pending-questions.ts +5 -0
- package/src/auth/github-app-token.ts +112 -13
- package/src/autopilot/build/llm-conflict-merge.ts +73 -10
- package/src/autopilot/build/merge-intent.ts +53 -0
- package/src/briefing/brief-items.ts +121 -0
- package/src/chat/index.ts +2 -0
- package/src/claims/claims-ledger.ts +232 -0
- package/src/claims/claims-render.ts +166 -0
- package/src/cli/agent-env-cli.ts +21 -0
- package/src/cli/claims-cli.ts +94 -0
- package/src/cli/decisions-cli.ts +44 -3
- package/src/cli/docs-cli.ts +2 -0
- package/src/cli/doctor-cli.ts +23 -1
- package/src/cli/doctor-node-modules.ts +147 -0
- package/src/cli/flow-cli.ts +11 -0
- package/src/cli/freeze-cli.ts +45 -0
- package/src/cli/intake-cli.ts +46 -17
- package/src/cli/lesson-cli.ts +108 -0
- package/src/cli/logs-cli.ts +104 -2
- package/src/cli/logs-model-input.ts +131 -0
- package/src/cli/pod-cli.ts +2 -0
- package/src/cli/pr-cli.ts +29 -1
- package/src/cli/private-ledger-commands.ts +54 -4
- package/src/cli/pty-drive-verdict.ts +11 -2
- package/src/cli/release-cli.ts +190 -33
- package/src/cli/rfc-status.ts +91 -0
- package/src/cli/seat-requests-cli.ts +52 -0
- package/src/connectors/linear.ts +5 -3
- package/src/context-bus/condense.ts +15 -20
- package/src/context-bus/context-now-public.ts +96 -0
- package/src/context-bus/context-now-surfaces.ts +55 -2
- package/src/context-bus/context-now.ts +6 -3
- package/src/context-bus/coord-events.ts +6 -4
- package/src/context-bus/long-term-memory.ts +92 -11
- package/src/dashboard/index.ts +75 -22
- package/src/dashboard/slash-runtime/chat-persona.ts +66 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +99 -0
- package/src/dashboard/slash-runtime/loops-table.ts +77 -0
- package/src/decisions/decision-cards.ts +33 -7
- package/src/decisions/decision-ledger.ts +40 -1
- package/src/decisions/proact-meter.ts +286 -0
- package/src/decisions/proact1-lite.ts +86 -0
- package/src/decisions/web-push-decision-cards.ts +1 -1
- package/src/discord/sprint21-runtime.ts +16 -0
- package/src/discord-self-message.ts +8 -0
- package/src/discord-slash-wire.ts +31 -2
- package/src/domains/alert-audit.ts +271 -0
- package/src/domains/core-tools.ts +4 -3
- package/src/domains/ops-facts-tool.ts +31 -1
- package/src/domains/outbound-alert.ts +1 -1
- package/src/elanous-config-dir.ts +29 -4
- package/src/execution-loop/launch-gate.ts +29 -14
- package/src/flow/cards.ts +239 -0
- package/src/graph-runner/graph-tick.ts +4 -0
- package/src/graph-runner/runner.ts +30 -5
- package/src/harness/harness-cli-command.ts +259 -38
- package/src/harness/harness-incidents.ts +45 -12
- package/src/harness/harness-pod-dispatch.ts +102 -11
- package/src/harness/harness-queue-child.ts +3 -3
- package/src/harness/harness-queue.ts +583 -65
- package/src/harness/helper-repair.ts +87 -0
- package/src/harness/helper-scan.ts +151 -0
- package/src/harness/launch-stamp.ts +236 -0
- package/src/harness/ledger-write-guard-child.fixture.ts +12 -0
- package/src/harness/ledger-write-guard.ts +35 -0
- package/src/harness/model-input-observation.ts +37 -0
- package/src/harness/pod-memory-policy.ts +15 -0
- package/src/harness/repository-name.ts +55 -0
- package/src/hq/fence-audit.ts +90 -0
- package/src/hq/hq.ts +63 -5
- package/src/hq/lease.ts +4 -4
- package/src/hq/move-plan.ts +126 -0
- package/src/hq/promote.ts +332 -0
- package/src/index.ts +159 -27
- package/src/intake-plane/check.ts +63 -0
- package/src/intake-plane/digest.ts +37 -15
- package/src/intake-plane/front-classifier.ts +6 -0
- package/src/intake-plane/items.ts +3 -2
- package/src/intake-plane/lens.ts +177 -0
- package/src/intake-plane/linear-wish.ts +39 -11
- package/src/intake-plane/route.ts +145 -1
- package/src/intake-plane/wish-benchmark-ledger.ts +129 -0
- package/src/intake-plane/wish-card.ts +53 -2
- package/src/intake-plane/wish-folder.ts +5 -2
- package/src/intake-plane/wish-reply.ts +72 -0
- package/src/launch-head/seat-goal-queue-lock.fixture.ts +15 -0
- package/src/launch-head/seat-goal-queue.ts +198 -0
- package/src/lessons/lesson-import.ts +106 -0
- package/src/lessons/lesson-ledger.ts +206 -0
- package/src/loops/activity.ts +203 -0
- package/src/loops/budget.ts +63 -0
- package/src/loops/checker.ts +5 -3
- package/src/loops/contract/examples/orchestrator.loop.yaml +1 -1
- package/src/loops/loop-cli.ts +36 -4
- package/src/loops/neighbors.ts +40 -0
- package/src/loops/observe.ts +10 -0
- package/src/loops/orchestrator/author-depth.ts +220 -0
- package/src/loops/orchestrator/author-input-check.ts +82 -0
- package/src/loops/orchestrator/author-ledger.ts +232 -0
- package/src/loops/orchestrator/finish-rate.ts +175 -0
- package/src/loops/orchestrator/overlap.ts +51 -12
- package/src/loops/orchestrator/resync-shadow.ts +227 -0
- package/src/loops/orchestrator/seat-share.ts +56 -0
- package/src/loops/orchestrator/tick.ts +309 -0
- package/src/loops/orchestrator/traffic.ts +134 -13
- package/src/loops/registry.ts +535 -9
- package/src/loops/status-rows.ts +118 -0
- package/src/loops/verdict.ts +17 -5
- package/src/maturity/bot-slash-catalog.ts +66 -0
- package/src/maturity/feature-maturity.ts +9 -5
- package/src/maturity/tui-slash-availability.ts +31 -0
- package/src/mss/logging/log-store.ts +35 -4
- package/src/nexus/api/dashboard.ts +6 -1
- package/src/nexus/api/http-server.ts +33 -3
- package/src/nexus/api/loop-edges.ts +173 -0
- package/src/nexus/api/merge-approvals-gate.ts +1 -1
- package/src/nexus/api/schedules-read.ts +18 -1
- package/src/nexus/api/seat-requests.ts +79 -56
- package/src/nexus/api/task-cards-api.ts +44 -5
- package/src/nexus/api/workflows.ts +2 -1
- package/src/prompt-enhance/enhance.ts +6 -1
- package/src/release-loop/auto-start.ts +51 -0
- package/src/release-loop/checklist.ts +22 -4
- package/src/release-loop/feature-store.ts +71 -32
- package/src/release-loop/landing-freeze.ts +121 -0
- package/src/release-loop/merged-pr-checklist.ts +125 -0
- package/src/release-loop/placement.ts +302 -0
- package/src/release-loop/release-schedule.ts +3 -1
- package/src/seat-dispatch/ceo-commands.ts +2 -2
- package/src/seat-dispatch/seat-ask.ts +16 -3
- package/src/seat-dispatch/seat-questions.ts +58 -0
- package/src/seat-dispatch/seat-request-eligibility.ts +19 -0
- package/src/seat-dispatch/seat-request-ledger.ts +133 -0
- package/src/seat-loop/seat-loop.ts +531 -40
- package/src/self-dev/dev-pipeline.ts +14 -6
- package/src/self-dev/draft-sweep.ts +162 -6
- package/src/self-dev/draft-triage-rules.ts +25 -8
- package/src/self-dev/orchestrate.ts +15 -1
- package/src/self-dev/review-provider-fallback.ts +6 -1
- package/src/self-dev/run-store.ts +73 -1
- package/src/self-dev/run-supervisor.ts +57 -2
- package/src/self-dev/self-orchestrate-runtime.ts +5 -1
- package/src/self-implement/budget-gate.ts +29 -0
- package/src/self-implement/expose-gate.ts +47 -0
- package/src/self-implement/frozen-merges.ts +295 -0
- package/src/self-implement/gate-cli.ts +10 -4
- package/src/self-implement/gate-scope.ts +46 -9
- package/src/self-implement/goal-archive.ts +222 -0
- package/src/self-implement/goal-author.ts +43 -5
- package/src/self-implement/goal-clarification-escalation.ts +5 -0
- package/src/self-implement/goal-lookup.ts +147 -0
- package/src/self-implement/heal-intake.ts +197 -0
- package/src/self-implement/host-regate.ts +32 -2
- package/src/self-implement/l8-merge-queue.ts +132 -0
- package/src/self-implement/orchestrator.ts +299 -48
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/revert-guard.ts +97 -0
- package/src/self-implement/run-ledger.ts +3 -1
- package/src/self-implement/run-status-mapping.ts +2 -0
- package/src/self-implement/seams.ts +29 -9
- package/src/self-implement/self-implement-cli.ts +1 -0
- package/src/self-implement/speed-claims.ts +338 -0
- package/src/session/index.ts +2 -0
- package/src/steward/triage.ts +74 -3
- package/src/steward/working-backwards.ts +4 -1
- package/src/task-cards/card-cli.ts +10 -2
- package/src/task-cards/card-store.ts +10 -6
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +63 -48
- package/src/task-orchestrator/surfaces/pod-command-job.ts +84 -9
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +5 -2
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +46 -6
- package/src/task-orchestrator/surfaces/pod-pool.ts +60 -8
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +224 -49
- package/src/task-orchestrator/surfaces/self-implement.ts +5 -1
- package/src/telegram-commands.ts +27 -3
- package/src/telegram-loops-command.ts +44 -0
- package/src/telegram.ts +25 -4
- package/src/user-config.ts +146 -18
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/nodes/bash.ts +9 -1
- package/src/workflow-runtime/storage.ts +31 -13
- package/apps/pwa/out/_next/static/D51l8jUBplJrIpWvENsDK/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1394-931c9827067b2276.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992-fe5c06d6b31f8b25.js +0 -25
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5250-c78ca295585bbf95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6511-ff8360be3d65aaa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6588-ba380869b67c4fa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7758-85c2b53f731da024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8605-9da4678f8a310d18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9269.d2a4795bc6812717.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9906-e7b8b5310a169dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-e5b4e1b256f41076.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e49b9b76c565a0b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b4f032c893b21cc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f14987d5850a31e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b433308aad13ceb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-4c1dbb21861beab2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c85b816e3b269dbb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f6bc66b919b2ea7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-60603c1e056c9b25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a0ea8f5a2341ee6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-45c5bf04b4a605e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-36c6c4183353ac9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-cb2eb0fd809980da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-31012264da8a341f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-50309aeb0bdd554a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-bc00e964e855f4df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-0696ee3fac9fe56c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66c27608f651b866.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6ddd2109b7fc3a80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-4e50b7298c1f69a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7a2bf830038a2264.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1f327f18694fabca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-e5cef2fe6e4028df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cf596128d2b420ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-f672536f14f0969f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-b52365662232db89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-e7a6c80f288b1948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-29a709616df9b050.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fee842d7c2151129.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-78b40a344ed22f24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-75d199f448171014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a011dd5b0bff29c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-d92e32d51ab5157e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-5f21aed6932ef375.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-1e1a53946804debf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-a1833cd43d832601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-2a511d320f762e06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1c3e03f88dac1e21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c4d5289c2ea97a89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b91f8952deaeaf27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-71b43a2588489987.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2b256feed331546f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-505bb96d69a8622c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +0 -1
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +0 -1
- /package/apps/pwa/out/_next/static/{D51l8jUBplJrIpWvENsDK → LZcstaO9_NXypPFmujolv}/_ssgManifest.js +0 -0
|
@@ -49,6 +49,7 @@ export interface SelfImplementDisposition {
|
|
|
49
49
|
ok?: boolean;
|
|
50
50
|
worktreePath?: string;
|
|
51
51
|
branch?: string;
|
|
52
|
+
harvestable?: true;
|
|
52
53
|
prUrl?: string;
|
|
53
54
|
prNumber?: number;
|
|
54
55
|
/** Head SHA checked by the Pod before host regate. */
|
|
@@ -84,6 +85,7 @@ export interface SelfImplementDisposition {
|
|
|
84
85
|
reviewVerdict?: 'pass' | 'warn' | 'fail';
|
|
85
86
|
/** 마지막 리뷰의 must-fix 수(`review.mustFix.length`). 같은 조건. */
|
|
86
87
|
reviewMustFixCount?: number;
|
|
88
|
+
mustFix?: string[];
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
/**
|
|
@@ -265,7 +267,7 @@ export function createSelfImplementAdapter(opts: SelfImplementAdapterOptions) {
|
|
|
265
267
|
: r.output.length === 0
|
|
266
268
|
? `${exitMessage} (child produced no output)`
|
|
267
269
|
: r.disposition
|
|
268
|
-
? `${exitMessage} (child
|
|
270
|
+
? `${exitMessage} (child stage=${r.disposition.stage ?? 'unknown'}; ${r.disposition.detail ?? `mustFix=${JSON.stringify(r.disposition.mustFix ?? 'unknown')}`})`
|
|
269
271
|
: `${exitMessage} (child output did not contain a parseable terminal JSON diagnostic)`;
|
|
270
272
|
return {
|
|
271
273
|
...exec,
|
|
@@ -461,6 +463,7 @@ export function parseSelfImplementJson(stdout: string): SelfImplementDisposition
|
|
|
461
463
|
...(typeof o.ok === 'boolean' ? { ok: o.ok } : {}),
|
|
462
464
|
...(typeof o.worktreePath === 'string' ? { worktreePath: o.worktreePath } : {}),
|
|
463
465
|
...(typeof o.branch === 'string' ? { branch: o.branch } : {}),
|
|
466
|
+
...(o.harvestable === true && typeof o.branch === 'string' && o.branch.trim() ? { harvestable: true } : {}),
|
|
464
467
|
...(typeof o.prUrl === 'string' ? { prUrl: o.prUrl } : {}),
|
|
465
468
|
...(typeof o.prNumber === 'number' ? { prNumber: o.prNumber } : {}),
|
|
466
469
|
...(typeof o.checkedHeadCommit === 'string' ? { checkedHeadCommit: o.checkedHeadCommit } : {}),
|
|
@@ -483,6 +486,7 @@ export function parseSelfImplementJson(stdout: string): SelfImplementDisposition
|
|
|
483
486
|
? { providerErrors: o.providerErrors as SelfImplementDisposition['providerErrors'] } : {}),
|
|
484
487
|
...(typeof o.runId === 'string' && o.runId.trim() ? { runId: o.runId, childRunId: o.runId } : {}),
|
|
485
488
|
...reviewGateFields(o),
|
|
489
|
+
...(Array.isArray(o.mustFix) && o.mustFix.every((item) => typeof item === 'string') ? { mustFix: o.mustFix as string[] } : {}),
|
|
486
490
|
};
|
|
487
491
|
reportUnmappedDispositionFields(o, mapped);
|
|
488
492
|
return mapped;
|
package/src/telegram-commands.ts
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
import type { TgIncoming, TgMessageStreamer } from './telegram.js';
|
|
15
15
|
import type { UserConfig } from './user-config.js';
|
|
16
16
|
import { botCommandsToTelegram } from './bots/command-surface.js';
|
|
17
|
+
import { SLASH_COMMANDS, type SlashCommand } from './chat/index.js';
|
|
18
|
+
import { FEATURE_MATURITY, type Maturity } from './maturity/feature-maturity.js';
|
|
19
|
+
import { buildBotSlashCatalog } from './maturity/bot-slash-catalog.js';
|
|
17
20
|
import {
|
|
18
21
|
appendMessage,
|
|
19
22
|
attachTelegramBinding,
|
|
@@ -46,6 +49,7 @@ import { classifyIntake } from './ad-pipeline/intake.js';
|
|
|
46
49
|
import { createAdPipelineDeps, runAdPipeline } from './ad-pipeline/run.js';
|
|
47
50
|
import { projectCommand } from './telegram-project-command.js';
|
|
48
51
|
import { telegramNowSlash } from './context-bus/context-now-surfaces.js';
|
|
52
|
+
import { telegramLoopsStatus } from './telegram-loops-command.js';
|
|
49
53
|
import { createWishCard } from './intake-plane/wish-card.js';
|
|
50
54
|
import { telegramDecisionOwner } from './decisions/telegram-decision-cards.js';
|
|
51
55
|
import { CardStore } from './task-cards/card-store.js';
|
|
@@ -298,8 +302,12 @@ function dropChatSessionReply(ctx: TgIncoming): string {
|
|
|
298
302
|
/** Build the default command set for a Telegram bot wired via
|
|
299
303
|
* botFromConfig. Returns the array rather than mutating globals so
|
|
300
304
|
* tests can construct a variant set with stubbed handlers. */
|
|
301
|
-
export function defaultTelegramCommands(
|
|
302
|
-
|
|
305
|
+
export function defaultTelegramCommands(
|
|
306
|
+
nowDeps?: ContextNowDeps,
|
|
307
|
+
coreCommands: readonly SlashCommand[] = SLASH_COMMANDS,
|
|
308
|
+
maturity: { tuiSlash: Readonly<Record<string, Maturity>>; telegramCommand: Readonly<Record<string, Maturity>>; discordCommand: Readonly<Record<string, Maturity>> } = FEATURE_MATURITY,
|
|
309
|
+
): TgSlashCommand[] {
|
|
310
|
+
const handled: TgSlashCommand[] = [
|
|
303
311
|
{
|
|
304
312
|
name: 'help',
|
|
305
313
|
description: 'List available commands',
|
|
@@ -316,6 +324,11 @@ export function defaultTelegramCommands(nowDeps?: ContextNowDeps): TgSlashComman
|
|
|
316
324
|
description: 'Show current release, decisions, seats and context: /now [topic]',
|
|
317
325
|
handler: async (args) => telegramNowSlash(args, nowDeps),
|
|
318
326
|
},
|
|
327
|
+
{
|
|
328
|
+
name: 'loops',
|
|
329
|
+
description: '루프·크론 현황 — 늦음·실패를 먼저 보여줍니다',
|
|
330
|
+
handler: async (args) => telegramLoopsStatus(args),
|
|
331
|
+
},
|
|
319
332
|
{
|
|
320
333
|
name: 'status',
|
|
321
334
|
description: 'Show bot identity, current session, provider + model',
|
|
@@ -604,7 +617,8 @@ export function defaultTelegramCommands(nowDeps?: ContextNowDeps): TgSlashComman
|
|
|
604
617
|
if (args.length === 0) return '/wish <소원 한 줄>';
|
|
605
618
|
const store = new CardStore();
|
|
606
619
|
try {
|
|
607
|
-
const card = createWishCard({ text: args.join(' '), source: 'telegram', ref: `${ctx.chatId}:${ctx.messageId}
|
|
620
|
+
const card = createWishCard({ text: args.join(' '), source: 'telegram', ref: `${ctx.chatId}:${ctx.messageId}`,
|
|
621
|
+
replyTo: { surface: 'telegram', chatId: String(ctx.chatId), ...(ctx.threadId != null ? { threadId: String(ctx.threadId) } : {}), ...(ctx.botId ? { botId: ctx.botId } : {}) } }, store);
|
|
608
622
|
return `소원 카드로 남겼습니다 — ${card.title} (카드 ${card.cardId.slice(0, 8)})`;
|
|
609
623
|
} finally {
|
|
610
624
|
store.close();
|
|
@@ -951,6 +965,16 @@ export function defaultTelegramCommands(nowDeps?: ContextNowDeps): TgSlashComman
|
|
|
951
965
|
},
|
|
952
966
|
...botCommandsToTelegram(),
|
|
953
967
|
];
|
|
968
|
+
const catalog = buildBotSlashCatalog({
|
|
969
|
+
surface: 'telegram', coreCommands, maturity,
|
|
970
|
+
handledCommands: handled,
|
|
971
|
+
});
|
|
972
|
+
const handlers = new Map(handled.map((command) => [command.name, command]));
|
|
973
|
+
return catalog.commands.map((entry) => handlers.get(entry.name) ?? {
|
|
974
|
+
name: entry.name,
|
|
975
|
+
description: entry.description,
|
|
976
|
+
handler: async () => catalog.unsupportedReply(entry.name)!,
|
|
977
|
+
});
|
|
954
978
|
}
|
|
955
979
|
|
|
956
980
|
/** Telegram-side adapter over the messenger-agnostic ACP turn runner.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { dashboardLoops } from './domains/dashboard-data.js';
|
|
2
|
+
import { readSchedulesInventory } from './nexus/api/schedules-read.js';
|
|
3
|
+
import { loadLoopRows, LOOP_SCHEDULES_PATH, LOOPS_PATH, type LoopRow } from './loops/status-rows.js';
|
|
4
|
+
|
|
5
|
+
interface LoopsSources {
|
|
6
|
+
schedules: () => unknown;
|
|
7
|
+
loops: () => unknown;
|
|
8
|
+
now: () => number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const defaultSources: LoopsSources = {
|
|
12
|
+
schedules: () => ({ schedules: readSchedulesInventory() }),
|
|
13
|
+
loops: () => ({ loops: dashboardLoops() }),
|
|
14
|
+
now: Date.now,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const clean = (text: string) => text.replace(/[\r\n\t]+/g, ' ').replace(/\s+/g, ' ').trim();
|
|
18
|
+
|
|
19
|
+
/** Read the same two inventories and apply the same row verdicts as PWA /loops. */
|
|
20
|
+
export async function telegramLoopsStatus(args: string[], sources: LoopsSources = defaultSources): Promise<string> {
|
|
21
|
+
if (args.length) return '사용법: /loops';
|
|
22
|
+
try {
|
|
23
|
+
const rows = await loadLoopRows(async (path) => {
|
|
24
|
+
if (path === LOOP_SCHEDULES_PATH) return sources.schedules();
|
|
25
|
+
if (path === LOOPS_PATH) return sources.loops();
|
|
26
|
+
throw new Error('unknown inventory');
|
|
27
|
+
}, sources.now());
|
|
28
|
+
if (!rows.length) return '등록된 루프·크론이 없습니다.';
|
|
29
|
+
const counts = (['늦음', '실패', '살아 있음', '꺼짐', '판정 불가'] as const)
|
|
30
|
+
.map(verdict => `${verdict} ${rows.filter(row => row.verdict === verdict).length}`);
|
|
31
|
+
const priority: Record<LoopRow['verdict'], number> = { '늦음': 0, '실패': 1, '살아 있음': 2, '꺼짐': 3, '판정 불가': 4 };
|
|
32
|
+
const lines = rows.slice().sort((a, b) => priority[a.verdict] - priority[b.verdict]).map(row =>
|
|
33
|
+
`• ${row.verdict === '늦음' ? '🔴' : row.verdict === '실패' ? '❌' : row.verdict === '살아 있음' ? '🟢' : '⚪'} ${row.verdict} · ${clean(row.name)} (${clean(row.layer)}) · ${clean(row.mode)} · 마지막 ${row.lastRun ?? '기록 없음'} · ${clean(row.id)}`);
|
|
34
|
+
let reply = ['루프·크론 현황', counts.join(' · ')].join('\n');
|
|
35
|
+
for (const [index, line] of lines.entries()) {
|
|
36
|
+
// Telegram caps a message at 4096 characters; leave space for an explicit omission count.
|
|
37
|
+
if (reply.length + line.length + 35 > 4000) return `${reply}\n… ${lines.length - index}개 더 (메시지 길이 제한)`;
|
|
38
|
+
reply += `\n${line}`;
|
|
39
|
+
}
|
|
40
|
+
return reply;
|
|
41
|
+
} catch {
|
|
42
|
+
return '루프 현황을 읽지 못했습니다. 일부 레지스트리 조회가 실패했습니다. 데몬 연결을 확인하세요.';
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/telegram.ts
CHANGED
|
@@ -66,7 +66,9 @@ import { detectUrlRoute, type UrlRouteDecision } from './skills/url-router.js';
|
|
|
66
66
|
import { observeDevRequestRouteFailSoft } from './skills/dev-request-router.js';
|
|
67
67
|
import { runUrlRoute } from './skills/url-route-exec.js';
|
|
68
68
|
import { recordRoutedLinkAbsorbed } from './intake-plane/link-ledger.js';
|
|
69
|
-
import { classifyFrontInput } from './intake-plane/front-classifier.js';
|
|
69
|
+
import { classifyFrontInput, telegramAbsorbUrls } from './intake-plane/front-classifier.js';
|
|
70
|
+
import { scheduleIntakeEvent } from './intake-plane/route.js';
|
|
71
|
+
import { dispatchTaskCreate } from './task-orchestrator/runtimes/create.js';
|
|
70
72
|
import { handleTelegramSeatWork, type TelegramSeatWorkDeps } from './intake-plane/telegram-seat-work.js';
|
|
71
73
|
import { deliverSeatAnswers } from './seat-dispatch/seat-ask.js';
|
|
72
74
|
import { effectiveInstanceRoot } from './instance/resolve.js';
|
|
@@ -1919,11 +1921,30 @@ export class TelegramBot {
|
|
|
1919
1921
|
? getActiveDelegation(delegationChatKey(this.botId, ctx.chatId, ctx.threadId))
|
|
1920
1922
|
: null;
|
|
1921
1923
|
if (!activeDeleg) {
|
|
1922
|
-
try {
|
|
1923
|
-
classifyFrontInput({ text: ctx.text, surface: 'telegram' }, { urlRouting: getUserConfig().skills.urlRouting });
|
|
1924
|
-
} catch { /* observation must not interrupt URL routing */ }
|
|
1925
1924
|
const urlDec = detectUrlRoute(ctx.text, getUserConfig().skills.urlRouting);
|
|
1926
1925
|
if (urlDec) {
|
|
1926
|
+
try {
|
|
1927
|
+
const frontInput = { text: ctx.text, surface: 'telegram' as const };
|
|
1928
|
+
const decision = classifyFrontInput(frontInput, { urlRouting: getUserConfig().skills.urlRouting });
|
|
1929
|
+
const absorbUrls = telegramAbsorbUrls(frontInput, decision);
|
|
1930
|
+
for (const url of absorbUrls) {
|
|
1931
|
+
const result = await scheduleIntakeEvent(effectiveInstanceRoot(), url, {
|
|
1932
|
+
eventMax: getUserConfig().intake.eventMax,
|
|
1933
|
+
post: async ({ url: link }) => {
|
|
1934
|
+
const posted = await dispatchTaskCreate({
|
|
1935
|
+
title: `흡수: ${link}`.slice(0, 80),
|
|
1936
|
+
surface: { kind: 'llm-direct', prompt: `이 링크를 흡수하고 노트로 저장하세요: ${link}` },
|
|
1937
|
+
});
|
|
1938
|
+
if (!posted.taskId) throw new Error('intake event task not created');
|
|
1939
|
+
return { taskId: posted.taskId };
|
|
1940
|
+
},
|
|
1941
|
+
});
|
|
1942
|
+
if (result.reply) await this.sendMessage(ctx.chatId, result.reply, { threadId: ctx.threadId, markdown: true });
|
|
1943
|
+
}
|
|
1944
|
+
if (absorbUrls.length) return;
|
|
1945
|
+
} catch (error) {
|
|
1946
|
+
debug.log('intake.event', 'failed', { reason: error instanceof Error ? error.name : 'unknown' });
|
|
1947
|
+
}
|
|
1927
1948
|
const handled = await this.runUrlRouteReply(ctx, urlDec);
|
|
1928
1949
|
if (handled) return;
|
|
1929
1950
|
}
|
package/src/user-config.ts
CHANGED
|
@@ -3097,6 +3097,8 @@ export interface IntakeSurfaceConfig {
|
|
|
3097
3097
|
}
|
|
3098
3098
|
|
|
3099
3099
|
export interface IntakeConfig {
|
|
3100
|
+
/** Maximum immediately scheduled Telegram absorption links per KST day. */
|
|
3101
|
+
eventMax?: number;
|
|
3100
3102
|
telegram: IntakeSurfaceConfig;
|
|
3101
3103
|
discord: IntakeSurfaceConfig;
|
|
3102
3104
|
approvals?: { repo?: string };
|
|
@@ -3477,13 +3479,20 @@ export function resolveRoleModel(role: ModelRole, config: UserConfig = getUserCo
|
|
|
3477
3479
|
|
|
3478
3480
|
export type OrchestratorSeat = 'OP' | 'TC' | 'MK' | 'UX';
|
|
3479
3481
|
export interface OrchestratorLoopConfig {
|
|
3482
|
+
/** ORCH1 graph mode — shadow writes observations only; live appends delegations (default shadow). */
|
|
3483
|
+
mode: 'off' | 'shadow' | 'live';
|
|
3480
3484
|
seatTrees: Partial<Record<OrchestratorSeat, string[]>>;
|
|
3481
3485
|
seatCaps: Record<OrchestratorSeat, number>;
|
|
3486
|
+
/** Per-seat release gate; absent seats retain the spawn-budget default. */
|
|
3487
|
+
releaseGate?: Partial<Record<OrchestratorSeat, number>>;
|
|
3482
3488
|
trafficMode: 'shadow' | 'live';
|
|
3489
|
+
idleRequest?: 'off' | 'shadow' | 'live';
|
|
3490
|
+
/** FINISH-RATE — the queue tick reads finish metrics before launching; shadow logs the hold only, on holds (default shadow). */
|
|
3491
|
+
finishGate?: 'off' | 'shadow' | 'on';
|
|
3483
3492
|
}
|
|
3484
3493
|
|
|
3485
3494
|
export const ORCHESTRATOR_DEFAULTS: OrchestratorLoopConfig = {
|
|
3486
|
-
seatTrees: {}, seatCaps: { TC: 8, UX: 6, MK: 6, OP: 4 }, trafficMode: 'shadow',
|
|
3495
|
+
mode: 'shadow', seatTrees: {}, seatCaps: { TC: 8, UX: 6, MK: 6, OP: 4 }, trafficMode: 'shadow', idleRequest: 'shadow', finishGate: 'shadow',
|
|
3487
3496
|
};
|
|
3488
3497
|
|
|
3489
3498
|
export function parseOrchestratorLoopConfig(raw: unknown): OrchestratorLoopConfig {
|
|
@@ -3492,25 +3501,36 @@ export function parseOrchestratorLoopConfig(raw: unknown): OrchestratorLoopConfi
|
|
|
3492
3501
|
? value.seatTrees as Record<string, unknown> : {};
|
|
3493
3502
|
const rawCaps = value.seatCaps && typeof value.seatCaps === 'object' && !Array.isArray(value.seatCaps)
|
|
3494
3503
|
? value.seatCaps as Record<string, unknown> : {};
|
|
3504
|
+
const rawGate = value.releaseGate && typeof value.releaseGate === 'object' && !Array.isArray(value.releaseGate)
|
|
3505
|
+
? value.releaseGate as Record<string, unknown> : {};
|
|
3495
3506
|
const seatTrees: OrchestratorLoopConfig['seatTrees'] = {};
|
|
3496
3507
|
const seatCaps = { ...ORCHESTRATOR_DEFAULTS.seatCaps };
|
|
3508
|
+
const releaseGate: NonNullable<OrchestratorLoopConfig['releaseGate']> = {};
|
|
3497
3509
|
for (const seat of ['OP', 'TC', 'MK', 'UX'] as const) {
|
|
3498
3510
|
if (Array.isArray(rawTrees[seat])) seatTrees[seat] = rawTrees[seat].filter((path): path is string => typeof path === 'string' && isAbsolute(path));
|
|
3499
3511
|
const cap = rawCaps[seat];
|
|
3500
3512
|
if (typeof cap === 'number' && Number.isSafeInteger(cap) && cap >= 0) seatCaps[seat] = cap;
|
|
3513
|
+
const gate = rawGate[seat];
|
|
3514
|
+
if (typeof gate === 'number' && Number.isSafeInteger(gate) && gate >= 0) releaseGate[seat] = gate;
|
|
3501
3515
|
}
|
|
3502
|
-
|
|
3516
|
+
const mode = value.mode === 'off' || value.mode === 'live' ? value.mode : 'shadow';
|
|
3517
|
+
return { mode, seatTrees, seatCaps, ...(Object.keys(releaseGate).length ? { releaseGate } : {}),
|
|
3518
|
+
trafficMode: value.trafficMode === 'live' ? 'live' : 'shadow',
|
|
3519
|
+
idleRequest: value.idleRequest === 'off' || value.idleRequest === 'live' ? value.idleRequest : 'shadow',
|
|
3520
|
+
finishGate: value.finishGate === 'off' || value.finishGate === 'on' ? value.finishGate : 'shadow' };
|
|
3503
3521
|
}
|
|
3504
3522
|
|
|
3505
3523
|
export type StewardLoopMode = 'off' | 'shadow' | 'live' | 'rescue';
|
|
3506
3524
|
|
|
3507
|
-
export type SeatLoopMode = 'off' | 'shadow' | 'on';
|
|
3525
|
+
export type SeatLoopMode = 'off' | 'shadow' | 'on' | 'live-safe';
|
|
3508
3526
|
|
|
3509
3527
|
export interface PersonaLoopConfig { enabled: boolean }
|
|
3510
3528
|
|
|
3511
3529
|
export interface SeatLoopConfig {
|
|
3512
|
-
/**
|
|
3530
|
+
/** Shadow observes by default; live-safe acts only through the shared rescue policy, while legacy on retains its behavior. */
|
|
3513
3531
|
mode: SeatLoopMode;
|
|
3532
|
+
/** Validated loop-agent neighbor entries keyed by the observing seat. */
|
|
3533
|
+
neighbors?: Partial<Record<'OP' | 'TC' | 'MK' | 'UX', import('./loops/neighbors.js').Neighbor[]>>;
|
|
3514
3534
|
/** Seat-to-seat and human questions default to shadow even when the checklist loop is on. */
|
|
3515
3535
|
questions?: 'shadow' | 'on';
|
|
3516
3536
|
seats?: string[];
|
|
@@ -3553,6 +3573,8 @@ export interface HqConfig {
|
|
|
3553
3573
|
standby?: string;
|
|
3554
3574
|
/** Lease TTL in seconds (default 1500 = 25 min). */
|
|
3555
3575
|
ttlSeconds?: number;
|
|
3576
|
+
/** Arbiter silence threshold (default 3); applying promotion requires explicit opt-in. */
|
|
3577
|
+
autoPromote?: { enabled?: boolean; streak?: number };
|
|
3556
3578
|
/** Roles that may still run when this host is fenced only for lack of quorum (never when a newer generation exists). Absent = none. */
|
|
3557
3579
|
failOpenRoles?: HqFenceRole[];
|
|
3558
3580
|
/** Per-host nexus health URL over the tailnet (default https://<host>.<tailnetDomain>:31415/v1/health). */
|
|
@@ -3575,19 +3597,22 @@ export interface UserConfig {
|
|
|
3575
3597
|
hq?: HqConfig;
|
|
3576
3598
|
/** Root CLI help audience; absent or invalid means owner. */
|
|
3577
3599
|
cli?: { helpRole?: 'owner' | 'contributor' | 'general' };
|
|
3600
|
+
/** Daemon public demonstration mode; absent means off. */
|
|
3601
|
+
nexus?: { demoMode?: boolean };
|
|
3578
3602
|
/** Execution-phase HITL answer deadline; absent means 30 minutes. */
|
|
3579
3603
|
hitl?: { executionDeadlineMinutes?: number };
|
|
3580
3604
|
coo?: { linearProject?: string };
|
|
3581
|
-
decisions?: { linearProjection: { enabled: boolean }; requireCrossCheck: boolean
|
|
3605
|
+
decisions?: { linearProjection: { enabled: boolean }; requireCrossCheck: boolean;
|
|
3606
|
+
crossCheckNeighbor: Record<EventSeat, EventSeat>; crossCheckWaitMinutes: number };
|
|
3582
3607
|
/** Per-seat goal and Pod limits; missing or invalid limits use seat-budget defaults. */
|
|
3583
3608
|
org?: { budget?: Record<string, { dailyGoals?: number; concurrentPods?: number }> };
|
|
3584
|
-
/** Steward and seat loops are parsed independently. An absent seat
|
|
3585
|
-
loops?: { orchestrator?: OrchestratorLoopConfig; steward?: { mode?: StewardLoopMode; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string>; alertAfterFailures?: number; launch?: 'off' | 'shadow' | 'live'; maxParallel?: number; podPool?: string }; seat?: SeatLoopConfig; persona?: PersonaLoopConfig };
|
|
3609
|
+
/** Steward and seat loops are parsed independently. An absent seat defaults to shadow. */
|
|
3610
|
+
loops?: { owners?: Record<string, EventSeat>; defaultOwner?: EventSeat; orchestrator?: OrchestratorLoopConfig; steward?: { mode?: StewardLoopMode; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string>; alertAfterFailures?: number; launch?: 'off' | 'shadow' | 'live'; maxParallel?: number; podPool?: string }; seat?: SeatLoopConfig; persona?: PersonaLoopConfig };
|
|
3586
3611
|
/** 🔐 Pod 의 Grok API 키 과금은 명시 opt-in 만. 생략·잘못된 값은 false.
|
|
3587
3612
|
* budgetGate 와 같은 `harness` 객체다 — 중복 선언이면 뒤 타입이 앞을 지운다. */
|
|
3588
|
-
harness?: { pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; difficultyPlacement?: boolean; defaultRepo?: string; substrate?: 'local' | 'pod'; podPool?: string; worktreeAddTimeoutSec?: number; queue?: { seatCap?: Partial<Record<'OP' | 'TC' | 'MK' | 'UX', number>> } };
|
|
3613
|
+
harness?: { revertGuard?: { depth: number }; pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; exposeGate?: 'warn' | 'strict'; difficultyPlacement?: boolean; defaultRepo?: string; /** Optional GitHub repository name (owner/repo), distinct from the local defaultRepo path. */ repo?: string; substrate?: 'local' | 'pod'; podPool?: string; worktreeAddTimeoutSec?: number; queue?: { seatCap?: Partial<Record<'OP' | 'TC' | 'MK' | 'UX', number>> }; /** `harness say` 문장을 Pod 안에서 저작부터 돌릴지. 생략·false = 끔(호스트가 저작). */ authorOnPod?: boolean };
|
|
3589
3614
|
/** ☸️ Pod 실행 칸 — `pool` = 기존 기본 풀(`컨텍스트[@ssh호스트][:상한][#k3d-레지스트리:포트]` 쉼표 · 앞이 우선). harness 실행은 인자·ELANOUS_POD_POOL·harness.podPool 다음으로 읽는다. */
|
|
3590
|
-
pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string; /** 읽기 전용 Pod lease 권장에 쓰는 계정별 동시 수. */ lease?: { perAccount?: number }; /** 실측 권고를 Pod 발사 기본값으로 쓸지 (기본 off). */ memory?: { adviseDefaults?: boolean } };
|
|
3615
|
+
pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string; /** 읽기 전용 Pod lease 권장에 쓰는 계정별 동시 수. */ lease?: { perAccount?: number }; /** 실측 권고를 Pod 발사 기본값으로 쓸지 (기본 off). */ memory?: { adviseDefaults?: boolean }; /** 명령 Job 자식 로그(child.log) 상한 바이트. 양의 정수만. 넘으면 끝부분 우선. */ childLogMaxBytes?: number };
|
|
3591
3616
|
skillRouter: SkillRouterConfig;
|
|
3592
3617
|
llm: LLMConfig;
|
|
3593
3618
|
skills: SkillsConfig;
|
|
@@ -3913,8 +3938,9 @@ function defaultConfig(): UserConfig {
|
|
|
3913
3938
|
return {
|
|
3914
3939
|
cli: { helpRole: 'owner' },
|
|
3915
3940
|
coo: { linearProject: '외부 행정·큰 일 (COO)' },
|
|
3916
|
-
decisions: { linearProjection: { enabled: false }, requireCrossCheck: false
|
|
3917
|
-
|
|
3941
|
+
decisions: { linearProjection: { enabled: false }, requireCrossCheck: false,
|
|
3942
|
+
crossCheckNeighbor: { OP: 'TC', TC: 'OP', MK: 'OP', UX: 'OP' }, crossCheckWaitMinutes: 120 },
|
|
3943
|
+
loops: { owners: {}, defaultOwner: 'OP', orchestrator: parseOrchestratorLoopConfig(undefined), steward: { mode: 'shadow' }, seat: { mode: 'shadow', questions: 'shadow', seats: ['MK'], podPool: 'pool-node-b@node-b:8' }, persona: { enabled: false } },
|
|
3918
3944
|
skillRouter: { ...SR_DEFAULTS },
|
|
3919
3945
|
llm: { ...LLM_DEFAULTS },
|
|
3920
3946
|
skills: skillsDefaults(),
|
|
@@ -3945,7 +3971,7 @@ function defaultConfig(): UserConfig {
|
|
|
3945
3971
|
},
|
|
3946
3972
|
},
|
|
3947
3973
|
voice: { stt: {}, tts: {}, vad: {}, chat: {}, discord: {}, telegram: {}, pwa: {} },
|
|
3948
|
-
intake: { telegram: {}, discord: {} },
|
|
3974
|
+
intake: { eventMax: 10, telegram: {}, discord: {} },
|
|
3949
3975
|
dashboard: {
|
|
3950
3976
|
promptBank: { ...DASHBOARD_PROMPT_BANK_DEFAULTS },
|
|
3951
3977
|
foldMode: 'task-unit',
|
|
@@ -3983,7 +4009,7 @@ function defaultConfig(): UserConfig {
|
|
|
3983
4009
|
nativeStructure: { ...TOOLS_DEFAULTS.nativeStructure },
|
|
3984
4010
|
selfImplement: { ...TOOLS_DEFAULTS.selfImplement },
|
|
3985
4011
|
},
|
|
3986
|
-
harness: { budgetGate: { ...DEFAULT_BUDGET_GATE }, difficultyPlacement: false },
|
|
4012
|
+
harness: { revertGuard: { depth: 50 }, budgetGate: { ...DEFAULT_BUDGET_GATE }, exposeGate: 'warn', difficultyPlacement: false },
|
|
3987
4013
|
grounding: { sources: [] },
|
|
3988
4014
|
raw: {},
|
|
3989
4015
|
};
|
|
@@ -4394,20 +4420,95 @@ function parseStewardTracks(input: unknown): Record<string, string> | undefined
|
|
|
4394
4420
|
return Object.keys(out).length ? out : undefined;
|
|
4395
4421
|
}
|
|
4396
4422
|
|
|
4423
|
+
function parseDecisionsConfig(input: unknown): NonNullable<UserConfig['decisions']> {
|
|
4424
|
+
const defaults: Record<EventSeat, EventSeat> = { OP: 'TC', TC: 'OP', MK: 'OP', UX: 'OP' };
|
|
4425
|
+
const raw = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : {};
|
|
4426
|
+
const neighbors = { ...defaults };
|
|
4427
|
+
if (raw.crossCheckNeighbor !== undefined) {
|
|
4428
|
+
if (!raw.crossCheckNeighbor || typeof raw.crossCheckNeighbor !== 'object' || Array.isArray(raw.crossCheckNeighbor)) {
|
|
4429
|
+
warnUserConfigDrop('decisions.crossCheckNeighbor', '자리별 이웃 자리 객체가 아닙니다 — 기본값으로 진행합니다.');
|
|
4430
|
+
} else {
|
|
4431
|
+
const values = raw.crossCheckNeighbor as Record<string, unknown>;
|
|
4432
|
+
for (const seat of Object.keys(defaults) as EventSeat[]) {
|
|
4433
|
+
if (values[seat] === undefined) continue;
|
|
4434
|
+
const to = values[seat];
|
|
4435
|
+
if ((to === 'OP' || to === 'TC' || to === 'MK' || to === 'UX') && to !== seat) neighbors[seat] = to;
|
|
4436
|
+
else warnUserConfigDrop(`decisions.crossCheckNeighbor.${seat}`, '다른 자리가 아닙니다 — 기본값으로 진행합니다.');
|
|
4437
|
+
}
|
|
4438
|
+
for (const seat of Object.keys(values)) {
|
|
4439
|
+
if (!(seat in defaults)) warnUserConfigDrop(`decisions.crossCheckNeighbor.${seat}`, '알 수 없는 자리입니다 — 기본값으로 진행합니다.');
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
const wait = raw.crossCheckWaitMinutes;
|
|
4444
|
+
if (wait !== undefined && !(typeof wait === 'number' && Number.isSafeInteger(wait) && wait > 0)) {
|
|
4445
|
+
warnUserConfigDrop('decisions.crossCheckWaitMinutes', '양의 정수가 아닙니다 — 기본값 120으로 진행합니다.');
|
|
4446
|
+
}
|
|
4447
|
+
return { linearProjection: { enabled: (raw.linearProjection as { enabled?: unknown } | undefined)?.enabled === true },
|
|
4448
|
+
requireCrossCheck: raw.requireCrossCheck === true, crossCheckNeighbor: neighbors,
|
|
4449
|
+
crossCheckWaitMinutes: typeof wait === 'number' && Number.isSafeInteger(wait) && wait > 0 ? wait : 120 };
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
function parseLoopOwners(input: unknown): { owners: Record<string, EventSeat>; defaultOwner: EventSeat } {
|
|
4453
|
+
const raw = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : {};
|
|
4454
|
+
const valid = (value: unknown): value is EventSeat => value === 'OP' || value === 'TC' || value === 'MK' || value === 'UX';
|
|
4455
|
+
const defaultOwner = valid(raw.defaultOwner) ? raw.defaultOwner : 'OP';
|
|
4456
|
+
if (raw.defaultOwner !== undefined && !valid(raw.defaultOwner)) warnUserConfigDrop('loops.defaultOwner', '잘못된 자리 — 기본 OP 로 진행');
|
|
4457
|
+
// Prototype-less: a loop titled «__proto__» (or «constructor») must keep its owner (review round 3).
|
|
4458
|
+
const owners: Record<string, EventSeat> = Object.create(null) as Record<string, EventSeat>;
|
|
4459
|
+
if (raw.owners !== undefined) {
|
|
4460
|
+
if (!raw.owners || typeof raw.owners !== 'object' || Array.isArray(raw.owners)) {
|
|
4461
|
+
warnUserConfigDrop('loops.owners', '객체가 아니다 — 기본 자리로 진행');
|
|
4462
|
+
} else {
|
|
4463
|
+
for (const [key, value] of Object.entries(raw.owners)) {
|
|
4464
|
+
if (key.trim() && valid(value)) owners[key] = value;
|
|
4465
|
+
else warnUserConfigDrop(`loops.owners.${key}`, `잘못된 자리 — 기본 ${defaultOwner} 로 진행`);
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
return { owners, defaultOwner };
|
|
4470
|
+
}
|
|
4471
|
+
|
|
4397
4472
|
function parseSeatLoopsConfig(input: unknown): SeatLoopConfig {
|
|
4398
|
-
const defaults: SeatLoopConfig = { mode: '
|
|
4473
|
+
const defaults: SeatLoopConfig = { mode: 'shadow', questions: 'shadow', seats: ['MK'], podPool: 'pool-node-b@node-b:8' };
|
|
4399
4474
|
if (!input || typeof input !== 'object' || Array.isArray(input)) return defaults;
|
|
4400
4475
|
const seat = (input as Record<string, unknown>).seat;
|
|
4401
4476
|
if (!seat || typeof seat !== 'object' || Array.isArray(seat)) return defaults;
|
|
4402
4477
|
const values = seat as Record<string, unknown>;
|
|
4403
4478
|
const mode = values.mode;
|
|
4404
4479
|
return {
|
|
4405
|
-
mode: mode === 'on' || mode === 'shadow' ? mode : '
|
|
4480
|
+
mode: mode === 'on' || mode === 'shadow' || mode === 'live-safe' || mode === 'off' ? mode : 'shadow',
|
|
4406
4481
|
questions: values.questions === 'on' ? 'on' : 'shadow',
|
|
4407
4482
|
seats: Array.isArray(values.seats) && values.seats.length > 0
|
|
4408
4483
|
&& values.seats.every((value) => typeof value === 'string' && /^(?:MK|OP|TC|UX)$/.test(value))
|
|
4409
4484
|
? [...new Set(values.seats as string[])] : ['MK'],
|
|
4410
4485
|
podPool: typeof values.podPool === 'string' && values.podPool.trim() ? values.podPool.trim() : defaults.podPool,
|
|
4486
|
+
...(() => {
|
|
4487
|
+
const raw = values.neighbors;
|
|
4488
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
|
|
4489
|
+
const neighbors: NonNullable<SeatLoopConfig['neighbors']> = {};
|
|
4490
|
+
for (const [owner, entries] of Object.entries(raw)) {
|
|
4491
|
+
if (!/^(?:OP|TC|MK|UX)$/.test(owner) || !Array.isArray(entries)) continue;
|
|
4492
|
+
const valid = entries.filter((entry): entry is import('./loops/neighbors.js').Neighbor => {
|
|
4493
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return false;
|
|
4494
|
+
const value = entry as Record<string, unknown>;
|
|
4495
|
+
const heartbeat = value.heartbeat && typeof value.heartbeat === 'object' && !Array.isArray(value.heartbeat)
|
|
4496
|
+
? value.heartbeat as Record<string, unknown> : undefined;
|
|
4497
|
+
const onAbsent = value.onAbsent && typeof value.onAbsent === 'object' && !Array.isArray(value.onAbsent)
|
|
4498
|
+
? value.onAbsent as Record<string, unknown> : undefined;
|
|
4499
|
+
return typeof value.id === 'string' && /^(?:op|tc|mk|ux)-seat$/.test(value.id)
|
|
4500
|
+
&& value.id !== `${owner.toLowerCase()}-seat`
|
|
4501
|
+
&& Array.isArray(value.exchange) && value.exchange.length > 0
|
|
4502
|
+
&& value.exchange.every((item) => typeof item === 'string' && ['status', 'request', 'decision', 'blocked'].includes(item))
|
|
4503
|
+
&& !!heartbeat && Number.isSafeInteger(heartbeat.everyMinutes) && (heartbeat.everyMinutes as number) > 0
|
|
4504
|
+
&& Number.isSafeInteger(heartbeat.missedTicks) && (heartbeat.missedTicks as number) > 0
|
|
4505
|
+
&& !!onAbsent && typeof onAbsent.action === 'string' && ['delegate', 'defer', 'escalate'].includes(onAbsent.action)
|
|
4506
|
+
&& typeof onAbsent.delegateTo === 'string' && onAbsent.delegateTo.trim().length > 0;
|
|
4507
|
+
});
|
|
4508
|
+
neighbors[owner as keyof typeof neighbors] = valid;
|
|
4509
|
+
}
|
|
4510
|
+
return { neighbors };
|
|
4511
|
+
})(),
|
|
4411
4512
|
...(typeof values.reportPr === 'number' && Number.isSafeInteger(values.reportPr) && values.reportPr > 0
|
|
4412
4513
|
? { reportPr: values.reportPr } : {}),
|
|
4413
4514
|
...(() => {
|
|
@@ -4472,6 +4573,13 @@ export function parseHqConfig(raw: unknown): HqConfig | undefined {
|
|
|
4472
4573
|
}
|
|
4473
4574
|
if (typeof r.ttlSeconds === 'number' && Number.isFinite(r.ttlSeconds) && r.ttlSeconds > 0) out.ttlSeconds = r.ttlSeconds;
|
|
4474
4575
|
if (typeof r.probeTimeoutSeconds === 'number' && Number.isFinite(r.probeTimeoutSeconds) && r.probeTimeoutSeconds > 0) out.probeTimeoutSeconds = r.probeTimeoutSeconds;
|
|
4576
|
+
if (r.autoPromote && typeof r.autoPromote === 'object' && !Array.isArray(r.autoPromote)) {
|
|
4577
|
+
const auto = r.autoPromote as Record<string, unknown>;
|
|
4578
|
+
const setting: NonNullable<HqConfig['autoPromote']> = {};
|
|
4579
|
+
if (typeof auto.enabled === 'boolean') setting.enabled = auto.enabled;
|
|
4580
|
+
if (typeof auto.streak === 'number' && Number.isSafeInteger(auto.streak) && auto.streak > 0) setting.streak = auto.streak;
|
|
4581
|
+
if (Object.keys(setting).length) out.autoPromote = setting;
|
|
4582
|
+
}
|
|
4475
4583
|
if (Array.isArray(r.failOpenRoles)) out.failOpenRoles = r.failOpenRoles.filter((v): v is HqFenceRole => HQ_FENCE_ROLES.includes(v as HqFenceRole));
|
|
4476
4584
|
if (r.healthUrls && typeof r.healthUrls === 'object' && !Array.isArray(r.healthUrls)) {
|
|
4477
4585
|
out.healthUrls = Object.fromEntries(Object.entries(r.healthUrls as Record<string, unknown>).filter((e): e is [string, string] => typeof e[1] === 'string'));
|
|
@@ -4598,11 +4706,15 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4598
4706
|
};
|
|
4599
4707
|
}
|
|
4600
4708
|
|
|
4709
|
+
const nexus = rawObj.nexus && typeof rawObj.nexus === 'object' && !Array.isArray(rawObj.nexus)
|
|
4710
|
+
? rawObj.nexus as Record<string, unknown> : {};
|
|
4601
4711
|
return {
|
|
4712
|
+
nexus: { demoMode: nexus.demoMode === true },
|
|
4602
4713
|
...(Object.keys(seatBudgets).length ? { org: { budget: seatBudgets } } : {}),
|
|
4603
4714
|
pod: {
|
|
4604
4715
|
...(typeof legacyPod.pool === 'string' && legacyPod.pool.trim() ? { pool: legacyPod.pool.trim() } : {}),
|
|
4605
4716
|
...(typeof legacyPod.hostMirror === 'string' && legacyPod.hostMirror.trim() ? { hostMirror: legacyPod.hostMirror.trim() } : {}),
|
|
4717
|
+
...(typeof legacyPod.childLogMaxBytes === 'number' && Number.isSafeInteger(legacyPod.childLogMaxBytes) && legacyPod.childLogMaxBytes > 0 ? { childLogMaxBytes: legacyPod.childLogMaxBytes } : {}),
|
|
4606
4718
|
...(typeof legacyPod.groundingUrl === 'string' ? { groundingUrl: legacyPod.groundingUrl } : {}),
|
|
4607
4719
|
memory: { adviseDefaults: Boolean(legacyPod.memory && typeof legacyPod.memory === 'object' && !Array.isArray(legacyPod.memory)
|
|
4608
4720
|
&& (legacyPod.memory as Record<string, unknown>).adviseDefaults === true) },
|
|
@@ -4614,8 +4726,14 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4614
4726
|
})() },
|
|
4615
4727
|
},
|
|
4616
4728
|
harness: {
|
|
4729
|
+
revertGuard: { depth: (() => {
|
|
4730
|
+
const value = harness.revertGuard && typeof harness.revertGuard === 'object' && !Array.isArray(harness.revertGuard)
|
|
4731
|
+
? (harness.revertGuard as Record<string, unknown>).depth : undefined;
|
|
4732
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : 50;
|
|
4733
|
+
})() },
|
|
4617
4734
|
pod: { grokApiKeyOptIn: harnessPod.grokApiKeyOptIn === true },
|
|
4618
4735
|
difficultyPlacement: harness.difficultyPlacement === true,
|
|
4736
|
+
exposeGate: harness.exposeGate === 'strict' ? 'strict' : 'warn',
|
|
4619
4737
|
queue: { seatCap: Object.fromEntries(Object.entries(
|
|
4620
4738
|
harness.queue && typeof harness.queue === 'object' && !Array.isArray(harness.queue)
|
|
4621
4739
|
&& (harness.queue as Record<string, unknown>).seatCap && typeof (harness.queue as Record<string, unknown>).seatCap === 'object'
|
|
@@ -4629,6 +4747,9 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4629
4747
|
? { worktreeAddTimeoutSec: harness.worktreeAddTimeoutSec } : {}),
|
|
4630
4748
|
...(typeof harness.defaultRepo === 'string' && isAbsolute(harness.defaultRepo)
|
|
4631
4749
|
? { defaultRepo: harness.defaultRepo } : {}),
|
|
4750
|
+
...(typeof harness.repo === 'string' && harness.repo.trim()
|
|
4751
|
+
? { repo: harness.repo.trim() } : {}),
|
|
4752
|
+
...(harness.authorOnPod === true ? { authorOnPod: true } : {}),
|
|
4632
4753
|
budgetGate: parseHarnessBudgetGate(
|
|
4633
4754
|
rawObj.harness && typeof rawObj.harness === 'object' && !Array.isArray(rawObj.harness)
|
|
4634
4755
|
? (rawObj.harness as Record<string, unknown>).budgetGate
|
|
@@ -5165,6 +5286,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
5165
5286
|
},
|
|
5166
5287
|
},
|
|
5167
5288
|
intake: {
|
|
5289
|
+
eventMax: typeof intake.eventMax === 'number' && Number.isSafeInteger(intake.eventMax) && intake.eventMax >= 0 ? intake.eventMax : 10,
|
|
5168
5290
|
telegram: {
|
|
5169
5291
|
...(normalizeIntakeAmbientCaptureMode(intakeTelegram.ambientCapture) !== undefined
|
|
5170
5292
|
? { ambientCapture: normalizeIntakeAmbientCaptureMode(intakeTelegram.ambientCapture)! }
|
|
@@ -5270,9 +5392,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
5270
5392
|
cli: { helpRole: parseCliHelpRole(rawObj.cli) },
|
|
5271
5393
|
coo: { linearProject: typeof (rawObj.coo as { linearProject?: unknown } | undefined)?.linearProject === 'string' && (rawObj.coo as { linearProject: string }).linearProject.trim()
|
|
5272
5394
|
? (rawObj.coo as { linearProject: string }).linearProject.trim() : '외부 행정·큰 일 (COO)' },
|
|
5273
|
-
decisions:
|
|
5274
|
-
|
|
5275
|
-
loops: { ...(stewardLoops ?? {}), orchestrator: parseOrchestratorLoopConfig((rawObj.loops as { orchestrator?: unknown } | undefined)?.orchestrator), seat: parseSeatLoopsConfig(rawObj.loops),
|
|
5395
|
+
decisions: parseDecisionsConfig(rawObj.decisions),
|
|
5396
|
+
loops: { ...(stewardLoops ?? {}), ...parseLoopOwners(rawObj.loops), orchestrator: parseOrchestratorLoopConfig((rawObj.loops as { orchestrator?: unknown } | undefined)?.orchestrator), seat: parseSeatLoopsConfig(rawObj.loops),
|
|
5276
5397
|
persona: { enabled: (rawObj.loops as { persona?: { enabled?: unknown } } | undefined)?.persona?.enabled === true } },
|
|
5277
5398
|
events: parseEventsConfig(rawObj.events),
|
|
5278
5399
|
// M1-1: sparse — undefined when the user hasn't set anything, so
|
|
@@ -5868,15 +5989,20 @@ export function saveUserConfig(
|
|
|
5868
5989
|
...rawHarness,
|
|
5869
5990
|
pod: cfg.harness?.pod ?? rawHarness.pod,
|
|
5870
5991
|
budgetGate: cfg.harness?.budgetGate ?? rawHarness.budgetGate,
|
|
5992
|
+
exposeGate: cfg.harness?.exposeGate ?? rawHarness.exposeGate,
|
|
5993
|
+
revertGuard: cfg.harness?.revertGuard ?? rawHarness.revertGuard,
|
|
5871
5994
|
difficultyPlacement: cfg.harness?.difficultyPlacement ?? rawHarness.difficultyPlacement,
|
|
5872
5995
|
defaultRepo: cfg.harness?.defaultRepo ?? rawHarness.defaultRepo,
|
|
5996
|
+
repo: cfg.harness?.repo,
|
|
5873
5997
|
substrate: cfg.harness?.substrate,
|
|
5874
5998
|
podPool: cfg.harness?.podPool,
|
|
5999
|
+
authorOnPod: cfg.harness?.authorOnPod === true ? true : undefined,
|
|
5875
6000
|
queue: cfg.harness?.queue ?? rawHarness.queue,
|
|
5876
6001
|
}),
|
|
5877
6002
|
...rawRest,
|
|
5878
6003
|
...(cfg.loops ? { loops: {
|
|
5879
6004
|
...rawLoops,
|
|
6005
|
+
owners: cfg.loops.owners ?? {}, defaultOwner: cfg.loops.defaultOwner ?? 'OP',
|
|
5880
6006
|
...(cfg.loops.steward ? { steward: { ...rawSteward, mode: cfg.loops.steward.mode ?? cfg.loops.steward.launch ?? 'shadow' } } : {}),
|
|
5881
6007
|
...(cfg.loops.orchestrator ? { orchestrator: cfg.loops.orchestrator } : {}),
|
|
5882
6008
|
...(cfg.loops.seat ? { seat: {
|
|
@@ -5884,6 +6010,7 @@ export function saveUserConfig(
|
|
|
5884
6010
|
questions: cfg.loops.seat.questions ?? 'shadow',
|
|
5885
6011
|
seats: cfg.loops.seat.seats ?? ['MK'],
|
|
5886
6012
|
podPool: cfg.loops.seat.podPool ?? 'pool-node-b@node-b:8',
|
|
6013
|
+
...(cfg.loops.seat.neighbors ? { neighbors: cfg.loops.seat.neighbors } : {}),
|
|
5887
6014
|
...(cfg.loops.seat.reportPr === undefined ? {} : { reportPr: cfg.loops.seat.reportPr }),
|
|
5888
6015
|
} } : {}),
|
|
5889
6016
|
} } : {}),
|
|
@@ -6104,6 +6231,7 @@ export function saveUserConfig(
|
|
|
6104
6231
|
}),
|
|
6105
6232
|
}),
|
|
6106
6233
|
}),
|
|
6234
|
+
intake: { ...(rawRest.intake && typeof rawRest.intake === 'object' ? rawRest.intake as Record<string, unknown> : {}), ...cfg.intake },
|
|
6107
6235
|
dashboard: stripUndef({
|
|
6108
6236
|
views: cfg.dashboard.views,
|
|
6109
6237
|
theme: cfg.dashboard.theme,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"f89d24931e428797960330ae109e8919ee784a15"}
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
import type { BashNode, NodeExecContext, NodeOutput, WorkflowDeps } from '../types.js';
|
|
9
9
|
import { interpolate } from '../variables.js';
|
|
10
10
|
|
|
11
|
+
/** Keep the start of stderr and its real error line. Bun prints the source frame first. */
|
|
12
|
+
export function formatBashStderr(stderr: string): string {
|
|
13
|
+
const head = 200;
|
|
14
|
+
const tail = 800;
|
|
15
|
+
if (stderr.length <= head + tail) return stderr;
|
|
16
|
+
return `${stderr.slice(0, head)}…${stderr.slice(-tail)}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
export async function executeBashNode(
|
|
12
20
|
node: BashNode,
|
|
13
21
|
ctx: NodeExecContext,
|
|
@@ -30,7 +38,7 @@ export async function executeBashNode(
|
|
|
30
38
|
return {
|
|
31
39
|
ok: false,
|
|
32
40
|
output: r.stdout, // surface partial output for $node.output access
|
|
33
|
-
error: `bash exit ${r.exitCode}${r.stderr ? `: ${r.stderr
|
|
41
|
+
error: `bash exit ${r.exitCode}${r.stderr ? `: ${formatBashStderr(r.stderr)}` : ''}`,
|
|
34
42
|
durationMs: Date.now() - startedAt,
|
|
35
43
|
};
|
|
36
44
|
}
|