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:

  1. Maintains a registry of tasks with cron expressions
  2. Polls or triggers on schedule
  3. Executes each task (spawns Claude Code session or runs a script)
  4. Logs results and errors
  5. 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?

OptionDescription
A) Python daemonLong-running Python process with schedule or APScheduler. Fits Opus’s Python stack (src/).
B) SQLite polling loopNode.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?

OptionDescription
A) SQLite tableTasks 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 markdownEach 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?

OptionDescription
A) Claude Code SDKSpawn a Claude Code session per task (like ClaudeClaw’s runAgent). Full AI capabilities.
B) Python functionsDirect function calls for known tasks (generate briefing, run cleanup). Faster, no AI overhead.
C) HybridSimple 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

PhaseDescriptionStatus
Phase 1Core scheduler with static tasks
Phase 2Dynamic task management (CLI/API)
Phase 3Claude Code integration for AI tasks

Phase 1: Core Scheduler —

Goal: A running process that executes tasks on a cron schedule and logs results.

File / FeatureDetailsOwnerStatus
src/scheduler/main.pyEntry point — polling loop or daemonopus
src/scheduler/registry.pyTask registry — load/store tasksopus
src/scheduler/executor.pyTask execution — run command/function, capture outputopus
src/scheduler/models.pyTask model — id, cron, command, status, last_run, next_runopus
Task loggingLog each run: start, end, result, errorsopus
Seed tasksInitial tasks: daily briefing, dashboard refreshopus

Phase 2: Dynamic Task Management —

Goal: Create, list, pause, resume, and delete tasks without editing code.

File / FeatureDetailsOwnerStatus
src/scheduler/cli.pyCLI for task CRUD: python -m scheduler create/list/pause/deleteopus
Pause/resumeToggle task status without deletingopus
Task historyStore last N results per task for debuggingopus

Phase 3: Claude Code Integration —

Goal: Allow tasks to spawn Claude Code sessions for AI-powered work.

File / FeatureDetailsOwnerStatus
src/scheduler/agent.pyClaude Code SDK wrapper — spawn session, collect resultopus
Session managementPer-task session persistence (optional)opus
Notification on resultSend task output via notification system (FR-049)opus

Prerequisites / Gap Analysis

Requirements

RequirementDescription
REQ-1Python environment set up (src/ scaffolded)
REQ-2For Phase 3: Claude Code SDK (@anthropic-ai/claude-agent-sdk) or Python equivalent
REQ-3For always-on: FR-019 (VPS Deployment) or local daemon

Current State

ComponentStatusDetails
Python project (src/)Not yet scaffolded
Claude Code SDKAvailable but not integrated
VPSFR-019 not started

Gap (What’s missing?)

GapEffortBlocker?
Python project scaffoldLowYes — need src/ before anything
Scheduler implementationMedCore of this FR
VPS for always-onMedNo — can run locally first

Test

Manual tests

TestExpectedActualLast
pending-

AI-verified tests

ScenarioExpected behaviorVerification method

E2E tests

ScenarioAssertion

Integration tests

ComponentCoverage

Unit tests

ComponentTestsCoverage

History

DateEventDetails
2026-03-04CreatedExtracted 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