elanous 0.2.21 → 0.2.22
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/1307-08b716476f1d50af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2489-ff55a35b202c0f94.js → 2489-d238d3e2eb5b2bf5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-d781be3e3a9cfd74.js → page-d85c43f46f58716b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-b0a80997903852d8.js → page-4e645600579ae952.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-2b1263165630d9c8.js → page-87edbfd19117823b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-e2d6bed48ac20120.js → page-cbaf66b1e1804adf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-80ed511e02c81412.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/{page-544dd4bd4847eeb7.js → page-9f5610caaa06178c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/{page-3ee191319bf97d87.js → page-ec8f3575e339de74.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-a449f1ed472b81c2.js → page-2a19c5cd3b562580.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-9045094d6d3b5cd0.js → page-b6a09cde2e07521a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/{page-c06673596849ef45.js → page-f7eae1518ca0c353.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{layout-9f81233f29dcd409.js → layout-8462d6a543cbb2d9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-7a12f61be4a579d1.js → page-786fb4504d0f2fa9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-c85b0589591a99c9.js → not-found-75209f14597dcb8f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/{page-725a4da02dd129eb.js → page-bf30affe3a85af7e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{page-21bec4afeb2f0917.js → page-76cf838050a8d681.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-dc39ee7a36d26385.js → page-7ec8e289b4c14df6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-84ae759f76053672.js → page-8c8ac17d52be2a79.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-3db58ddb61fe2be9.js → page-d359ab048d63a9d9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-c5315e30f3528dc4.js → page-b8b345c880bf78d1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-2fe368efb6de3b6a.js → page-f151cc10ad026940.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-c69762987b751174.js → page-bf495a1e284f4e00.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-7f8d7fcdf058a845.js → page-69cb93d1a2e57e0e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-22163556cd38bc88.js → page-72ec543928d67c3e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +1 -0
- package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +14 -14
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +14 -14
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +14 -14
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +14 -14
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +14 -14
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +14 -14
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +14 -14
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +14 -14
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +14 -14
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +14 -14
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +14 -14
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +14 -14
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +14 -14
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +14 -14
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +14 -14
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +14 -14
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +14 -14
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +14 -14
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +14 -14
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +14 -14
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +14 -14
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +14 -14
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +14 -14
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +14 -14
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +14 -14
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +14 -14
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +14 -14
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +14 -14
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +15 -15
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +14 -14
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +14 -14
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +14 -14
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +14 -14
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +14 -14
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +14 -14
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +14 -14
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +14 -14
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +14 -14
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +14 -14
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +14 -14
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +14 -14
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +14 -14
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +14 -14
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +14 -14
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +14 -14
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +14 -14
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/drafts/recipes.yaml +2 -2
- package/graphs/test-diet/recipes.yaml +3 -0
- package/graphs/test-diet/test-diet.yaml +3 -1
- package/package.json +1 -1
- package/scripts/f-session-monitor.ts +69 -0
- package/scripts/hq/standby-snapshot.ts +7 -3
- package/scripts/knowledge-compress.ts +11 -0
- package/scripts/nightly-docops.ts +90 -3
- package/scripts/research-coo-admin-dates.ts +39 -0
- package/scripts/skills/public-check.ts +7 -2
- package/scripts/smart-merge/resync-shadow.ts +5 -3
- package/scripts/test-diet/lib.ts +81 -1
- package/scripts/test-diet/node.ts +48 -2
- package/scripts/verify-coo-admin-evidence.ts +83 -0
- package/src/acp/client.ts +4 -2
- package/src/agent/run-context.ts +4 -0
- package/src/agent-env/profile.ts +25 -5
- package/src/agent-mission/driver.ts +26 -12
- package/src/agent-mission/supervisor-metrics.ts +17 -2
- package/src/agent-substrate/acp-reviewer.ts +12 -5
- package/src/agent-substrate/pr-reviewer.ts +11 -4
- package/src/agent-substrate/review-intent.ts +102 -3
- package/src/autopilot/build/llm-conflict-merge.ts +22 -8
- package/src/autopilot/pr-manager.ts +18 -8
- package/src/away/release-watch.ts +47 -8
- package/src/briefing/brief-items.ts +104 -11
- package/src/chat/index.ts +1 -0
- package/src/cli/brief-cli.ts +20 -2
- package/src/cli/config-classify.ts +83 -0
- package/src/cli/control-cli.ts +14 -0
- package/src/cli/decisions-cli.ts +26 -16
- package/src/cli/logs-model-input.ts +1 -1
- package/src/cli/pr-cli.ts +65 -8
- package/src/cli/release-cli.ts +21 -4
- package/src/cli/tasks-cli.ts +108 -1
- package/src/connectors/types.ts +6 -6
- package/src/context-bus/context-now-surfaces.ts +18 -0
- package/src/context-bus/coord-events.ts +32 -4
- package/src/context-bus/long-term-memory.ts +23 -6
- package/src/context-bus/nightly-condense.ts +169 -21
- package/src/control/control-status.ts +87 -0
- package/src/control-plane/light-member.ts +5 -3
- package/src/control-plane/member.ts +172 -7
- package/src/core-turn/run-goal-loop.ts +22 -1
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +9 -0
- package/src/decisions/decision-cards.ts +20 -1
- package/src/decisions/decision-ledger.ts +11 -8
- package/src/decisions/web-push-decision-cards.ts +19 -3
- package/src/discord-self-message.ts +2 -2
- package/src/domains/coo-admin-dates.evidence.json +876 -0
- package/src/domains/coo-admin-tool.ts +48 -14
- package/src/domains/ops-status.ts +53 -0
- package/src/domains/outbound-alert.ts +24 -1
- package/src/exec-requests/planner.ts +6 -0
- package/src/graph-kinds/registry.ts +6 -6
- package/src/graph-runner/graph-cli.ts +34 -2
- package/src/graph-runner/graph-run-api.ts +7 -0
- package/src/graph-runner/graph-tick.ts +73 -12
- package/src/graph-runner/runner.ts +43 -11
- package/src/graph-unify/wf-to-graph.ts +79 -0
- package/src/graph-wizard/generate.ts +34 -2
- package/src/graph-wizard/steps.ts +13 -0
- package/src/harness/harness-cli-command.ts +121 -23
- package/src/harness/harness-queue.ts +58 -14
- package/src/harness/launch-advice.ts +23 -0
- package/src/index.ts +36 -7
- package/src/knowledge/conclusion-compress.ts +93 -0
- package/src/knowledge/know-find.ts +9 -2
- package/src/knowledge/query.ts +20 -0
- package/src/llm.ts +26 -16
- package/src/loops/neighbor-runtime.ts +88 -0
- package/src/loops/orchestrator/author-depth.ts +29 -11
- package/src/loops/orchestrator/overlap.ts +7 -1
- package/src/loops/orchestrator/resync-shadow.ts +1 -1
- package/src/loops/orchestrator/tick.ts +35 -2
- package/src/loops/orchestrator/traffic.ts +2 -0
- package/src/loops/registry.ts +5 -0
- package/src/market/publish.ts +17 -1
- package/src/maturity/feature-maturity.ts +2 -1
- package/src/mss/logging/redaction.ts +17 -0
- package/src/nexus/api/draft-metrics.ts +22 -8
- package/src/nexus/api/graph-peer-edit.ts +77 -0
- package/src/nexus/api/graph-wizard-api.ts +9 -1
- package/src/nexus/api/graphs-api.ts +145 -7
- package/src/nexus/api/http-server.ts +93 -8
- package/src/nexus/api/plugins-market.ts +24 -0
- package/src/nexus/index.ts +3 -2
- package/src/oauth/claude-pty-maturity.ts +24 -0
- package/src/oauth/fallback-chain.ts +27 -14
- package/src/plugins/maker/market-bundle.ts +9 -0
- package/src/plugins/maker/plugin-maker.ts +9 -3
- package/src/plugins/maker/wizard-generate.ts +73 -9
- package/src/policy/llm-policy.ts +11 -6
- package/src/release-loop/checklist-board.ts +27 -0
- package/src/release-loop/checklist.ts +38 -0
- package/src/seat-address/seat-address.ts +1 -0
- package/src/seat-loop/seat-loop.ts +174 -20
- package/src/seat-loop/seat-report.ts +29 -1
- package/src/self-dev/dev-cli.ts +90 -8
- package/src/self-dev/dev-pipeline.ts +20 -1
- package/src/self-dev/draft-sweep.ts +45 -8
- package/src/self-dev/orchestrate.ts +3 -0
- package/src/self-dev/review-provider-fallback.ts +83 -0
- package/src/self-dev/run-supervisor.ts +5 -1
- package/src/self-implement/harness-policy-gates.ts +7 -5
- package/src/self-implement/host-regate.ts +28 -14
- package/src/self-implement/l8-merge-queue.ts +80 -8
- package/src/self-implement/orchestrator.ts +68 -27
- package/src/self-implement/seams.ts +5 -3
- package/src/self-implement/self-implement-cli.ts +4 -0
- package/src/shell-env-bootstrap.ts +19 -4
- package/src/steward/triage.ts +25 -8
- package/src/storage/file-lock.ts +33 -4
- package/src/task-agent/completion-evidence.ts +31 -3
- package/src/task-agent/cover.ts +61 -0
- package/src/task-agent/live-moves.ts +126 -3
- package/src/task-agent/shadow.ts +19 -4
- package/src/task-agent/task-hand.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +138 -15
- package/src/task-orchestrator/surfaces/self-implement.ts +7 -0
- package/src/telegram-commands.ts +8 -0
- package/src/telegram-project-command.ts +6 -0
- package/src/telegram.ts +2 -2
- package/src/typecheck-ratchet.ts +2 -1
- package/src/user-config.ts +35 -4
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/executor.ts +24 -2
- package/src/workflow-runtime/triggers/registry.ts +27 -0
- package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
- package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
- package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
- /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → aBi6EyMtLsrl7J8eH4kF7}/_buildManifest.js +0 -0
- /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → aBi6EyMtLsrl7J8eH4kF7}/_ssgManifest.js +0 -0
|
@@ -55,6 +55,8 @@ export interface SelfImplementDisposition {
|
|
|
55
55
|
prNumber?: number;
|
|
56
56
|
/** Head SHA checked by the Pod before host regate. */
|
|
57
57
|
checkedHeadCommit?: string;
|
|
58
|
+
/** Review verdict only when the child bound a real pass to a clean, unchanged worktree head. */
|
|
59
|
+
selfReview?: { verdict: 'pass'; head: string };
|
|
58
60
|
hostRegate?: { passed: boolean; failures: Array<{ step: string; detail: string }>; os: string };
|
|
59
61
|
merged?: boolean;
|
|
60
62
|
detail?: string;
|
|
@@ -469,6 +471,11 @@ export function parseSelfImplementJson(stdout: string): SelfImplementDisposition
|
|
|
469
471
|
...(typeof o.prUrl === 'string' ? { prUrl: o.prUrl } : {}),
|
|
470
472
|
...(typeof o.prNumber === 'number' ? { prNumber: o.prNumber } : {}),
|
|
471
473
|
...(typeof o.checkedHeadCommit === 'string' ? { checkedHeadCommit: o.checkedHeadCommit } : {}),
|
|
474
|
+
...(o.reviewedHeadCommit && typeof o.reviewedHeadCommit === 'string' && /^[0-9a-f]{40}$/i.test(o.reviewedHeadCommit)
|
|
475
|
+
&& o.review && typeof o.review === 'object' && !Array.isArray(o.review)
|
|
476
|
+
&& (o.review as { reviewed?: unknown; verdict?: unknown }).reviewed === true
|
|
477
|
+
&& (o.review as { verdict?: unknown }).verdict === 'pass'
|
|
478
|
+
? { selfReview: { verdict: 'pass' as const, head: o.reviewedHeadCommit } } : {}),
|
|
472
479
|
...(typeof o.hostRegate === 'object' && o.hostRegate !== null ? { hostRegate: o.hostRegate as SelfImplementDisposition['hostRegate'] } : {}),
|
|
473
480
|
...(typeof o.merged === 'boolean' ? { merged: o.merged } : {}),
|
|
474
481
|
...(typeof o.detail === 'string' ? { detail: o.detail } : {}),
|
package/src/telegram-commands.ts
CHANGED
|
@@ -56,6 +56,8 @@ import { telegramDecisionOwner } from './decisions/telegram-decision-cards.js';
|
|
|
56
56
|
import { CardStore } from './task-cards/card-store.js';
|
|
57
57
|
import type { ContextNowDeps } from './context-bus/context-now.js';
|
|
58
58
|
import type { RunningRunsResult } from './self-implement/running-runs.js';
|
|
59
|
+
import { checklistBoardSlash } from './release-loop/checklist-board.js';
|
|
60
|
+
import type { Checklist } from './release-loop/checklist.js';
|
|
59
61
|
|
|
60
62
|
/** How many prior user/assistant turns to pass into `executeSkill` as
|
|
61
63
|
* the `## Recent conversation` block. Mirrors the dashboard default
|
|
@@ -348,6 +350,7 @@ export function defaultTelegramCommands(
|
|
|
348
350
|
coreCommands: readonly SlashCommand[] = SLASH_COMMANDS,
|
|
349
351
|
maturity: { tuiSlash: Readonly<Record<string, Maturity>>; telegramCommand: Readonly<Record<string, Maturity>>; discordCommand: Readonly<Record<string, Maturity>> } = FEATURE_MATURITY,
|
|
350
352
|
runningRunsQuery?: () => RunningRunsResult,
|
|
353
|
+
checklistRead?: (version: string) => Checklist,
|
|
351
354
|
): TgSlashCommand[] {
|
|
352
355
|
const handled: TgSlashCommand[] = [
|
|
353
356
|
{
|
|
@@ -376,6 +379,11 @@ export function defaultTelegramCommands(
|
|
|
376
379
|
description: 'Running harness runs — same output as TUI /harness runs',
|
|
377
380
|
handler: async (args) => telegramRunsSlash(args, runningRunsQuery),
|
|
378
381
|
},
|
|
382
|
+
{
|
|
383
|
+
name: 'board',
|
|
384
|
+
description: '판 체크리스트 — /board [판]',
|
|
385
|
+
handler: async (args) => checklistBoardSlash(args, checklistRead),
|
|
386
|
+
},
|
|
379
387
|
{
|
|
380
388
|
name: 'release',
|
|
381
389
|
description: '발행 현황 — 지금 런·노드·막힘을 한 통으로',
|
|
@@ -121,6 +121,12 @@ export function attachTelegramProjectButtons(
|
|
|
121
121
|
await bot.answerCallbackQuery(q.id, { text: '개인 대화에서만 고를 수 있습니다' });
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
|
+
// Reject callbacks outside Telegram's 64-byte limit and empty project ids.
|
|
125
|
+
if (Buffer.byteLength(q.data, 'utf8') > 64 || q.data.length === 4) {
|
|
126
|
+
debug.log('telegram.project', 'button-rejected', { reason: 'invalid-callback-data', chatId: q.chatId });
|
|
127
|
+
await bot.answerCallbackQuery(q.id, { text: '프로젝트를 다시 골라 주세요' });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
124
130
|
const chatId = q.chatId;
|
|
125
131
|
const session = deps.findSession(chatId, q.threadId, bot.botId);
|
|
126
132
|
if (!session) {
|
package/src/telegram.ts
CHANGED
|
@@ -81,7 +81,7 @@ import { maybeHandleCardPhoto, type CardPhotoDeps } from './telegram-card-follow
|
|
|
81
81
|
import { attachTelegramProjectButtons } from './telegram-project-command.js';
|
|
82
82
|
import { attachTelegramFabricPlan } from './telegram-fabric-plan.js';
|
|
83
83
|
import { contextNow as readContextNow, type ContextNowDeps } from './context-bus/context-now.js';
|
|
84
|
-
import {
|
|
84
|
+
import { renderContextFirstNow } from './context-bus/context-now-surfaces.js';
|
|
85
85
|
import { createContextFirstGate, renderContextFirst } from './context-bus/context-first.js';
|
|
86
86
|
|
|
87
87
|
export type TgAttachmentKind = 'photo' | 'voice' | 'audio' | 'document';
|
|
@@ -437,7 +437,7 @@ export class TelegramBot {
|
|
|
437
437
|
const cfg = this.slashContext?.userConfig.telegram;
|
|
438
438
|
if (cfg?.contextFirst === false) return;
|
|
439
439
|
try {
|
|
440
|
-
await this.sendMessage(ctx.chatId, renderContextFirst(this.readContextNow, this.contextNowDeps,
|
|
440
|
+
await this.sendMessage(ctx.chatId, renderContextFirst(this.readContextNow, this.contextNowDeps, renderContextFirstNow), { replyTo: ctx.messageId, threadId: ctx.threadId });
|
|
441
441
|
} catch (err) {
|
|
442
442
|
this.log(`telegram context-first failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
443
443
|
}
|
package/src/typecheck-ratchet.ts
CHANGED
|
@@ -8,9 +8,10 @@ export const TYPECHECK_GATE_CONFIG = 'tsconfig.gate.json';
|
|
|
8
8
|
* 🩸 2026-09-23: 🅢·🅕·🅣 세 창이 같은 날 `heap out of memory` 로 착지가 막혔다. 📏 통과한 판의 최대 RSS **5.0GB**
|
|
9
9
|
* (128GB 기계 · 부하와 무관하게 재현 — 🅕 「로드 ~7 로 내려간 뒤에도 났다」). 우회 12288 로 🅢 착지 19건 PASS.
|
|
10
10
|
* ⇒ 부하 탓이 아니라 «자란 프로젝트»다. 값을 사람이 기억해 붙이는 우회를 도구가 스스로 갖는다.
|
|
11
|
+
* 🩸 2026-10-08: 12288 로도 호스트 재게이트·`pr land` 가 OOM 으로 «못 잼»(#25177 · #25248 · TC 수확 4건 — 전부 20480 에서 PASS) → 20480.
|
|
11
12
|
* ⚠️ 호출자가 이미 `--max-old-space-size` 를 줬으면 «그것을» 존중한다(덮지 않는다).
|
|
12
13
|
*/
|
|
13
|
-
export const TSC_HEAP_MB =
|
|
14
|
+
export const TSC_HEAP_MB = 20480;
|
|
14
15
|
export function tscEnv(base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
|
15
16
|
const cur = base.NODE_OPTIONS ?? '';
|
|
16
17
|
if (/--max-old-space-size[= ]/.test(cur)) return base;
|
package/src/user-config.ts
CHANGED
|
@@ -214,6 +214,8 @@ export interface LLMConfig {
|
|
|
214
214
|
* `within-quota`(한도 안에서만 · 전부 차면 멈춤) · `fallback`(한도 안 ⊕ 폴백 체인 · 기본) · `credits`(크레딧까지).
|
|
215
215
|
* 회전·Pod 배분·폴백·매시 한도 알림이 «이 한 값»을 같이 읽는다. 없으면 옛 `codexCreditsAllowed` 를 읽는다. */
|
|
216
216
|
codexQuotaPolicy?: 'within-quota' | 'fallback' | 'credits';
|
|
217
|
+
/** Grok weekly launch usage ceiling (percent); defaults to 80. */
|
|
218
|
+
grokWeeklyCapPct?: number;
|
|
217
219
|
/** ⭐⭐ codex 가 «소진된 뒤» 갈 곳을 «순서»로 정한다 (대표 2026-08-13).
|
|
218
220
|
*
|
|
219
221
|
* 값: `['codex-rotate', 'grok']` — 아는 칸은 그 둘뿐이고, 모르는 이름은 버린다(관측에 남는다).
|
|
@@ -431,7 +433,7 @@ export interface RotationEntry {
|
|
|
431
433
|
label?: string;
|
|
432
434
|
}
|
|
433
435
|
|
|
434
|
-
const LLM_DEFAULTS: LLMConfig = { provider: 'auto' };
|
|
436
|
+
const LLM_DEFAULTS: LLMConfig = { provider: 'auto', grokWeeklyCapPct: 80 };
|
|
435
437
|
|
|
436
438
|
// ── Skills ───────────────────────────────────────────────────────────
|
|
437
439
|
|
|
@@ -1149,6 +1151,8 @@ export interface SelfImplementToolConfig {
|
|
|
1149
1151
|
clarificationEscalation: SelfImplementClarificationEscalationConfig;
|
|
1150
1152
|
/** RUN-TTL: hours an open self-impl PR may go without a commit before the draft sweep asks for a rebase. Absent or invalid = 24. */
|
|
1151
1153
|
runTtlHours?: number;
|
|
1154
|
+
/** DRAFT-CLEANUP-FIX: per-tick close cap of `harness drafts sweep`. Raw value — `resolveDraftSweepCloseCap` validates (1–100, default 10, warns). */
|
|
1155
|
+
draftSweepCloseCap?: unknown;
|
|
1152
1156
|
/** RUN-TTL sweep step: `shadow` (default) only logs; `live` sends the resync memo / adds `elanous:needs-rebase`. Cap absent or invalid = 30. */
|
|
1153
1157
|
runTtl?: { mode: 'shadow' | 'live'; cap?: number };
|
|
1154
1158
|
/** STOP-AUTOHEAL: `shadow` (default) only records what the stop dispatcher would do (`event='autoheal'`); `live` runs the injected heal seams once per run per stop class. */
|
|
@@ -2684,6 +2688,8 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
|
|
|
2684
2688
|
const childLlm = parseChildLlmPreference(selfImplRaw.childLlm);
|
|
2685
2689
|
const runTtlHoursRaw = selfImplRaw.runTtlHours;
|
|
2686
2690
|
const runTtlHours = typeof runTtlHoursRaw === 'number' && Number.isFinite(runTtlHoursRaw) && runTtlHoursRaw > 0 ? runTtlHoursRaw : undefined;
|
|
2691
|
+
// Kept raw: the sweep validates and warns, so an out-of-range value is visible rather than silently dropped.
|
|
2692
|
+
const draftSweepCloseCap = selfImplRaw.draftSweepCloseCap;
|
|
2687
2693
|
const runTtlRaw = selfImplRaw.runTtl && typeof selfImplRaw.runTtl === 'object' && !Array.isArray(selfImplRaw.runTtl)
|
|
2688
2694
|
? selfImplRaw.runTtl as Record<string, unknown> : undefined;
|
|
2689
2695
|
const runTtl = runTtlRaw ? {
|
|
@@ -2729,7 +2735,7 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
|
|
|
2729
2735
|
runDevHarness,
|
|
2730
2736
|
selfOrchestrate,
|
|
2731
2737
|
nativeStructure,
|
|
2732
|
-
selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalRecordInDoc, goalAuthorPersistentGrounding, fabricDecompose, fabricDecomposeAutoPathThreshold, autoOpenPr, draftOnStop, salvageRetention, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(childLlm ? { childLlm } : {}), ...(runTtlHours !== undefined ? { runTtlHours } : {}), ...(runTtl ? { runTtl } : {}), ...(autoheal ? { autoheal } : {}) },
|
|
2738
|
+
selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalRecordInDoc, goalAuthorPersistentGrounding, fabricDecompose, fabricDecomposeAutoPathThreshold, autoOpenPr, draftOnStop, salvageRetention, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(childLlm ? { childLlm } : {}), ...(runTtlHours !== undefined ? { runTtlHours } : {}), ...(draftSweepCloseCap !== undefined ? { draftSweepCloseCap } : {}), ...(runTtl ? { runTtl } : {}), ...(autoheal ? { autoheal } : {}) },
|
|
2733
2739
|
};
|
|
2734
2740
|
}
|
|
2735
2741
|
|
|
@@ -3311,8 +3317,22 @@ export interface RoleLlmSpec {
|
|
|
3311
3317
|
model?: string;
|
|
3312
3318
|
}
|
|
3313
3319
|
|
|
3314
|
-
/**
|
|
3315
|
-
export
|
|
3320
|
+
/** Reviewer-only ACP subscription selection; it is not a streaming LLM provider. */
|
|
3321
|
+
export interface SubscriptionReviewerSpec {
|
|
3322
|
+
provider: 'claude-acp';
|
|
3323
|
+
executor?: 'cct' | 'cc';
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
export function parseSubscriptionReviewerSpec(raw: unknown): SubscriptionReviewerSpec | undefined {
|
|
3327
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
|
|
3328
|
+
const v = raw as Record<string, unknown>;
|
|
3329
|
+
if (v.provider !== 'claude-acp' || (v.executor !== undefined && v.executor !== 'cct' && v.executor !== 'cc')
|
|
3330
|
+
|| Object.keys(v).some(k => k !== 'provider' && k !== 'executor')) return undefined;
|
|
3331
|
+
return { provider: 'claude-acp', ...(v.executor ? { executor: v.executor as 'cct' | 'cc' } : {}) };
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
/** 역할별 LLM 선택(sparse). `reviewer` is the opt-in harness ACP lane. */
|
|
3335
|
+
export type RoleLlmConfig = Partial<Record<ModelRole, RoleLlmSpec>> & { reviewer?: SubscriptionReviewerSpec };
|
|
3316
3336
|
|
|
3317
3337
|
export type ModelResolutionSource = 'config' | 'tier' | 'environment' | 'default';
|
|
3318
3338
|
|
|
@@ -3603,6 +3623,8 @@ export interface SeatLoopConfig {
|
|
|
3603
3623
|
repeatStop?: number;
|
|
3604
3624
|
/** OP-LOOP-DECIDE: OP seat filters open decision cards (repeat-stop → b · harness scope → b unless money/security/secret/public paths). shadow records only; live decides/routes. Absent = shadow. */
|
|
3605
3625
|
opDecide?: { mode: 'shadow' | 'live' };
|
|
3626
|
+
/** IDLE-LADDER: when a seat's own queue is empty the loop picks idle work (landed-yellow rebuttal → next-release authoring → standing work → borrow an unlaunched neighbor cell). Absent = off (only the empty-queue minutes metric is recorded); 'shadow' records the pick only; 'live' lets live-safe/on launch it. */
|
|
3627
|
+
idleLadder?: 'shadow' | 'live';
|
|
3606
3628
|
}
|
|
3607
3629
|
|
|
3608
3630
|
export type EventSeat = 'OP' | 'TC' | 'MK' | 'UX';
|
|
@@ -4134,6 +4156,10 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
|
|
|
4134
4156
|
if (entry.ok) parsed[role] = entry.spec;
|
|
4135
4157
|
else dropped.push({ role, reason: entry.reason });
|
|
4136
4158
|
}
|
|
4159
|
+
if (values.reviewer !== undefined) {
|
|
4160
|
+
parsed.reviewer = parseSubscriptionReviewerSpec(values.reviewer);
|
|
4161
|
+
if (!parsed.reviewer) warnUserConfigDrop('roleLlm.reviewer', 'claude-acp reviewer 설정이 유효하지 않아 무시');
|
|
4162
|
+
}
|
|
4137
4163
|
// ⛔ config 로딩은 «나머지를 살리려고» 잘못된 칸을 버리는데, 그 사실이 어디에도 안 남으면
|
|
4138
4164
|
// 사용자는 「왜 내 설정이 안 먹지」를 영영 못 푼다(CLI 는 이름을 대며 거부하는데 여기만 조용했다).
|
|
4139
4165
|
// ⇒ 버린 것을 «이름과 이유»로 남긴다. 로딩 자체는 계속한다.
|
|
@@ -4747,6 +4773,7 @@ function parseSeatLoopsConfig(input: unknown): SeatLoopConfig {
|
|
|
4747
4773
|
const mode = (raw as Record<string, unknown>).mode;
|
|
4748
4774
|
return mode === 'shadow' || mode === 'live' ? { opDecide: { mode } } : {};
|
|
4749
4775
|
})(),
|
|
4776
|
+
...(values.idleLadder === 'shadow' || values.idleLadder === 'live' ? { idleLadder: values.idleLadder } : {}),
|
|
4750
4777
|
};
|
|
4751
4778
|
}
|
|
4752
4779
|
|
|
@@ -5114,6 +5141,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
5114
5141
|
// ⛔ 같은 모양(문자열 배열)이라 아래 fallbackChain 과 «같은 자»를 쓴다.
|
|
5115
5142
|
codexCreditsAllowed: llm.codexCreditsAllowed === true ? true : undefined,
|
|
5116
5143
|
codexQuotaPolicy: isCodexQuotaPolicy(llm.codexQuotaPolicy) ? llm.codexQuotaPolicy : undefined,
|
|
5144
|
+
grokWeeklyCapPct: typeof llm.grokWeeklyCapPct === 'number' && Number.isFinite(llm.grokWeeklyCapPct)
|
|
5145
|
+
&& llm.grokWeeklyCapPct >= 0 && llm.grokWeeklyCapPct <= 100 ? llm.grokWeeklyCapPct : LLM_DEFAULTS.grokWeeklyCapPct,
|
|
5117
5146
|
codexAccountOrder: Array.isArray(llm.codexAccountOrder)
|
|
5118
5147
|
? llm.codexAccountOrder.filter((v: unknown): v is string => typeof v === 'string' && v.length > 0)
|
|
5119
5148
|
: undefined,
|
|
@@ -6328,6 +6357,7 @@ export function saveUserConfig(
|
|
|
6328
6357
|
...(cfg.loops.seat.stall ? { stall: cfg.loops.seat.stall } : {}),
|
|
6329
6358
|
...(cfg.loops.seat.repeatStop === undefined ? {} : { repeatStop: cfg.loops.seat.repeatStop }),
|
|
6330
6359
|
...(cfg.loops.seat.opDecide ? { opDecide: cfg.loops.seat.opDecide } : {}),
|
|
6360
|
+
...(cfg.loops.seat.idleLadder ? { idleLadder: cfg.loops.seat.idleLadder } : {}),
|
|
6331
6361
|
} } : {}),
|
|
6332
6362
|
} } : {}),
|
|
6333
6363
|
...(cfg.autopilot ? { autopilot: {
|
|
@@ -6383,6 +6413,7 @@ export function saveUserConfig(
|
|
|
6383
6413
|
// ★ 2026-09-28: 타입·파서에만 넣고 이 whitelist 를 빠뜨려 `config set llm.codexCreditsAllowed true` 가 «직렬화 드롭» 됐다(#21375 직후 운영 실측).
|
|
6384
6414
|
codexCreditsAllowed: cfg.llm.codexCreditsAllowed,
|
|
6385
6415
|
codexQuotaPolicy: cfg.llm.codexQuotaPolicy,
|
|
6416
|
+
grokWeeklyCapPct: cfg.llm.grokWeeklyCapPct,
|
|
6386
6417
|
fallbackChain: cfg.llm.fallbackChain,
|
|
6387
6418
|
reviewFallbackModels: cfg.llm.reviewFallbackModels,
|
|
6388
6419
|
codexStore: cfg.llm.codexStore,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"7f281a6aa9a90d9da2b5f3e9a22e2347b0c19bff"}
|
|
@@ -41,6 +41,9 @@ import {
|
|
|
41
41
|
import { evaluateWhen } from './variables.js';
|
|
42
42
|
import { readWorkflowPin } from './pin-data.js';
|
|
43
43
|
import { WORKFLOW_CORE_KINDS } from '../graph-kinds/registry.js';
|
|
44
|
+
import { workflowToGraph, walkWorkflowGraph } from '../graph-unify/wf-to-graph.js';
|
|
45
|
+
import { debug } from '../debug/log.js';
|
|
46
|
+
import { getUserConfig } from '../user-config.js';
|
|
44
47
|
import { checkModelRequires } from '../registry/resolver.js';
|
|
45
48
|
import { validateJudgmentContract, validateJudgmentVerdict } from './judgment-contract.js';
|
|
46
49
|
import { signalBus } from '../signal-bus/index.js';
|
|
@@ -107,8 +110,25 @@ export async function* runWorkflow(
|
|
|
107
110
|
yield { type: 'workflow_start', workflow: opts.workflow.name, runId, mode };
|
|
108
111
|
|
|
109
112
|
let order: string[];
|
|
113
|
+
let graphRecipes: Readonly<Record<string, DagNode>> | undefined;
|
|
110
114
|
try {
|
|
111
|
-
|
|
115
|
+
// WF2G supplies the graph cursor. The compatibility adapter owns workflow
|
|
116
|
+
// events, substitution, pins and persistence; graph-runner's file/command
|
|
117
|
+
// recipes do not execute workflow nodes yet.
|
|
118
|
+
const graphEnabled = getUserConfig().raw.workflowGraphEnabled !== false;
|
|
119
|
+
const conversion = graphEnabled ? workflowToGraph(opts.workflow) : null;
|
|
120
|
+
if (conversion?.ok) {
|
|
121
|
+
try {
|
|
122
|
+
order = walkWorkflowGraph(conversion.graph);
|
|
123
|
+
graphRecipes = conversion.graph.recipes;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
debug.log('graph.unify', 'wf-fallback', { file: opts.workflow.name, reason: String(error) });
|
|
126
|
+
order = topoSort(opts.workflow.nodes);
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
if (conversion) debug.log('graph.unify', 'wf-fallback', { file: opts.workflow.name, reason: conversion.reason });
|
|
130
|
+
order = topoSort(opts.workflow.nodes);
|
|
131
|
+
}
|
|
112
132
|
} catch (err) {
|
|
113
133
|
yield {
|
|
114
134
|
type: 'workflow_failed',
|
|
@@ -119,7 +139,9 @@ export async function* runWorkflow(
|
|
|
119
139
|
return {};
|
|
120
140
|
}
|
|
121
141
|
|
|
122
|
-
const nodeById =
|
|
142
|
+
const nodeById = graphRecipes
|
|
143
|
+
? new Map(Object.entries(graphRecipes))
|
|
144
|
+
: new Map(opts.workflow.nodes.map(n => [n.id, n] as const));
|
|
123
145
|
const startIndex = opts.fromNode ? order.indexOf(opts.fromNode) : 0;
|
|
124
146
|
const outputs: Record<string, NodeOutput> = {};
|
|
125
147
|
if (startIndex < 0 || (opts.onlyNode && !nodeById.has(opts.onlyNode))) {
|
|
@@ -20,6 +20,33 @@ export interface ScheduleEntry {
|
|
|
20
20
|
trigger: ScheduleTriggerNode['scheduleTrigger'];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// Graph schedules use the same ScheduleEntry shape as workflow nodes; the
|
|
24
|
+
// graph identity is namespaced so a workflow of the same name cannot collide.
|
|
25
|
+
export function graphScheduleEntries(document: unknown): ScheduleEntry[] {
|
|
26
|
+
if (!document || typeof document !== 'object' || Array.isArray(document)) throw new Error('invalid graph YAML');
|
|
27
|
+
const graph = document as Record<string, unknown>;
|
|
28
|
+
const triggers = graph.triggers;
|
|
29
|
+
if (triggers === undefined) return [];
|
|
30
|
+
if (!triggers || typeof triggers !== 'object' || Array.isArray(triggers)) throw new Error('graph triggers must be an object');
|
|
31
|
+
const schedule = (triggers as Record<string, unknown>).schedule;
|
|
32
|
+
if (schedule === undefined) return [];
|
|
33
|
+
if (typeof graph.graph_id !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(graph.graph_id) || graph.graph_id === '.' || graph.graph_id === '..') {
|
|
34
|
+
throw new Error('graph schedule requires a valid graph_id');
|
|
35
|
+
}
|
|
36
|
+
const schedules = Array.isArray(schedule) ? schedule : [schedule];
|
|
37
|
+
return schedules.map((raw, index) => {
|
|
38
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('graph triggers.schedule must contain schedule objects');
|
|
39
|
+
const value = raw as Record<string, unknown>;
|
|
40
|
+
if (value.type === 'cron' && typeof value.cron === 'string' && value.cron.trim()) {
|
|
41
|
+
return { workflowName: `graph:${graph.graph_id}`, nodeId: `schedule:${index}`, trigger: { type: 'cron', cron: value.cron } };
|
|
42
|
+
}
|
|
43
|
+
if (value.type === 'interval' && typeof value.interval === 'number' && Number.isFinite(value.interval) && value.interval > 0) {
|
|
44
|
+
return { workflowName: `graph:${graph.graph_id}`, nodeId: `schedule:${index}`, trigger: { type: 'interval', interval: value.interval } };
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`invalid graph triggers.schedule[${index}]: expected cron or interval`);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
23
50
|
export interface WebhookEntry {
|
|
24
51
|
workflowName: string;
|
|
25
52
|
nodeId: string;
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
// daemon can drive schedule + webhook + (future) discord/telegram
|
|
6
6
|
// uniformly.
|
|
7
7
|
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
import { parse as parseYaml } from 'yaml';
|
|
8
11
|
import { isScheduleTriggerNode } from '../schema.js';
|
|
9
12
|
import type { ScheduleTriggerNode, WorkflowEntry } from '../types.js';
|
|
10
|
-
import type
|
|
13
|
+
import { graphScheduleEntries, type ScheduleEntry } from './registry.js';
|
|
11
14
|
import { startScheduler, type SchedulerHandle, type SchedulerOpts } from './scheduler.js';
|
|
12
15
|
import type { TriggerEmit, TriggerSource, TriggerSubscription } from './source.js';
|
|
13
16
|
|
|
@@ -25,6 +28,8 @@ export interface ScheduleSource extends TriggerSource {
|
|
|
25
28
|
handle(): SchedulerHandle | null;
|
|
26
29
|
/** Subscription snapshot for `daemon.status()`. */
|
|
27
30
|
subscriptions(): TriggerSubscription[];
|
|
31
|
+
/** Subscribe a graph YAML's schedule declarations to the same scheduler. */
|
|
32
|
+
subscribeGraph(file: string, onFire: () => void | Promise<void>): void;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
interface Binding {
|
|
@@ -34,14 +39,30 @@ interface Binding {
|
|
|
34
39
|
onEmit: TriggerEmit;
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
interface GraphBinding {
|
|
43
|
+
file: string;
|
|
44
|
+
scheduleEntry: ScheduleEntry;
|
|
45
|
+
onFire: () => void | Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
export function createScheduleSource(opts: ScheduleSourceOpts = {}): ScheduleSource {
|
|
38
49
|
const bindings: Binding[] = [];
|
|
50
|
+
const graphBindings: GraphBinding[] = [];
|
|
39
51
|
let handle: SchedulerHandle | null = null;
|
|
40
52
|
let started = false;
|
|
41
53
|
|
|
42
54
|
return {
|
|
43
55
|
kind: 'schedule',
|
|
44
56
|
handle: () => handle,
|
|
57
|
+
subscribeGraph(file, onFire) {
|
|
58
|
+
file = resolve(file);
|
|
59
|
+
const schedules = graphScheduleEntries(parseYaml(readFileSync(file, 'utf8')) as unknown);
|
|
60
|
+
for (const scheduleEntry of schedules) {
|
|
61
|
+
if (graphBindings.some(b => b.file === file && b.scheduleEntry.nodeId === scheduleEntry.nodeId)) continue;
|
|
62
|
+
graphBindings.push({ file, scheduleEntry, onFire });
|
|
63
|
+
if (started && handle) handle.add(scheduleEntry);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
45
66
|
subscribe(entry, onEmit) {
|
|
46
67
|
for (const node of entry.definition.nodes ?? []) {
|
|
47
68
|
if (!isScheduleTriggerNode(node)) continue;
|
|
@@ -68,8 +89,13 @@ export function createScheduleSource(opts: ScheduleSourceOpts = {}): ScheduleSou
|
|
|
68
89
|
if (started) return;
|
|
69
90
|
started = true;
|
|
70
91
|
handle = startScheduler({
|
|
71
|
-
registry: bindings.map(b => b.scheduleEntry),
|
|
92
|
+
registry: [...bindings.map(b => b.scheduleEntry), ...graphBindings.map(b => b.scheduleEntry)],
|
|
72
93
|
runWorkflow: async (scheduleEntry) => {
|
|
94
|
+
const graphBinding = graphBindings.find(b => b.scheduleEntry === scheduleEntry);
|
|
95
|
+
if (graphBinding) {
|
|
96
|
+
await graphBinding.onFire();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
73
99
|
const binding = bindings.find(b =>
|
|
74
100
|
b.scheduleEntry.workflowName === scheduleEntry.workflowName
|
|
75
101
|
&& b.scheduleEntry.nodeId === scheduleEntry.nodeId);
|
|
@@ -89,9 +115,10 @@ export function createScheduleSource(opts: ScheduleSourceOpts = {}): ScheduleSou
|
|
|
89
115
|
handle?.stop();
|
|
90
116
|
handle = null;
|
|
91
117
|
bindings.length = 0;
|
|
118
|
+
graphBindings.length = 0;
|
|
92
119
|
started = false;
|
|
93
120
|
},
|
|
94
|
-
subscriptions: () => bindings.map(b => ({
|
|
121
|
+
subscriptions: () => [...bindings, ...graphBindings].map(b => ({
|
|
95
122
|
kind: 'schedule' as const,
|
|
96
123
|
workflowName: b.scheduleEntry.workflowName,
|
|
97
124
|
nodeId: b.scheduleEntry.nodeId,
|