scheduled-tasks dispatcher stopped honoring SKILL.md `model:` frontmatter on/around 2026-04-27 ~01-02 UTC

Resolved 💬 2 comments Opened May 5, 2026 by andidundeecomm Closed May 29, 2026

Bug: scheduled-tasks dispatcher stopped honoring SKILL.md model: frontmatter on/around 2026-04-27 ~01–02 UTC

Summary

As of approximately 2026-04-27 01:00–02:30 UTC, the Claude Code scheduled-tasks dispatcher stopped reading the model: frontmatter field in ~/.claude/scheduled-tasks/{id}/SKILL.md. Every scheduled task now runs on Opus regardless of what its frontmatter says — including tasks set to sonnet and tasks set to haiku. Pre-04-27 sessions for the same tasks ran on Sonnet/Haiku as the frontmatter specified.

This is a global behaviour change, not a per-task regression. Editing or re-saving SKILL.md after the change has no effect.

For Pro users this is invisibly costly (quota burn). For API users it's ~3× cost.

Environment

  • Claude Code desktop app, Windows 11
  • ~/.claude/scheduled-tasks/{id}/SKILL.md storage layout
  • mcp__scheduled-tasks__create_scheduled_task / update_scheduled_task / list_scheduled_tasks
  • Session metadata at %APPDATA%/Claude/claude-code-sessions/<root>/<group>/local_*.json

Evidence: coordinated transition across 12 tasks within a 2-hour window

For each task with model: sonnet (or model: haiku) in frontmatter, I extracted the timestamp of the last Sonnet/Haiku session and the first Opus session that followed:

| Task | Frontmatter | Last non-Opus session (UTC) | First Opus session after (UTC) |
|---|---|---|---|
| meeting-digest-sweeper | sonnet | 2026-04-27 00:51 | 2026-04-27 01:06 |
| vbe-workflow-sync | sonnet | 2026-04-26 23:45 | 2026-04-27 02:08 |
| vbe-cache-refresh | haiku | 2026-04-26 23:45 | 2026-04-27 02:15 |
| learn-system-sync | sonnet | 2026-04-26 23:45 | 2026-04-27 02:18 |
| vbe-comment-staleness | sonnet | 2026-04-26 23:47 | 2026-04-27 02:19 |
| migration-matrix-refresh | (no model: line) | 2026-04-26 23:52 | 2026-04-27 02:28 |
| learn-daily-digest | sonnet | 2026-04-26 23:53 | 2026-04-27 16:10 |
| verify-scheduled-jobs | sonnet | 2026-04-26 23:53 | 2026-04-27 16:10 |
| onb-sync | sonnet | 2026-04-26 23:58 | 2026-04-27 16:13 |
| standup-digest | sonnet | 2026-04-27 00:51 | 2026-04-27 23:08 |
| learn-pending-processor | sonnet | 2026-04-28 18:06 | 2026-04-28 19:06 |
| learn-weekly-audit | sonnet | 2026-04-26 23:48 | 2026-05-03 22:29 (next dispatch — weekly) |

The "first Opus after" times trail by however long it took each task's cron to fire next. The earliest Opus session is 2026-04-27 01:06 UTC. Every task's very next dispatch after that boundary returned Opus, regardless of frontmatter.

Tasks that legitimately have model: opus (e.g. learn-monthly-audit, standup-digest-audit) and tasks with no model: line still run Opus — these are matching by accident or by default, not by the dispatcher reading frontmatter.

Why this isn't "the SKILL.md edits broke things"

A task's prior verification report attributed the regression to SKILL.md frontmatter edits made on 2026-04-29 to five specific tasks. That framing is wrong:

  • The transition happened ~2 days earlier (04-27 ~01 UTC) and affected every task with non-Opus frontmatter, not just the 5 that were later edited.
  • The 04-29 edits to those 5 SKILL.md files had no effect either way — the dispatcher had already stopped reading frontmatter.

Reproduction

  1. Pick any active scheduled task whose SKILL.md frontmatter has model: sonnet. Confirm via local_*.json that recent runs use claude-opus-4-7[1m].
  2. Compare against earlier runs (pre-2026-04-27) — they used claude-sonnet-4-6.
  3. Edit the file: re-save with the same model: sonnet line, or remove and re-add it. Wait for the next dispatch. Model is still claude-opus-4-7[1m].
  4. Try update_scheduled_task mutations:
  • update_scheduled_task(taskId, description=<same value>) → next dispatch still Opus.
  • update_scheduled_task(taskId, enabled=false) then update_scheduled_task(taskId, enabled=true, fireAt=<near future>) → next dispatch still Opus. (Verified 2026-05-05 00:03 UTC on migration-matrix-refresh.)
  • update_scheduled_task(taskId, fireAt=<near future>) on an active task → next dispatch still Opus. (Verified 2026-05-04 21:52 UTC on migration-matrix-refresh.)

Why we can't work around it

  • mcp__scheduled-tasks__create_scheduled_task schema has no model parameter.
  • There's no delete_scheduled_task tool — can't delete and recreate within the MCP.
  • Filesystem-level deletion of ~/.claude/scheduled-tasks/{id}/ would orphan whatever scheduler state the runner keeps elsewhere.
  • Setting the global default via ~/.claude/settings.json "model": "sonnet" does NOT help, even after a full Claude Code app restart. Verified 2026-05-05: after adding "model": "sonnet" to user-level settings.json, restarting the desktop app, and letting cron-driven dispatches fire naturally, every scheduled-task session still launched on Opus. Sample (post-restart cron firings, 2026-05-05 02:46–02:47 UTC):
  • vbe-workflow-sync (frontmatter: sonnet) → Opus
  • vbe-cache-refresh (frontmatter: haiku) → Opus
  • learn-system-sync (frontmatter: sonnet) → Opus

Neither the frontmatter nor the global default is read at dispatch time. The dispatcher appears to have its own hardcoded or per-task-cached model selection that no user-facing config affects.

Asks

  1. Restore frontmatter-honoring behaviour at dispatch time, OR expose model as an explicit parameter on create_scheduled_task and update_scheduled_task.
  2. Add a delete_scheduled_task tool to the mcp__scheduled-tasks__* surface.
  3. Document the current behaviour in the meantime so users on Pro plans know their model: sonnet configurations are silently being ignored.

Workaround currently in use

Disabled the most expensive scheduled tasks (enabled: false) until a fix lands.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗