Commit Graph

17 Commits

Author SHA1 Message Date
Steve Yegge
e5c88ae9d4 feat(lifecycle): immediate daemon notification via SIGUSR1
- 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>
2025-12-20 20:28:36 -08:00
Steve Yegge
a9d204aa22 feat(daemon): add lifecycle support for refinery and crew
- Add refinery and crew patterns to identityToSession()
- Add refinery and crew handling to restartSession() with pre-sync
- Add refinery and crew to identityToStateFile()
- Fix gt refinery start to send gt prime after Claude starts
- New syncWorkspace() helper for agents with persistent clones
2025-12-20 17:42:21 -08:00
Steve Yegge
d2fccd580c feat(daemon): Add slot-based notification deduplication (gt-wpg)
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>
2025-12-20 13:19:40 -08:00
Steve Yegge
1554380228 feat(deacon): improve timing and add heartbeat command
Timing changes for more relaxed poke intervals:
- Daemon heartbeat: 60s → 5 minutes
- Backoff base: 60s → 5 minutes
- Backoff max: 10m → 30 minutes
- Fresh threshold: <2min → <5min
- Stale threshold: 2-5min → 5-15min
- Very stale threshold: >5min → >15min

New command:
- `gt deacon heartbeat [action]` - Touch heartbeat file easily

Template rewrite:
- Clearer wake/sleep model
- Documents wake sources (daemon poke, mail, timer callbacks)
- Simpler rounds with `gt deacon heartbeat` instead of bash echo
- Mentions plugins as optional maintenance tasks
- Explains timer callbacks pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 02:12:21 -08:00
Steve Yegge
348a7d0525 feat(deacon): make deacon the system heartbeat with auto-start
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>
2025-12-20 02:00:54 -08:00
Steve Yegge
23cf29df9c Merge remote-tracking branch 'origin/polecat/Slit'
# Conflicts:
#	internal/daemon/lifecycle_test.go
#	internal/refinery/engineer.go
2025-12-19 18:27:12 -08:00
Steve Yegge
89520a5854 Merge remote-tracking branch 'origin/polecat/Scabrous'
# Conflicts:
#	docs/architecture.md
#	docs/harness.md
#	internal/beads/builtin_molecules.go
#	internal/cmd/mail.go
#	internal/cmd/molecule.go
#	internal/cmd/mq.go
#	internal/git/git.go
#	internal/mail/router.go
2025-12-19 17:59:36 -08:00
Steve Yegge
3a5f542cc9 Merge remote-tracking branch 'origin/polecat/Doof' 2025-12-19 17:42:05 -08:00
Steve Yegge
178bebee40 refactor: update lifecycle mail targets from daemon/ to deacon/ (gt-5af.5)
Update all code and documentation to use deacon/ instead of daemon/
for lifecycle mail targets:

- internal/cmd/handoff.go: getManager() returns deacon/ for Mayor/Witness
- internal/daemon/lifecycle.go: ProcessLifecycleRequests uses deacon/ inbox
- docs/architecture.md: update all references in lifecycle docs
- scripts/mayor-respawn-daemon.sh: use BD_IDENTITY=deacon for mail commands

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 17:26:16 -08:00
Steve Yegge
22977d15ba feat(daemon): verify requesting_cycle before kill (gt-y5o)
Before killing an agent session, the daemon now verifies that the
agent has set requesting_<action>=true in its state.json file.
This ensures agents have completed pre-shutdown tasks (git clean,
handoff mail, etc) before being terminated.

- Added verifyAgentRequestingState() for state file verification
- Added identityToStateFile() to map identity to state.json path
- Added comprehensive tests in lifecycle_test.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 16:28:59 -08:00
Steve Yegge
f9c973c23d feat(daemon): implement proper rig discovery from rigs.json
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>
2025-12-19 16:28:31 -08:00
Steve Yegge
0716c4d48a test(daemon): add unit tests for daemon package (gt-99a)
Add comprehensive unit tests for:
- Config and state serialization (DefaultConfig, LoadState, SaveState)
- Session name pattern matching (isWitnessSession)
- Lifecycle request parsing (parseLifecycleRequest)
- Identity to session mapping (identityToSession)

Tests document a bug where parseLifecycleRequest always matches 'cycle'
because "LIFECYCLE:" prefix contains "cycle". Filed as gt-rixa.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 16:18:01 -08:00
Steve Yegge
4d0492fdf6 feat(tmux): add per-rig color themes and dynamic status line (gt-vc1n)
Add tmux status bar theming for Gas Town sessions:

- Per-rig color themes auto-assigned via consistent hashing
- 10 curated dark themes (ocean, forest, rust, plum, etc.)
- Special gold/dark theme for Mayor
- Dynamic status line showing current issue and mail count
- Mayor status shows polecat/rig counts

New commands:
- gt theme --list: show available themes
- gt theme apply: apply to running sessions
- gt issue set/clear: agents update their current issue
- gt status-line: internal command for tmux refresh

Status bar format:
- Left: [rig/worker] role
- Right: <issue> | <mail> | HH:MM

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 14:17:39 -08:00
Steve Yegge
4048cdc373 fix(lint): resolve all errcheck warnings
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>
2025-12-19 12:44:42 -08:00
Steve Yegge
3a477f673c feat(daemon): add adaptive backoff for heartbeat pokes
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>
2025-12-19 12:44:05 -08:00
Steve Yegge
e8c139c598 Add Beads as Universal Data Plane to architecture docs
- Document molecule concept (composable workflow beads)
- Add OS metaphor mapping (daemon=kernel, molecules=templates, etc.)
- Table of bead categories: work, mail, MR, molecules, timed, pinned, resources
- Created beads: gt-aqm (epic), gt-4nn (molecules), gt-caz/8h4/b3p (P2)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 18:12:38 -08:00
Steve Yegge
1265df70f9 feat: add gt daemon for town-level background service
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>
2025-12-18 13:06:20 -08:00