Skip to content

compliance: fire processAgentBadges on owner_test transitions (skip Slack notify) #4376

@bokelley

Description

@bokelley

Gap

PR #4250 routes owner-triggered evaluate_agent_quality runs to canonical compliance state, so the public registry reflects the verdict immediately. But the badge fan-out (`processAgentBadges` in `compliance-heartbeat.ts:131-219`) is heartbeat-coupled — owner_test runs deliberately skip it to avoid notification spam.

Effect: an owner who just fixed compliance has to wait up to 1 hour for the next heartbeat tick to re-issue their AAO Verified badge. The compliance status flips to passing in real time; the badge does not.

Fix shape

Extract the badge-issuance block from `compliance-heartbeat.ts` into a shared helper (e.g. `services/badge-issuance.ts` already exists — add a `processBadgesForCompletedRun()` wrapper there). Call from:

The Slack-spam concern was about `notifyComplianceChange` and `notifyVerificationChange` — both fire DMs/channels. Badge processing itself is internal state issuance/revocation; firing it without notifications is the correct split.

Acceptance criteria

  • Owner runs `evaluate_agent_quality`, agent transitions failing→passing, badge issues in the same response cycle (no 1h wait)
  • Owner runs `evaluate_agent_quality`, agent transitions passing→failing, badge revokes immediately
  • No new Slack DM fires from owner_test path (verified by test)
  • Heartbeat path's notifications unchanged
  • Per-version badge fan-out (`SUPPORTED_BADGE_VERSIONS`) preserved

Why this needs to ship soon

Owners iterating on compliance fixes see a confusing UX: dashboard says "passing" but their public badge still says "untested." The 1h gap teaches developers to trust the badge less than the status, undermining the whole verification pipeline.

Discovered

PR #4250 review iteration (#4250). Deferred as out-of-scope for that PR because the heartbeat fan-out is ~70 lines and extracting/sharing is its own refactor.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.compliance-suite

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions