Decisions
- Pending: Runtime approach — Python daemon, systemd timers, or SQLite polling loop?
- Pending: Task registration — config file (YAML/TOML), SQLite, or vault markdown?
- Pending: Where does it run — local first or VPS-only?
User Tasks
Summary
A task scheduler that runs timed/recurring tasks autonomously — the missing foundation that multiple FRs depend on.
Problem / Motivation
Multiple FRs assume scheduled execution exists but none define it:
- FR-037 (Daily Briefings) needs a daily cron to refresh dashboards and generate briefings
- FR-048 (System Self-Review) needs scheduled doc freshness checks
- FR-032 (Auto Cleaning) needs periodic vault/code maintenance
- FR-019 (VPS Deployment) Phase 2 says “set up cron jobs” without defining how
- FR-067 (External Repo Research) wants a scheduled GitHub scan
Without a scheduler, none of these can run autonomously. It’s the single biggest blocker for Opus to move from interactive-only to always-on.
Proposed Solution
A lightweight task runner that:
- Maintains a registry of tasks with cron expressions
- Polls or triggers on schedule
- Executes each task (spawns Claude Code session or runs a script)
- Logs results and errors
- Sends notifications on failure (ties into FR-049)
Reference: ClaudeClaw’s scheduler pattern (see vault/00_system/external/Internet/REBUILD_PROMPT.md) — SQLite-backed polling loop checking every 60s, cron-parser for schedule expressions, task CRUD via CLI.
Open Questions
1. Runtime Approach
Question: How should the scheduler process run?
| Option | Description |
|---|---|
| A) Python daemon | Long-running Python process with schedule or APScheduler. Fits Opus’s Python stack (src/). |
| B) SQLite polling loop | Node.js/Python process polling SQLite every 60s (ClaudeClaw pattern). Simple, proven. |
| C) System-level (cron/systemd timers) | OS-native scheduling. No custom daemon needed. Less portable, harder to manage tasks dynamically. |
Recommendation: Option A or B — both allow dynamic task management. System-level cron is too rigid for tasks that Opus itself should be able to create/modify.
Decision:
2. Task Registration
Question: How are tasks defined and stored?
| Option | Description |
|---|---|
| A) SQLite table | Tasks stored in SQLite with cron expression, prompt/command, status. Easy CRUD, queryable. ClaudeClaw pattern. |
| B) Config file (YAML) | Static file listing tasks and schedules. Simple, version-controlled, but harder to modify at runtime. |
| C) Vault markdown | Each task is a markdown file in vault/. Visible in Obsidian but overkill for simple cron entries. |
Recommendation: Option A — SQLite is the natural fit for runtime state. A seed config file can populate initial tasks.
Decision:
3. Task Execution
Question: How does the scheduler run a task?
| Option | Description |
|---|---|
| A) Claude Code SDK | Spawn a Claude Code session per task (like ClaudeClaw’s runAgent). Full AI capabilities. |
| B) Python functions | Direct function calls for known tasks (generate briefing, run cleanup). Faster, no AI overhead. |
| C) Hybrid | Simple tasks run as Python functions, complex tasks spawn Claude Code. |
Recommendation: Option C — briefing generation needs AI, but dashboard refresh is just file parsing.
Decision:
Phase Overview
| Phase | Description | Status |
|---|---|---|
| Phase 1 | Core scheduler with static tasks | — |
| Phase 2 | Dynamic task management (CLI/API) | — |
| Phase 3 | Claude Code integration for AI tasks | — |
Phase 1: Core Scheduler —
Goal: A running process that executes tasks on a cron schedule and logs results.
| File / Feature | Details | Owner | Status |
|---|---|---|---|
src/scheduler/main.py | Entry point — polling loop or daemon | opus | — |
src/scheduler/registry.py | Task registry — load/store tasks | opus | — |
src/scheduler/executor.py | Task execution — run command/function, capture output | opus | — |
src/scheduler/models.py | Task model — id, cron, command, status, last_run, next_run | opus | — |
| Task logging | Log each run: start, end, result, errors | opus | — |
| Seed tasks | Initial tasks: daily briefing, dashboard refresh | opus | — |
Phase 2: Dynamic Task Management —
Goal: Create, list, pause, resume, and delete tasks without editing code.
| File / Feature | Details | Owner | Status |
|---|---|---|---|
src/scheduler/cli.py | CLI for task CRUD: python -m scheduler create/list/pause/delete | opus | — |
| Pause/resume | Toggle task status without deleting | opus | — |
| Task history | Store last N results per task for debugging | opus | — |
Phase 3: Claude Code Integration —
Goal: Allow tasks to spawn Claude Code sessions for AI-powered work.
| File / Feature | Details | Owner | Status |
|---|---|---|---|
src/scheduler/agent.py | Claude Code SDK wrapper — spawn session, collect result | opus | — |
| Session management | Per-task session persistence (optional) | opus | — |
| Notification on result | Send task output via notification system (FR-049) | opus | — |
Prerequisites / Gap Analysis
Requirements
| Requirement | Description |
|---|---|
| REQ-1 | Python environment set up (src/ scaffolded) |
| REQ-2 | For Phase 3: Claude Code SDK (@anthropic-ai/claude-agent-sdk) or Python equivalent |
| REQ-3 | For always-on: FR-019 (VPS Deployment) or local daemon |
Current State
| Component | Status | Details |
|---|---|---|
Python project (src/) | — | Not yet scaffolded |
| Claude Code SDK | — | Available but not integrated |
| VPS | — | FR-019 not started |
Gap (What’s missing?)
| Gap | Effort | Blocker? |
|---|---|---|
| Python project scaffold | Low | Yes — need src/ before anything |
| Scheduler implementation | Med | Core of this FR |
| VPS for always-on | Med | No — can run locally first |
Test
Manual tests
| Test | Expected | Actual | Last |
|---|---|---|---|
| … | … | pending | - |
AI-verified tests
| Scenario | Expected behavior | Verification method |
|---|---|---|
| … | … | … |
E2E tests
| Scenario | Assertion |
|---|---|
| … | … |
Integration tests
| Component | Coverage |
|---|---|
| … | … |
Unit tests
| Component | Tests | Coverage |
|---|---|---|
| … | … | … |
History
| Date | Event | Details |
|---|---|---|
| 2026-03-04 | Created | Extracted from multiple FRs that assumed scheduling existed |
References
- FR-037 (Daily Briefings) — first consumer: daily dashboard refresh + briefing generation
- FR-048 (System Self-Review) — scheduled doc freshness checks
- FR-032 (Auto Cleaning) — periodic vault/code maintenance
- FR-019 (VPS Deployment) — provides always-on runtime
- FR-067 (External Repo Research) — scheduled GitHub scans
- FR-049 (Error Logging) — monitors scheduler failures
- FR-066 (Self-Improving System) — autonomous execution depends on scheduler
- ClaudeClaw Rebuild Prompt — reference implementation for SQLite + cron polling pattern