Files
stack/docs/scratchpads/172-herald-status.md
Jason Woltje d3058cb3de 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>
2026-02-01 21:42:44 -06:00

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

  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

  • 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 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