Dog Execution Model: Imperative vs Formula Dispatch
Status: Active Design Doc
Created: 2026-02-27
Problem Statement
Gas Town dogs (daemon patrol routines) use two execution models:
- Imperative Go (ticker fires → Go code runs): Doctor, Reaper, JSONL backup, Dolt backup
- Formula-only (ticker fires → molecule poured → ... nothing): Compactor (was stub),
Janitor(removed)
The formula-only dogs were broken because no agent interprets their molecules from ticker context. The molecule system requires an idle dog to execute the formula, but the ticker fires regardless of dog availability.
After the Beads Flows work, the Compactor has been upgraded to imperative Go. The Janitor dog was removed entirely — test infrastructure migrated from a dedicated port-3308 Dolt test server to testcontainers-go (Docker), eliminating the orphan test database problem at its source.
This document captures the target execution model going forward.
Current State (Post Testcontainers Migration)
| Dog | Model | Works? | Notes |
|---|---|---|---|
| Doctor | Imperative Go (466 lines) | Yes | 7 health checks, GC, zombie kill |
| Reaper | Imperative Go (658 lines) | Yes | Close, purge, auto-close, mail purge |
| JSONL Backup | Imperative Go (619 lines) | Yes | Export, scrub, filter, spike detect, push |
| Dolt Backup | Imperative Go | Yes | Filesystem backup sync |
| Compactor | Imperative Go (new) | Yes | Flatten + GC when commits > threshold |
Target Model
Keep imperative Go for: reliability-critical dogs
Dogs that MUST run on schedule, unattended, with no agent dependency:
- Doctor: Health checks are the foundation. Must run even if all agents are dead.
- Reaper: Data hygiene can't depend on agent availability.
- Compactor: Compaction must run deterministically on its 24h schedule.
- JSONL Backup: Backup integrity can't be left to agent scheduling.
- Dolt Backup: Same as JSONL.
Principle: If the dog's failure would cause a Clown Show, it must be imperative Go.
Migrate to plugin dispatch for: enhancement/opportunistic dogs
Dogs whose failure is merely inconvenient, not catastrophic:
- Future: cosmetic cleanup, metrics collection, log rotation.
Plugin dispatch model
For plugin-dispatched dogs:
- Remove dedicated ticker from daemon
Run()loop - Create
plugins/<dog>/plugin.mdwith cooldown gate handleDogs()dispatches to idle dog when cooldown expires- Dog agent interprets the plugin formula and executes
Key constraint: The handleDogs() dispatch path already exists and works.
The issue is that ticker-based dogs bypass it. Plugin dogs use it correctly.
Migration Path
Future dogs default to plugin
- New dogs should start as plugins unless reliability-critical
- Existing imperative dogs stay as Go (working, tested, reliable)
Decision: Do NOT migrate working imperative dogs
The Doctor, Reaper, Compactor, and backup dogs work reliably as imperative Go. Migrating them to formula+agent would:
- Add a dependency on agent availability
- Introduce latency (agent startup, formula interpretation)
- Risk regression on critical paths
- Gain nothing — they already work
The only dogs that should use formula dispatch are ones where agent intelligence adds value or where the dog's task is inherently non-critical.