feat(#172): Implement Herald status updates

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>
This commit is contained in:
2026-02-01 21:42:44 -06:00
parent 8f3949e388
commit d3058cb3de
6 changed files with 1034 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
# 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
1. Review existing code:
- JobEventsService (#169) for event types
- IChatProvider interface and Discord provider (#170)
2. Create Herald module following TDD:
- RED: Write tests for status broadcasting
- GREEN: Implement Herald service
- REFACTOR: Clean up and optimize
3. Implement channel selection logic (job type → channel mapping)
4. Add PR comment support via GitHub/Gitea API
5. Format messages using PDA-friendly language
## Progress
- [x] Create scratchpad
- [x] Review JobEventsService and event types
- [x] Review IChatProvider interface and Discord provider
- [x] Write tests for Herald service (RED)
- [x] Create Herald module structure
- [x] Implement Herald service (GREEN)
- [x] Add channel selection logic
- [ ] Add PR comment support (deferred - GitHub API integration needed)
- [x] Refactor and optimize (REFACTOR)
- [x] Run quality gates (typecheck, lint, test, build)
- [x] 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 channel
- `createThread(options)` - Create thread for updates
- `sendThreadMessage(options)` - Send message to thread
- `isConnected()` - Check connection status
### Workspace Settings
- Workspace has `settings` JSON field for configuration
- Can store channel mappings: `{ herald: { channelMappings: { "code-task": "channel-id" } } }`
### Herald Responsibilities
1. Subscribe to job events from JobEventsService
2. Format status messages using PDA-friendly language
3. Route to appropriate channels based on workspace config
4. Support Discord (via bridge) and PR comments (via GitHub/Gitea API)
5. 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