fix: emit rich mutation events for status changes (bd-313v)

- Add emitRichMutation() function for events with metadata
- handleClose now emits MutationStatus with old/new status
- handleUpdate detects status changes and emits MutationStatus
- Add comprehensive tests for rich mutation events

Also:
- Add activity.go test coverage (bd-3jcw):
  - Tests for parseDurationString, filterEvents, formatEvent
  - Tests for all mutation type displays
- Fix silent error handling in --follow mode (bd-csnr):
  - Track consecutive daemon failures
  - Show warning after 5 failures (rate-limited to 30s)
  - Show reconnection message on recovery

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-23 04:16:26 -08:00
parent 3f51ca5454
commit da809061db
5 changed files with 662 additions and 8 deletions

View File

@@ -139,10 +139,19 @@ func NewServer(socketPath string, store storage.Storage, workspacePath string, d
// Non-blocking: drops event if channel is full (sync will happen eventually).
// Also stores in recent mutations buffer for polling.
func (s *Server) emitMutation(eventType, issueID string) {
event := MutationEvent{
Type: eventType,
IssueID: issueID,
Timestamp: time.Now(),
s.emitRichMutation(MutationEvent{
Type: eventType,
IssueID: issueID,
})
}
// emitRichMutation sends a pre-built mutation event with optional metadata.
// Use this for events that include additional context (status changes, bonded events, etc.)
// Non-blocking: drops event if channel is full (sync will happen eventually).
func (s *Server) emitRichMutation(event MutationEvent) {
// Always set timestamp if not provided
if event.Timestamp.IsZero() {
event.Timestamp = time.Now()
}
// Send to mutation channel for daemon