Skip to content

Back to Roadmap Index

Phase 5: Daemon ✅ COMPLETED

Goal: Build the main daemon process that ties everything together.

Status: ✅ Completed on 2026-01-22 (Commit: b9b9714)

Tasks

  1. Daemon Class (src/reeve/pulse/daemon.py) ✅
  2. Implemented PulseDaemon class (273 lines)
  3. Implemented _scheduler_loop() - polls every 1 second
  4. Implemented _execute_pulse() - async pulse execution with error handling
  5. Handles prompt building with sticky notes via PulseExecutor
  6. Graceful shutdown (SIGTERM/SIGINT) with 30-second grace period
  7. See Daemon & API

  8. Logging (src/reeve/utils/logging.py) ✅

  9. Implemented setup_logging() function (72 lines)
  10. RotatingFileHandler with 10MB max, 5 backups
  11. Structured logging format
  12. Console + file output (configurable)

  13. Entry Point (src/reeve/pulse/__main__.py) ✅

  14. Implemented module entry point (59 lines)
  15. Configuration loading and logging setup
  16. Graceful KeyboardInterrupt handling

  17. Testing

  18. 21 comprehensive unit tests (tests/test_pulse_daemon.py)
  19. 2 integration/validation tests (tests/test_phase5_validation.py)
  20. All tests pass: 94/94

Deliverables

  • ✅ Functional daemon process
  • ✅ Pulse execution working end-to-end
  • ✅ Proper logging with file rotation
  • ✅ Comprehensive test suite

Validation

# Terminal 1: Start daemon
uv run python -m reeve.pulse

# Terminal 2: Schedule pulse via MCP (in Claude Code)
schedule_pulse(
    scheduled_at="in 10 seconds",
    prompt="Test pulse execution",
    priority="high"
)

# Terminal 1: Watch logs for execution
# Should see: "Executing pulse X: Test pulse execution..."
# Should see: "Pulse X completed successfully in Yms"

Demo

Step 1: Start the daemon

# Terminal 1: Start daemon in foreground
uv run python -m reeve.pulse

# Expected output:
# 2026-01-19 10:30:00 | INFO | Starting Pulse Daemon...
# 2026-01-19 10:30:00 | INFO | Database: ~/.reeve/pulse_queue.db
# 2026-01-19 10:30:00 | INFO | Scheduler loop started (polling every 1s)
# 2026-01-19 10:30:00 | INFO | Ready to execute pulses

Step 2: Schedule pulses via MCP (in Claude Code or via demo script)

# Terminal 2: Run the demo script
uv run python demos/phase5_daemon_demo.py

# The script will:
# 1. Schedule 3 pulses with different priorities and timing
# 2. Watch the daemon execute them in priority order
# 3. Verify retry logic on simulated failures
# 4. Test graceful shutdown

Expected daemon output

2026-01-19 10:30:05 | INFO | Found 3 due pulses
2026-01-19 10:30:05 | INFO | Executing pulse #1 (CRITICAL): "Emergency system check"
2026-01-19 10:30:05 | INFO | Launching Hapi session...
2026-01-19 10:30:08 | INFO | Pulse #1 completed successfully (3.2s)
2026-01-19 10:30:10 | INFO | Executing pulse #2 (HIGH): "Morning briefing"
2026-01-19 10:30:10 | INFO | Launching Hapi session...
2026-01-19 10:30:13 | INFO | Pulse #2 completed successfully (2.8s)
2026-01-19 10:30:15 | INFO | Executing pulse #3 (NORMAL): "Check calendar"
2026-01-19 10:30:15 | INFO | Launching Hapi session...
2026-01-19 10:30:18 | INFO | Pulse #3 completed successfully (2.1s)

Step 3: Test retry logic

# The demo script will schedule a pulse that intentionally fails
# Expected daemon output:
2026-01-19 10:31:00 | INFO | Executing pulse #4 (HIGH): "Flaky task"
2026-01-19 10:31:00 | INFO | Launching Hapi session...
2026-01-19 10:31:02 | ERROR | Pulse #4 failed: Hapi returned error code 1
2026-01-19 10:31:02 | INFO | Scheduling retry #1 in 2 minutes
2026-01-19 10:33:02 | INFO | Executing pulse #5 (HIGH): "Flaky task (retry 1)"
2026-01-19 10:33:02 | INFO | Launching Hapi session...
2026-01-19 10:33:05 | INFO | Pulse #5 completed successfully (2.5s)

Step 4: Test graceful shutdown

# In Terminal 1, press Ctrl+C
^C2026-01-19 10:35:00 | INFO | Received shutdown signal
2026-01-19 10:35:00 | INFO | Waiting for 1 running pulse to complete...
2026-01-19 10:35:02 | INFO | All pulses completed
2026-01-19 10:35:02 | INFO | Daemon shut down gracefully

Previous: Phase 4: Pulse Executor

Next: Phase 6: HTTP API