Remove Go code that makes workflow decisions. All health checking,
staleness detection, nudging, and escalation belongs in the Deacon
molecule where Claude executes it.
Removed:
- internal/daemon/backoff.go (190 lines) - exponential backoff decisions
- internal/doctor/stale_check.go (284 lines) - staleness detection
- IsFresh/IsStale/IsVeryStale from keepalive.go
- pokeMayor, pokeWitnesses, pokeWitness from daemon.go
- Heartbeat staleness classification from pokeDeacon
Changed:
- Lifecycle parsing now uses structured body (JSON or simple text)
instead of keyword matching on subject line
- Daemon now only ensures Deacon is running and sends simple heartbeats
- No backoff, no staleness classification, no decision-making
Total: ~800 lines removed from Go code
The Deacon molecule will handle all health checking, nudging, and
escalation. Go is now just a message router.
See gt-gaxo epic for full rationale.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The daemon was creating the deacon session in ~/gt (town root) which loaded
the Mayor CLAUDE.md instead of the Deacon CLAUDE.md. Also, tmux SetEnvironment
does not export variables to spawned processes.
Changes:
- Create deacon session in ~/gt/deacon (correct CLAUDE.md)
- Export GT_ROLE=deacon in launch command (process inherits env)
- Apply to both initial launch and restart paths
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shell loops bypassed the proper lifecycle architecture. Now:
- Witness: Launches Claude directly, daemon/deacon health-scan handles restart
- Deacon: Launches Claude directly, daemon detects exit and restarts
- Daemon: ensureDeaconRunning() now checks if Claude is running (pane cmd)
and restarts it if session exists but Claude has exited
- gt deacon restart: Now does stop+start instead of Ctrl-C
This enforces proper lifecycle flow through LIFECYCLE mail and daemon
heartbeat rather than bypassing it with shell loops.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- .beads-ephemeral/ -> .beads-wisp/
- Rename doctor checks: EphemeralCheck -> WispCheck
- Update all docs to use 'transient' for polecats, 'wisp' for molecules
- Preserve 'ephemeral' only as descriptive adjective for wisps
- Steam engine metaphor: wisps are steam vapors that dissipate
Part of Christmas launch wisp terminology unification.
The deacon patrol role is thankless - it gets a nudge every minute.
This adds rotating motivational and educational tips to make it more fun.
Messages include gratitude, encouragement, and tips about Gas Town.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- daemon.go: Add SIGUSR1 handler to process lifecycle requests immediately
- handoff.go: Signal daemon after sending lifecycle mail to deacon/
- mail.go: Show message IDs in hook output for direct reading
Previously, gt handoff would wait up to 5 min for daemon heartbeat poll.
Now lifecycle requests are processed within milliseconds.
Closes gt-zut3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement replaceable notifications to prevent heartbeat stacking when
agents are busy. Only the latest notification per slot is delivered.
Changes:
- Add NotificationManager for tracking pending notifications
- Add SendKeysReplace() that clears input line before sending
- Integrate slot tracking into daemon heartbeat pokes
- Mark notifications consumed when agent shows activity
The system tracks pending notifications in state files and skips
sending if a notification for the same slot is still pending.
When agent activity is detected (keepalive), slots are marked
consumed allowing new notifications to be sent.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Robustness improvements for the Deacon:
- Add DeaconTheme (purple/silver ecclesiastical theme)
- Apply theme to deacon sessions like mayor/witness
- Daemon now auto-starts deacon if not running
- Daemon pokes deacon instead of directly poking mayor/witnesses
- Deacon is responsible for monitoring mayor and witnesses
The daemon is a "dumb scheduler" that keeps the deacon alive.
The deacon (Claude agent) has the intelligence to understand
context and take remedial action when agents are unhealthy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace tmux session scanning with proper rig discovery:
- Primary: Load rigs from mayor/rigs.json via rig manager
- Fallback: Scan town directory for .beads or config.json
- Handle rigs without running witnesses gracefully
Closes gt-oc2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix ~50 errcheck warnings across the codebase:
- Add explicit `_ =` for intentionally ignored error returns (cleanup,
best-effort operations, etc.)
- Use `defer func() { _ = ... }()` pattern for defer statements
- Handle tmux SetEnvironment, KillSession, SendKeysRaw returns
- Handle mail router.Send returns
- Handle os.RemoveAll, os.Rename in cleanup paths
- Handle rand.Read returns for ID generation
- Handle fmt.Fprint* returns when writing to io.Writer
- Fix for-select with single case to use for-range
- Handle cobra MarkFlagRequired returns
All tests pass. Code compiles without errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements per-agent backoff tracking to reduce noise for busy agents:
- AgentBackoff type tracks interval, miss count, and last activity
- BackoffManager manages state across all agents
- Geometric backoff strategy (1.5x factor, 10min cap)
- Integrates with keepalive to skip pokes when agents are fresh
- Resets backoff immediately when activity detected
Closes gt-8bx
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the town daemon (gt-99m) that handles:
- Periodic heartbeat to poke Mayor and Witnesses
- Lifecycle request processing (cycle, restart, shutdown)
- Session management for agent restarts
Commands:
- gt daemon start: Start daemon in background
- gt daemon stop: Stop running daemon
- gt daemon status: Show daemon status and stats
- gt daemon logs: View daemon log file
The daemon is a "dumb scheduler" - all intelligence remains in agents.
It simply pokes them on schedule and executes lifecycle requests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>