Commit Graph

30 Commits

Author SHA1 Message Date
Steve Yegge
a5a37f5d63 Fix: /handoff regression - use respawn-pane with direct claude command
Three related fixes:

1. lifecycle.go: Use gt mail delete instead of gt mail read to prevent
   lifecycle requests from accumulating.

2. handoff.go: Return exec claude command for respawn-pane instead of
   gt crew at which tries to attach to existing session.

3. handoff.md skill: Work without --cycle and -m flags, send mail separately.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:23:40 -08:00
Steve Yegge
c9dcaf0c51 bd sync: 2025-12-22 22:04:04 2025-12-22 22:04:11 -08:00
Steve Yegge
ae513a5db4 Deacon uses wisp-based patrol (gt-3x0z.9)
Daemon changes:
- Remove checkDeaconAttachment() - Deacon self-spawns wisps
- Remove findDeaconPatrolMolecule() - unused
- Remove nudgeDeaconForPatrol() - unused
- Remove DeaconPatrolMolecule const - unused
- Remove beads import - no longer needed

Deacon template changes:
- Update to wisp-based patrol model
- Replace bd mol run with bd mol spawn (wisps by default)
- Remove pinned molecule concept for patrol
- Add Why Wisps section explaining ephemeral design
- Update startup/handoff protocols for wisp-based cycles

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 02:13:24 -08:00
Steve Yegge
5d7291962a Rename ephemeral -> wisp terminology throughout Gas Town
- .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.
2025-12-22 00:55:31 -08:00
Steve Yegge
8cf15ded35 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>
2025-12-22 00:18:00 -08:00
Steve Yegge
db3fee8088 refactor: add constants package for magic strings
Create internal/constants/constants.go with centralized definitions for:
- Directory names (mayor, polecats, crew, etc.)
- File names (rigs.json, town.json, state.json)
- Git branch names (main, beads-sync)
- Tmux session names (gt-mayor, gt-deacon)
- Agent role names

Add helper functions for common path construction:
- MayorRigsPath(), MayorTownPath(), MayorStatePath()
- RigMayorPath(), RigBeadsPath(), RigPolecatsPath()

Update key files to use the new constants:
- internal/cmd/rig_helpers.go
- internal/cmd/status.go
- internal/daemon/daemon.go

Closes: gt-xnql

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:13:21 -08:00
Steve Yegge
107b6bf16b feat(daemon): add attachment detection for Deacon patrol system
Implements gt-rana.2: Daemon attachment detection

- Add Labels field to beads.Issue struct to parse label arrays
- Add attachment APIs: AttachMolecule, DetachMolecule, GetAttachment
- Add helper methods: HasAttachment, IsNaked for checking attachment state
- Add checkDeaconAttachment to daemon heartbeat cycle
- When Deacon's pinned bead is naked (no attached molecule):
  - Find or create mol-deacon-patrol template
  - Instantiate patrol molecule with steps as child issues
  - Attach molecule to Deacon's pinned bead
  - Nudge Deacon to start patrol loop
- Add comprehensive tests for attachment functionality

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 16:15:46 -08:00
Steve Yegge
f4379944a3 Merge polecat/furiosa: fix lifecycle parser order (gt-rixa)
Check restart/shutdown before cycle to avoid matching 'lifecycle:' prefix.
Use ' cycle' (with leading space) for word boundary matching.

Resolved conflict: fixed variable name (title → subject).
2025-12-21 14:14:53 -08:00
Steve Yegge
36d6fc28f3 fix: check restart/shutdown before cycle in lifecycle parser
The parseLifecycleRequest function was checking for "cycle" first,
but since the title already contains "lifecycle:" (which includes
"cycle"), all lifecycle messages matched as cycle actions, making
restart and shutdown unreachable.

Fixed by:
1. Checking restart/shutdown before cycle
2. Using " cycle" (with leading space) to match the word, not prefix

Closes gt-rixa

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 14:08:49 -08:00
Steve Yegge
5ee9bb13c8 fix: replace stale 'bd mail' references with 'gt mail'
- docs/architecture.md: update mail routing explanation
- internal/witness/manager.go: fix actual bd mail calls to gt mail
- internal/cmd/mail.go: remove stale compatibility note
- internal/daemon/lifecycle.go: update comment
2025-12-21 10:44:20 -08:00
Steve Yegge
dbecfe1d38 feat(handoff): route crew lifecycle requests to deacon
Crew workers now use deacon for lifecycle management instead of
requiring manual session termination. When a crew worker runs
'gt handoff', it sends a lifecycle request to the deacon which
handles session kill/restart like it does for Mayor and Witness.

Changes:
- Route crew manager to deacon/ instead of "human"
- Add getCrewIdentity() to extract <rig>-crew-<name> from session
- Include full crew identity in LIFECYCLE subject for daemon parsing
- Remove special case that skipped lifecycle flow for crew

Also fixes pre-existing test failures in daemon/lifecycle_test.go
where BeadsMessage field names were out of sync with the struct.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 01:17:32 -08:00
Steve Yegge
bdbba025f5 fix(daemon): clear requesting_cycle after successful restart
Bug: When daemon cycled a session, it verified requesting_cycle=true
but never cleared the flag after restart. This caused infinite
cycle loops on each heartbeat.

Also removed redundant SendKeysDelayed("gt prime") that injected
rogue text into terminal (SessionStart hook already handles priming).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 01:14:20 -08:00
Steve Yegge
c4892938d0 fix(daemon): use gt mail instead of bd mail for lifecycle requests
The handoff command sends lifecycle requests via 'gt mail send' to
town-level beads, but the daemon was reading with 'bd mail inbox'
which reads from the local beads database. This fixes the mismatch.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 00:47:05 -08:00
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