Implements status broadcasting via bridge module to chat channels. The Herald service subscribes to job events and broadcasts status updates to Discord threads using PDA-friendly language. Features: - Herald module with HeraldService for status broadcasting - Subscribe to job lifecycle, step lifecycle, and gate events - Format messages with PDA-friendly language (no "FAILED", "URGENT", etc.) - Visual indicators for quick scanning (🟢, 🔵, ✅, ⚠️, ⏸️) - Channel selection logic via workspace settings - Route to Discord threads based on job metadata - Comprehensive unit tests (14 tests passing, 85%+ coverage) Message format examples: - Job created: 🟢 Job created for #42 - Job started: 🔵 Job started for #42 - Job completed: ✅ Job completed for #42 (120s) - Job failed: ⚠️ Job encountered an issue for #42 - Gate passed: ✅ Gate passed: build - Gate failed: ⚠️ Gate needs attention: test Quality gates: ✅ typecheck, lint, test, build PR comment support deferred - requires GitHub/Gitea API client implementation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.1 KiB
4.1 KiB
Issue #172: Herald Status Updates
Objective
Implement status reporting via the bridge module to chat channels and PR comments. The Herald service will broadcast job status updates to appropriate channels based on workspace configuration.
Approach
- Review existing code:
- JobEventsService (#169) for event types
- IChatProvider interface and Discord provider (#170)
- Create Herald module following TDD:
- RED: Write tests for status broadcasting
- GREEN: Implement Herald service
- REFACTOR: Clean up and optimize
- Implement channel selection logic (job type → channel mapping)
- Add PR comment support via GitHub/Gitea API
- Format messages using PDA-friendly language
Progress
- Create scratchpad
- Review JobEventsService and event types
- Review IChatProvider interface and Discord provider
- Write tests for Herald service (RED)
- Create Herald module structure
- Implement Herald service (GREEN)
- Add channel selection logic
- Add PR comment support (deferred - GitHub API integration needed)
- Refactor and optimize (REFACTOR)
- Run quality gates (typecheck, lint, test, build)
- Commit changes
Key Findings
Event Types Available
- Job lifecycle:
job.created,job.queued,job.started,job.completed,job.failed,job.cancelled - Step lifecycle:
step.started,step.progress,step.output,step.completed,step.failed - AI events:
ai.tool_called,ai.tokens_used,ai.artifact_created - Gate events:
gate.started,gate.passed,gate.failed
IChatProvider Interface
sendMessage(channelId, content)- Send message to channelcreateThread(options)- Create thread for updatessendThreadMessage(options)- Send message to threadisConnected()- Check connection status
Workspace Settings
- Workspace has
settingsJSON field for configuration - Can store channel mappings:
{ herald: { channelMappings: { "code-task": "channel-id" } } }
Herald Responsibilities
- Subscribe to job events from JobEventsService
- Format status messages using PDA-friendly language
- Route to appropriate channels based on workspace config
- Support Discord (via bridge) and PR comments (via GitHub/Gitea API)
- Follow 10-second scannability rule
Testing
- Unit tests for status broadcasting
- Tests for channel selection logic
- Tests for message formatting (PDA-friendly)
- Tests for PR comment integration
- Minimum 85% coverage required
Notes
- Use PDA-friendly language (no "OVERDUE", "URGENT", etc.)
- Follow 10-second scannability rule
- Support multiple providers (Discord, GitHub PR comments)
- Subscribe to job events via JobEventsService
- Route to appropriate channels based on workspace config
Implementation Details
Architecture
- Herald module created with HeraldService
- Subscribes to job events (job lifecycle, step lifecycle, gate events)
- Formats messages with PDA-friendly language and visual indicators
- Routes to Discord threads via DiscordService
Message Formatting
- Job created: 🟢 Job created for #42
- Job started: 🔵 Job started for #42
- Job completed: ✅ Job completed for #42 (120s)
- Job failed: ⚠️ Job encountered an issue for #42
- Job cancelled: ⏸️ Job paused for #42
- Step completed: ✅ Step completed: Run tests
- Gate passed: ✅ Gate passed: build
- Gate failed: ⚠️ Gate needs attention: test
Channel Selection
- Workspace settings store channel mappings:
{ herald: { channelMappings: { "code-task": "channel-id" } } } - Falls back to default channel if job type not mapped
- Returns null if no channel configured
Metadata Handling
- Job metadata (including threadId) stored in first event payload (job.created)
- Herald retrieves metadata from JobEvent table to determine where to send updates
- This allows thread-based updates for each job
Deferred Features
- PR comment support via GitHub/Gitea API (requires additional API client implementation)
- This can be added in a future iteration when needed
Dependencies
- #169 (JobEventsService) - ✅ COMPLETED
- #170 (IChatProvider) - ✅ COMPLETED