Add rotating MOTD messages to deacon heartbeat
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>
This commit is contained in:
@@ -24,13 +24,14 @@ import (
|
|||||||
|
|
||||||
// Daemon is the town-level background service.
|
// Daemon is the town-level background service.
|
||||||
type Daemon struct {
|
type Daemon struct {
|
||||||
config *Config
|
config *Config
|
||||||
tmux *tmux.Tmux
|
tmux *tmux.Tmux
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
backoff *BackoffManager
|
backoff *BackoffManager
|
||||||
notifications *NotificationManager
|
notifications *NotificationManager
|
||||||
|
lastMOTDIndex int // tracks last MOTD to avoid consecutive repeats
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new daemon instance.
|
// New creates a new daemon instance.
|
||||||
@@ -158,6 +159,39 @@ const DeaconRole = "deacon"
|
|||||||
// DeaconPatrolMolecule is the well-known ID for the deacon patrol molecule.
|
// DeaconPatrolMolecule is the well-known ID for the deacon patrol molecule.
|
||||||
const DeaconPatrolMolecule = "mol-deacon-patrol"
|
const DeaconPatrolMolecule = "mol-deacon-patrol"
|
||||||
|
|
||||||
|
// deaconMOTDMessages contains rotating motivational and educational tips
|
||||||
|
// for the Deacon heartbeat. These make the thankless patrol role more fun.
|
||||||
|
var deaconMOTDMessages = []string{
|
||||||
|
"Thanks for keeping the town running!",
|
||||||
|
"You are Gas Town's most critical role.",
|
||||||
|
"You are the heart of Gas Town! Be watchful!",
|
||||||
|
"Tip: Polecats are ephemeral - spawn freely, kill liberally.",
|
||||||
|
"Tip: Witnesses monitor polecats; you monitor witnesses.",
|
||||||
|
"Tip: Wisps are ephemeral molecules for patrol cycles.",
|
||||||
|
"The town sleeps soundly because you never do.",
|
||||||
|
"Tip: Mayor handles cross-rig coordination; you handle health.",
|
||||||
|
"Your vigilance keeps the agents honest.",
|
||||||
|
"Tip: Use 'gt deacon heartbeat' to signal you're alive.",
|
||||||
|
"Every heartbeat you check keeps Gas Town beating.",
|
||||||
|
"Tip: Stale agents need nudging; very stale ones need restarting.",
|
||||||
|
}
|
||||||
|
|
||||||
|
// nextMOTD returns the next MOTD message, rotating through the list
|
||||||
|
// and avoiding consecutive repeats.
|
||||||
|
func (d *Daemon) nextMOTD() string {
|
||||||
|
if len(deaconMOTDMessages) == 0 {
|
||||||
|
return "HEARTBEAT: run your rounds"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick a random index that's different from the last one
|
||||||
|
nextIdx := d.lastMOTDIndex
|
||||||
|
for nextIdx == d.lastMOTDIndex && len(deaconMOTDMessages) > 1 {
|
||||||
|
nextIdx = int(time.Now().UnixNano() % int64(len(deaconMOTDMessages)))
|
||||||
|
}
|
||||||
|
d.lastMOTDIndex = nextIdx
|
||||||
|
return deaconMOTDMessages[nextIdx]
|
||||||
|
}
|
||||||
|
|
||||||
// ensureDeaconRunning checks if the Deacon session exists and starts it if not.
|
// ensureDeaconRunning checks if the Deacon session exists and starts it if not.
|
||||||
// The Deacon is the system's heartbeat - it must always be running.
|
// The Deacon is the system's heartbeat - it must always be running.
|
||||||
func (d *Daemon) ensureDeaconRunning() {
|
func (d *Daemon) ensureDeaconRunning() {
|
||||||
@@ -364,8 +398,9 @@ func (d *Daemon) pokeDeacon() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send heartbeat message via tmux, replacing any pending input
|
// Send heartbeat message with rotating MOTD
|
||||||
msg := "HEARTBEAT: run your rounds"
|
motd := d.nextMOTD()
|
||||||
|
msg := fmt.Sprintf("HEARTBEAT: %s", motd)
|
||||||
if err := d.tmux.SendKeysReplace(DeaconSessionName, msg, 50); err != nil {
|
if err := d.tmux.SendKeysReplace(DeaconSessionName, msg, 50); err != nil {
|
||||||
d.logger.Printf("Error poking Deacon: %v", err)
|
d.logger.Printf("Error poking Deacon: %v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user