Skip to content

Route triage and audit automations to any comms destination#291

Merged
daniel-lxs merged 2 commits into
developfrom
feat/automation-runner-destinations
Jul 13, 2026
Merged

Route triage and audit automations to any comms destination#291
daniel-lxs merged 2 commits into
developfrom
feat/automation-runner-destinations

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

What

Sixth PR of the "automations on all comms channels" track (follows #280, #281, #284, #285, #289). This is the one where non-Slack destinations actually light up: Sentry triage, Dependabot triage, and the security/code-quality auditors can now report to Teams or Telegram.

Design

Rather than teaching every runner about communication adapters, the resolved destination is stamped onto the scan task's communication payload fields (communicationProvider/ChannelId/ServiceUrl) at enqueue. Everything downstream then works unchanged: the worker converts those to envs, the surface-generic tools (send_chat_reply, post_to_channel from #285) register and dispatch correctly, and the own-conversation posting restriction naturally scopes the task to its destination. Slack destinations are deliberately unstamped — their scan tasks keep the existing arbitrary-channel post_to_slack_channel flow byte-for-byte.

  • Destination resolution (packages/sdk/src/server/automations/destination.ts): extends the db-level waterfall (automation's own target → Slack manager channel) with a primary-conversation tail for Slack-less deployments — most recently active Teams conversation, then the Telegram primary chat. The tail is skipped when Slack is connected, so a Slack deployment that just hasn't picked a manager channel keeps its explicit nudge instead of surprising another surface. Teams destinations resolve their Bot Framework serviceUrl from teamsInstallations (indexed lookup) at launch; unresolvable serviceUrl means no destination rather than a broken one.
  • Runner eligibility: deployments without Slack are now eligible when any comms provider is connected (listConnectedCommunicationProviders, the piece deferred since Add generic communication adapter dispatch #281). Slack-only side effects (routing debug posts, workspace timezone) are guarded on an actual bot token.
  • Prompts are surface-correct: channel tag, posting tool name, and destination wording parameterized per provider across the four automations' scan prompts.
  • Gates: manual "Run now" and the settings-save validation accept a resolved destination on any provider the automation's descriptor supports; Slack-only automations (announcer, manager_stats, suggester) keep their exact current behavior and errors. Registry capability declarations flip to ['slack','teams','telegram'] for the four generalized automations.
  • ci_failure_triage explicitly skips non-Slack destinations with a clear reason — its prompt and webhook announcement path are still Slack-shaped; it generalizes in a follow-up along with announcer/manager-stats (which post directly via SlackNotifier with Block Kit and need message degradation, tracked as PR 6b).

Testing

  • New destination-module suite (11 tests): waterfall order, connected-provider listing, serviceUrl resolution and its failure mode, Slack-nudge preservation, Teams/Telegram tails, payload stamping, prompt context
  • Full local runs green: types (529), db (257), sdk (469), web (1947), api (906); lint/types/knip pass
  • Live Teams validation on the dev stack is the remaining step before this should merge

🤖 Generated with Claude Code

Sentry triage, Dependabot triage, and the security/code-quality
auditors can now report to Teams or Telegram, not just Slack.

Core design: instead of teaching runners about adapters, the resolved
destination is stamped onto the scan task's communication payload
fields, so the surface-generic worker tools (send_chat_reply,
post_to_channel) and the own-conversation posting restriction all
apply unchanged. Slack destinations stay byte-identical (no stamping).

- New destination module: resolveAutomationRuntimeDestination extends
  the db waterfall (own target -> Slack manager channel) with a
  primary-conversation tail for Slack-less deployments (most recently
  active Teams conversation, then the Telegram primary chat); the tail
  is skipped when Slack is connected so the "configure a manager
  channel" nudge survives. listConnectedCommunicationProviders gates
  deployment eligibility. Teams destinations resolve their Bot
  Framework serviceUrl from teamsInstallations at launch.
- scheduled-triage-runner and merged-pr-audit-runner resolve
  destinations, stamp payload fields, and keep Slack-only side effects
  (debug posts, workspace timezone) guarded on an actual Slack token.
- Scan prompts are surface-correct: channel tag, posting tool name,
  and surface wording parameterized per destination.
- ci_failure_triage explicitly skips non-Slack destinations for now
  (its prompt and webhook announcements are still Slack-shaped).
- Manual "Run now" and settings validation accept a resolved
  destination on any provider the automation's descriptor supports;
  registry declarations flip to slack/teams/telegram for the four
  generalized automations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@roomote-roomote

roomote-roomote Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

No new code issues found. Both earlier notes are addressed in the latest changes. See task

  • packages/sdk/src/server/automations/scheduled-triage-runner.ts:101 — the Slack-less skip reason now reads 'No connected communication provider.', which is accurate for the triage runner (its eligibility gate only checks connected comms providers; GitHub is gated per-automation inside buildScanTask).
  • packages/sdk/src/server/automations/sentry-triage.ts:157, dependabot-triage.ts:96, merged-pr-audit-runner.ts:419 — the feedback lookups now pass surface: destination.provider, and loadAutomationThreadFeedback* forwards it to the surface filter, so Teams/Telegram destinations match their own tracked threads. The reply-harvesting gap (feedback replies still read from the Slack conversation log only) is now explicitly documented in background-automation-slack-threads.ts as a follow-up.

Reviewed c9b3590

- Thread-feedback loaders take the destination surface (default slack)
  and the runners pass it, so Teams/Telegram feedback context flows as
  soon as those surfaces track automation threads.
- Stale 'No active Slack installation' skip reason now reads 'No
  connected communication provider'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daniel-lxs
daniel-lxs merged commit f919d60 into develop Jul 13, 2026
18 checks passed
@daniel-lxs
daniel-lxs deleted the feat/automation-runner-destinations branch July 13, 2026 23:13
brunobergher pushed a commit that referenced this pull request Jul 14, 2026
* Route triage and audit automations to any comms destination

Sentry triage, Dependabot triage, and the security/code-quality
auditors can now report to Teams or Telegram, not just Slack.

Core design: instead of teaching runners about adapters, the resolved
destination is stamped onto the scan task's communication payload
fields, so the surface-generic worker tools (send_chat_reply,
post_to_channel) and the own-conversation posting restriction all
apply unchanged. Slack destinations stay byte-identical (no stamping).

- New destination module: resolveAutomationRuntimeDestination extends
  the db waterfall (own target -> Slack manager channel) with a
  primary-conversation tail for Slack-less deployments (most recently
  active Teams conversation, then the Telegram primary chat); the tail
  is skipped when Slack is connected so the "configure a manager
  channel" nudge survives. listConnectedCommunicationProviders gates
  deployment eligibility. Teams destinations resolve their Bot
  Framework serviceUrl from teamsInstallations at launch.
- scheduled-triage-runner and merged-pr-audit-runner resolve
  destinations, stamp payload fields, and keep Slack-only side effects
  (debug posts, workspace timezone) guarded on an actual Slack token.
- Scan prompts are surface-correct: channel tag, posting tool name,
  and surface wording parameterized per destination.
- ci_failure_triage explicitly skips non-Slack destinations for now
  (its prompt and webhook announcements are still Slack-shaped).
- Manual "Run now" and settings validation accept a resolved
  destination on any provider the automation's descriptor supports;
  registry declarations flip to slack/teams/telegram for the four
  generalized automations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: destination-surface feedback lookups, skip reason

- Thread-feedback loaders take the destination surface (default slack)
  and the runners pass it, so Teams/Telegram feedback context flows as
  soon as those surfaces track automation threads.
- Stale 'No active Slack installation' skip reason now reads 'No
  connected communication provider'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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