Repository navigation
OpenCode scheduled tasks: migrate the Muse→OpenCode cron wrappers into OpenChamber scheduled tasks (waves, monitoring gates) #2174
Description
What this is
Drew, 2026-10-29: find where OpenCode-native scheduled tasks can replace the Muse cron jobs that currently launch OpenCode — to save Muse tokens or raise throughput — with proper management and monitoring of those tasks and their outcomes. Study: ~/workspace/research_notes/opencode-scheduled-tasks-20261029/findings.md.
Verdict: PARTIAL — the trigger exists, in OpenChamber, not OpenCode
- OpenCode core has no scheduler. Zero cron/timer code in packages/core|server|cli; sessions are purely event-driven.
- OpenChamber has a real scheduled-tasks subsystem (packages/web/server/lib/scheduled-tasks/): cron/daily/weekly/once with timezones, per-project + chats scopes, new-session-per-run (model/agent pinning, permission auto-accept, goal mode with token budget, sessions stamped metadata.kind='scheduled') or prompt-into-existing-session, cross-instance occurrence claiming, loop files (.agents/loops/*.md), REST + UI + CLI + an agent tool (openchamber_schedule).
- But it is a prompt scheduler, not a job system: state holds only the last run, no token capture, no alerting, in-code defaults of 4 global / 2 per-project concurrent runs, and a 30-minute run cap (vs ~90-minute shift windows).
Migration waves (Claude input tokens, trailing-24h, runtime-DB attribution)
Wave 1 (~3.4B/day of the fleet's ~5.1B/day):
- Repo-queue worker shifts — ~2.26B/day, save ~2.1–2.2B. The Muse layer is claim/checkpoint/terminal-verbs via repo-queue.py plus implementation over laptop-ssh — the identical runbook an OpenCode session already executes when dispatcher-launched. Ports near-verbatim as per-queue scheduled tasks. Blockers: repo-queue.py must run laptop-side; sandbox lane-lock files replaced by the atomic DB claim; run cap raised.
- Issue creators — ~0.96B/day, save ~0.9B. The runbook already is a self-contained prompt. One API-created scheduled task per repo-lane. Note: this reprices the 3.93M-Claude-tokens/filed-issue figure behind Drew's held creator-throttle decision into pool tokens.
- OpenChamber dispatcher + babysitter — ~390M/day, save ~350–370M. The most rule-bound jobs in the fleet, currently spending Claude tokens operating the API of the system that would run the loop natively. Port as existing-session scheduled pokes into persistent sessions (cross-round state lives in session context instead of being re-read at ~1.4M/run).
Wave 2 (~0.25B): fleet-monitor, pr-diff pair, issue-sweep, pool-quota-steward (partial fits).
Keep on Muse: fleet-watchdog (it is the monitor — it must instead gain coverage of the OpenChamber tasks) and orchestration-pass (the consumer/escalation collector).
The honest trade
The throughput ceiling moves from Claude-subscription/cron concurrency to pool quotas + the laptop's 12-session cap. At a known-100% pool the native fleet stalls where Muse lanes currently sail past. This makes the migration dependent on the full-quota utilization program (#2173) keeping pools fed and rotated.
Gating monitoring gaps (fix before migrating anything)
- Per-run history — scheduled-task state is last-run-only (laptop JSON). Consume the already-emitted
openchamber:scheduled-task-ranSSE events into Supabase. - Token accounting — every OpenCode assistant message already carries cost + tokens (schema/session-message.ts), but nothing exports it; the mirror covers only the Muse runtime. Build an OpenCode-side exporter twin of runtime-db-export (this is External-system observability: unified PM + queue + quota attribution (webhooks, hot list, session IDs, projections) #2072 work).
- Failure alerting / dead-man's switch — fleet-watchdog polls GET /api/openchamber/scheduled-tasks/status + queue-claim staleness.
- Server residency — the scheduler dies with the OpenChamber server process; confirm the laptop deployment is always-on (not socket-activated or idle-stopped).
- Shared-state locality — fleet bookkeeping (backlogs, sweep.log, lane locks) is sandbox-resident; OpenCode sessions are laptop-resident. Move per-job state to Supabase, following the queue pattern.
- Identity binding (task id / session id / queue task id in one place), the loop-file approval gate (silently pauses migrated jobs), escalation path for urgent classes.
Acceptance
- Gaps 1–4 closed and demonstrated on one pilot: ONE queue lane running as an OpenChamber scheduled task for 48h with per-run history, token accounting, and watchdog coverage — reviewed against its Muse-cron baseline (outcome, tokens, time), then a go/no-go for the rest of wave 1.
Acceptance criteria
- Each Muse cron wrapper that launches OpenCode is inventoried (in the linked study or a comment here) with a disposition: migrated to an OpenChamber scheduled task, kept on Muse cron with a named reason, or retired.
- Migrated tasks run in waves with monitoring gates between waves: a wave's runs are observed completing (run records + outcome checks) before the next wave migrates.
- For every migrated task, the Muse-token cost change is measured or explicitly estimated, and any throughput change is noted — the migration's stated purpose is token savings or throughput, so the result must say which it got.
Activity
developing-today commentedon Oct 29, 2026
CODE-1067
dezren39 commentedon Oct 29, 2026
DREW DIRECTION (2026-10-29, main chat) — corrections to this issue's framing:
The 'gates' in the issue body are hereby build tasks, not gates: per-run history export (from the OpenCode DB), watchdog monitoring of the scheduled tasks, residency confirmation. First build dispatched 2026-10-29: two queue lanes as OpenChamber scheduled tasks, additive, DB-claim only, Muse lanes untouched.
dezren39 commentedon Oct 29, 2026
OpenChamber scheduled lanes — LIVE (additive, per Drew's direction 2026-10-29)
Two OpenChamber scheduled tasks now run the repo-health queues ADDITIVELY alongside the existing Muse cron lanes. No Muse cron job was touched; no OpenChamber/OpenCode config file was edited outside the scheduled-tasks CLI.
repo-health-code-pilot)8ac61616-3815-4e7b-b33d-840a3829154a/home/user/git/code*/40 * * * *, America/Chicagoopencode-route/workhorse(route pool, no raw model pin) /buildrepo-health-opencode-pilot)3fe37e8a-c61b-419c-9e97-769ecd264d5d/home/user(no OpenChamber project exists for~/git/opencode; the prompt anchors the session at~/git/opencodeand uses absolute worktree paths)*/40 * * * *, America/Chicagoopencode-route/workhorse/buildEach task's prompt = a lane header + the SAME per-repo worker runbook the Muse lanes execute, verbatim. Header adaptations only: no sandbox lane-lock files (the atomic DB claim is the only claim), health gate first, worktrees under
~/git/fleet, ~30-min run discipline with terminal park/complete verbs, first checkpoint carries"origin": "openchamber-scheduled-lane"for audit, sandbox backlog/sweep-log writes skipped (bookkeeping noted in thecomplete()result instead). Worker ids unchanged (repo-worker-code/repo-worker-opencode).Verification (2026-10-29, fleet clock UTC)
repo-queue.py healthruns on the laptop against Supabase;openchamber scheduleCLI surface works; quota re-read before triggering — no workhorse pool walled.ses_e5e795f9576ffe8tuA71C91x8c, opencode sessionses_e5e795f8099ffeWHVRz8NTmgh8.ses_e5e7953b638ffenCsU6ORljLIC, opencode sessionses_e5e7953b16fffevBgwWxHh8ur1; next occurrence 08:40Z. Both tasks remain ENABLED.agent.tasks.progress): OpenChamber lanes claimed tasks 2827, 2828, 3227, 2833 (code) and 2712, 2705, 2900 (opencode) — all distinct ids; Muse lanes claimed different tasks in the same window (2661, 2681, plus the pre-existing 2821/2825/2990/2826/3223). No task was double-claimed. The atomic claim is doing its job.Notes / watch items:
awaiting_cisince 07:49Z — within its 45-min lease; the queue's lease machinery is the backstop if its session died waiting on CI.~/workspace/research_notes/opencode-scheduled-tasks-20261029/rollout.md(sandbox).dezren39 commentedon Oct 29, 2026
Second OpenChamber scheduled lane for the code queue is live (Drew's direction, 2026-10-29) — mirroring the first code lane exactly: task
2717091f-6f5a-4a46-beae-5e7db58d376b, project /home/user/git/code, cron*/40 * * * *America/Chicago, model opencode-route/workhorse, agent build, new session per run, same lane prompt (header + code worker runbook verbatim), atomic DB claim only, origin markeropenchamber-scheduled-lane. The CLI accepted the identical task name with no refusal.Verification: manual trigger → session ses_e5e793aea23ffeFylbU3awqnEu (lastStatus success). Its first claim landed 51s after dispatch: task 2869 (triage of code#1968), claimed 2026-10-29T08:27:56Z with the origin marker in its first checkpoint, attempts=1. No first-lane cron occurrence existed in that window, and the concurrent Muse-lane claims (2864, 2866, 2871) carry no origin marker — zero overlap, the atomic claim held across two OpenChamber code lanes + the Muse lanes. Left ENABLED on the regular */40 cadence. Full record: rollout addendum in ~/workspace/research_notes/opencode-scheduled-tasks-20261029/rollout.md. No existing lane or Muse cron was touched.
dezren39 commentedon Oct 29, 2026
Intake review
kind/infrastructure,source/human(Drew's 2026-10-29 directive quoted in the body),status/needs-triage,priority/high,effort/l,meta/enriched; AC appended.dezren39 commentedon Oct 31, 2026
Lane expansion — Drew, 2026-10-31 ~07:56 CDT: +4 code, +1 openchamber, +1 nix OpenChamber scheduled lanes.
Created via the laptop
openchamber scheduleCLI, all ENABLED, all cron*/40 * * * *America/Chicago, modelopencode-route/workhorse, agentbuild, new session per run, origin markeropenchamber-scheduled-lane:c29174f1-48e0-4b13-b4ff-9b73ab67e9ab,262eb403-3347-4a7c-ba6b-e7bc263ca853,335a5d1f-bfc1-4831-99ea-850c8939a727,7b47536b-c162-444c-be8a-3a9538cc4cb5(project ~/git/code; staged lane prompt reused verbatim)46984602-51a3-438c-b3a5-f2857811adb1(project /home/user — no registered project for this repo; prompt anchors at the primary clone ~/git/openchamber-fork)8d133595-c60c-4dcb-8e82-59b7d0ac9b5a(project /home/user; prompt anchors at ~/code/dezren39-nix)Openchamber/nix prompts = the 2026-10-29 rollout header adaptations + each queue's own worker runbook verbatim; staged in hatch-personal
workspace/research_notes/opencode-scheduled-tasks-20261029/prompts/(commit d95bfaf7b) and copied to the laptop with sha256 verification.Verification: manual triggers of one new code lane (session ses_e5e6df34549ffeX6juJcU0fKTk), the openchamber lane (ses_e5e6df34345ffePROYiiixfhjY), and the nix lane (ses_e5e6df34175ffewvlbwb0qw4Lm) all ended
lastStatus=success. The nix queue currently holds 0 queued tasks, so that lane idles until work lands. Pre-flight quota read (aggregator, 12:45Z): workhorse route doors have weekly headroom (opencode-go.personal 39%, opencode-go.lab 75%, command-code 64%); the Meta reserve door reads 100% weekly.Store inventory now: 9 enabled queue lanes (code ×6, opencode ×1, openchamber ×1, nix ×1) plus the #3026 claimant task (disabled).
Two discrepancies vs the 2026-10-29 record — flagged, not silently fixed:
2717091fis no longer in the store. The second code lane present is9aca43b4-5439-4939-9f71-323f5d32521b: prompt byte-identical to the lane prompt, but cron is20,40 * * * *and the model is unset (falls back to the project default instead of the pinned workhorse route).8 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
opencode. Revalidated fresh this claim (2026-11-04T07:04Z): issue OpenCode scheduled tasks: migrate the Muse→OpenCode cron wrappers into OpenChamber scheduled tasks (waves, monitoring gates) #2174 OPEN, no held / user/owned / do-not-merge / do-not-auto-edit labels; claim labels synced this note (removed queue/queued + status/needs-triage; added work/assigned, queue/claimed, status/in-progress).dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 4, 2026
🤖 Agent note · triaged / recommendation recorded
Fresh check — gates and pilot
openchamber:scheduled-task-ran; the live scheduled-task records retain only latest-run fields. The OpenCode session/message APIs preserve individual run evidence, but this pass found no consumer persisting scheduled-run events into Supabase. At 2026-11-04 07:19Z the code project had 12 enabled queue lanes (11 on*/40, one on20,40); 7 latest sessions were still active, so schedulerlastStatus=successalone is not a terminal outcome record.session_v2/session_messagehistory). On this laptopopencode-usage-export.timeris active andstate.jsonreports last tick2026-11-04T07:15:13Z;latest.jsonandhistory.jsonlare present. This verifies per-session export, but not a normalized OpenChamber-vs-Muse comparison for this pilot.2026-11-03T20:56:27Z, and user lingering is enabled. The scheduler itself is process-local, however, so laptop sleep, shutdown, or power loss still interrupts it.Recommendation to Drew: NO-GO for any Muse cutover/retirement; continue only the additive scheduled lanes while closing the missing run-history/watchdog evidence and collecting relative outcome, token, and elapsed-time data. This is a recommendation, not a cutover decision; no schedule was changed.