Session names `gt-mayor` and `gt-deacon` were hardcoded, causing tmux
session name collisions when running multiple towns simultaneously.
Changed to `gt-{town}-mayor` and `gt-{town}-deacon` format (e.g.,
`gt-ai-mayor`) to allow concurrent multi-town operation.
Key changes:
- session.MayorSessionName() and DeaconSessionName() now take townName param
- Added workspace.GetTownName() helper to load town name from config
- Updated all callers in cmd/, daemon/, doctor/, mail/, rig/, templates/
- Updated tests with new session name format
- Bead IDs remain unchanged (already scoped by .beads/ directory)
Fixes#60🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements announce channel delivery in router.go:
- Add isAnnounceAddress() and parseAnnounceName() helpers
- Add ErrUnknownAnnounce error variable
- Add expandAnnounce() to load AnnounceConfig from messaging.json
- Add sendToAnnounce() for bulletin board delivery (single copy, no claiming)
- Add pruneAnnounce() for retention-based message cleanup
- Integrate announce routing in Send()
Announce channels store ONE copy of each message (unlike lists which fan-out).
Messages persist until retention limit is reached, with oldest messages
pruned automatically when limit is exceeded.
Also includes address helpers (gt-pn2fq dependency).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add announce address detection to internal/mail/router.go following
the same pattern as isListAddress/parseListName and isQueueAddress/
parseQueueName.
Added:
- isAnnounceAddress(address string) bool - returns true for 'announce:' prefix
- parseAnnounceName(address string) string - extracts channel name
- ErrUnknownAnnounce error variable
(gt-pn2fq)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add queue expansion to internal/mail/router.go following the expandList() pattern:
- Add ErrUnknownQueue error for unknown queue names
- Add expandQueue() method to look up QueueConfig from messaging.json
- Add TestExpandQueue and TestExpandQueueNoTownRoot tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add queue address detection following the same pattern as list address
detection. Includes tests in router_test.go.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements @group address resolution for mail routing:
- @rig/<rigname>: All agents in a rig
- @town: All town-level agents (mayor, deacon)
- @witnesses, @dogs, @refineries: Role-based groups
- @crew/<rig>, @polecats/<rig>: Role+rig scoped groups
- @overseer: Human operator (uses overseer.json)
Resolution uses `bd list --type=agent` queries with
description filtering. Fan-out at send time creates
individual messages for each resolved recipient.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement static mailing list expansion for the mail system:
- Add list:name address syntax (e.g., list:oncall)
- Load lists from ~/gt/config/messaging.json
- Fan-out delivery: each list member gets their own message copy
- Clear error handling for unknown list names
- Add tests for list detection, parsing, and expansion
- Update gt mail send help text with list:name documentation
- Show recipients in output when sending to a list
Example:
gt mail send list:oncall -s "Alert" -m "System down"
# Expands to: mayor/, gastown/witness
# Creates 2 message copies
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>