Skip to content

Post announcer and manager-stats reports via communication adapters#305

Merged
daniel-lxs merged 2 commits into
developfrom
feat/announcer-adapter-posting
Jul 14, 2026
Merged

Post announcer and manager-stats reports via communication adapters#305
daniel-lxs merged 2 commits into
developfrom
feat/announcer-adapter-posting

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

What

PR "6b" of the automations-everywhere track (follows #291, #293) — the last two Slack-hardwired reporters.

The announcer and manager-stats automations posted their reports directly via SlackNotifier with Block Kit, bypassing everything the earlier PRs built. They now resolve their destination through the same waterfall as the triage/audit automations and, for Teams/Telegram destinations, post through getCommunicationProviderAdapter:

  • Summary text degrades from Slack mrkdwn to standard markdown (*bold***bold**, <url|label>[label](url)) via a new shared helper
  • The Slack settings-context footer becomes an "Automation settings" url button (rendered as a Block Kit actions block on Slack, trailing links on Teams, inline keyboard on Telegram — the Surface-scope automation tracked messages and add button parity #284 parity)
  • Announcer detail messages thread under the root post per surface (Teams replyToMessageId, Telegram topics)
  • Tracked automation threads upsert with the destination surface; feedback lookups pass it through
  • Deployment eligibility generalizes like the triage runner (Slack installations, else any connected comms provider); manager-stats resolves its GitHub actor from the installation row on Slack-less deployments

Slack destinations are byte-identical — the existing notifier path is preserved behind the provider branch.

Deliberately untouched: ci_failure_triage (webhook announcements still Slack-shaped) and the suggester's advanced per-idea routing.

Testing

  • New announcer non-Slack-path suite (root post shape, tracked surface, per-surface threading, null-adapter failure, null-destination skip) + degradation helper tests
  • types (545), db (257), sdk (476), api (906) green; web green except 5 pre-existing compute-provisioning failures that reproduce identically on clean develop with this diff stashed (unrelated; machine/develop-tip issue)
  • lint/types/knip pass

Like #291, the non-Slack paths stay dormant until the automations-page UI (next PR) exposes destination configuration; live validation gates that PR.

🤖 Generated with Claude Code

@roomote-roomote

roomote-roomote Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

2 issues outstanding. See task

The only change since the last review removes a duplicate WORKER_RUNTIME_SCHEMA_VERSION import that was inherited from develop; the symbol is still imported via the grouped @roomote/types import, so the change is safe and introduces nothing new. This PR's own logic files are unchanged since the last review, so both prior findings still stand.

  • 🟡 packages/sdk/src/server/automations/announcer.ts:302-306 — For Telegram detail replies the code passes threadId: root.messageId, and the Telegram adapter maps threadId to message_thread_id (see telegram-provider.ts:114,262). message_thread_id is a forum topic id, not a message id, so on a normal (non-forum) Telegram chat the API rejects it with Bad Request: message thread not found and each per-repo breakdown chunk is silently dropped by the surrounding try/catch. The root post never supplies a topic id, so root.threadId is the only valid topic to thread under — use root.threadId and fall back to no thread when it is absent, rather than root.messageId. (Teams is unaffected: it maps threadId/replyToMessageId to replyToActivityId, which correctly wants the parent activity id.)
  • 🟢 packages/sdk/src/server/automations/manager-stats.ts:123-127 — On a Slack-less deployment the GitHub actor is selected with .limit(1) and no orderBy, so a deployment with multiple non-suspended GitHub installations picks a non-deterministic installer to scope the weekly stats digest. Add an explicit ordering (e.g. earliest createdAt) for a stable actor.

Reviewed 49f531d

The last two Slack-hardwired automation reporters now reach Teams and
Telegram destinations. Slack destinations keep the existing
SlackNotifier + Block Kit path byte-identical; non-Slack destinations
post through getCommunicationProviderAdapter with the summary degraded
from Slack mrkdwn to standard markdown (new degradeSlackMrkdwnToMarkdown
helper), the settings-link footer becoming a cross-surface url button,
detail messages threaded under the root, and tracked automation threads
upserted with the destination surface.

Deployment eligibility generalizes like the triage runner: Slack
installations first, otherwise any connected communication provider
(manager-stats resolves its GitHub actor from the installation row on
Slack-less deployments). Registry declarations flip to
slack/teams/telegram for both.

ci_failure_triage and the suggester's advanced routing intentionally
stay Slack-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daniel-lxs
daniel-lxs force-pushed the feat/announcer-adapter-posting branch from 1005e58 to 56d2e4e Compare July 14, 2026 00:13
Same one-line fix as #310; keeps this branch typechecking until that
lands on develop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daniel-lxs
daniel-lxs merged commit ae9a348 into develop Jul 14, 2026
17 of 18 checks passed
@daniel-lxs
daniel-lxs deleted the feat/announcer-adapter-posting branch July 14, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant