Skip to content

[Improve] Attribute tasks and PRs to the initiating user or named automation#14

Draft
roomote-roomote-v1[bot] wants to merge 3 commits into
developfrom
feature/simplify-analytics-attribution-0kc1xsa3sdov6
Draft

[Improve] Attribute tasks and PRs to the initiating user or named automation#14
roomote-roomote-v1[bot] wants to merge 3 commits into
developfrom
feature/simplify-analytics-attribution-0kc1xsa3sdov6

Conversation

@roomote-roomote-v1

@roomote-roomote-v1 roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown

Opened on behalf of Matt Rubens. Follow up by mentioning @openmote, in the web UI, or in Slack.

What changed

Every task now resolves to a single initiator — either the user who started it or the named automation that did — and all attribution surfaces read only that:

  • Named automation attribution: a canonical resolver (resolveTaskAutomationDisplayName) maps task types, background-automation keys, and suggestion sources to the automation labels from the registry ("PR Reviewer", "Resolve PR Conflicts", "Suggest Ideas", "Triage Sentry Issues", etc.). The attribution snapshot stamps attributionSourceKind: 'automation' plus that label at task creation; unnamed automatic work falls into a shared "Automations" bucket. attributionOverride accepts an explicit displayName for callers that want to name themselves.
  • Analytics "Tasks by user" shows each named automation as its own series plus "Automations" and real user names, instead of lumping all automation work under one "Roomote" label. The tasks "Source" dimension now labels automation-initiated tasks as "Automation" instead of "Web"/"GitHub".
  • Task creator filter (task list + analytics filter options) offers one option per named automation plus an "Automations" option, backed by a single shared SQL predicate helper that replaced four duplicated predicate blocks. The legacy author:roomote filter value is gone (no real users yet, so no compat shims).
  • PR attribution line now reads > Created by PR Reviewer. (or the relevant automation) instead of always > Created by Roomote.; humans keep "Opened on behalf of".
  • No more fallback user ids on automation tasks: scheduled and webhook automations (Suggest Ideas, Sentry/Dependabot triage, security/code-quality auditors, CI failure triage) previously stamped the first active user's id onto their tasks just to satisfy the enqueue guard. They now enqueue with a null userId, and the guard allows automation-initiated tasks explicitly. Job tokens and MCP credentials already resolve lazily; the resolver was renamed to resolveCredentialUserIdForCloudJob and documented as credential plumbing, never attribution. Four Slack MCP endpoints that compared tokens against the raw job userId column now use the same lazy resolution so automation tasks keep Slack access. A lightweight deploymentHasActiveCredentialUser() preflight keeps the old empty-deployment behavior: automation launchers skip (or record a failed run) up front when no active user exists, instead of recording a succeeded run for a job that would later fail credential resolution at dequeue; manual “Run now” triggers complete their pre-created queued run as skipped so it never sticks in queued.

This supersedes #13: its automation-name resolver and analytics dimension extraction are absorbed here, and this PR goes further by consolidating the read surfaces and removing the stamped user ids entirely.

Why this change was made

The Tasks By User chart mixed people with generic automation/bot labels, and attribution facts were spread across three overlapping systems (legacy tasks.userId, the attribution snapshot, and the authorship-rules columns) stitched together differently per surface. Direction confirmed in the task thread: one initiator per task — user name or automation name — and simplify aggressively while the product has no real users.

Impact

  • Analytics, filter options, task lists, task details, and PR bodies all attribute work to a person's name or an automation's name, consistently.
  • Automation tasks no longer appear in the first admin's personal task list, pins, or search, since they no longer carry that user's id.
  • Historical rows are untouched (no backfill, per decision): pre-change automation tasks stay in the shared "Automations" bucket.
  • Runtime behavior of job tokens and MCP credential resolution is unchanged (same stable first-active-user fallback at mint time); authorship rules (effectiveAuthor*/effectivePrOwner*) remain the feature-flagged override layer for git author and PR ownership, but analytics no longer depends on them.
  • Follow-up noted, out of scope: Slack bot-authored channel auto-start still launches with the Slack installer's identity (deeply coupled to routing/credentials); an org-level "automation credentials user" setting is another candidate follow-up.

Screenshots

Analytics Tasks-by-user chart showing PR Reviewer, Suggest Ideas, Automations, and Roomote Demo as separate attribution series

Task creator filter dropdown offering Automations, PR Reviewer, and Suggest Ideas options alongside the human user Roomote Demo

@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown
Author

Superseded by the current review summary: #14 (comment)

@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown
Author

No new code issues found. See task

  • apps/bullmq/src/scheduled-jobs/scheduled-triage-runner.ts:180: Scheduled automations now enqueue null-user jobs and immediately mark the background run succeeded, but credential resolution still happens later in BaseController.dequeueCloudJob and throws when no active user exists. In that case the automation run remains recorded as successful even though the task cannot start; keep the old guard or update the run to failed when deferred credential resolution fails.
  • apps/bullmq/src/scheduled-jobs/scheduled-triage-runner.ts:164 and apps/bullmq/src/scheduled-jobs/suggester.ts:174: These new no-active-user guards skip before starting or completing a run. Manual “Run now” triggers create a queued background run before BullMQ executes the job, so when credentials are unavailable these branches leave that run stuck in queued instead of marking it failed or skipped; complete the existing opts.bullmqJobId run before continuing.

@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown
Author

Fixed both flagged issues:

  • 16971ed: deploymentHasActiveCredentialUser() preflight restores the empty-deployment guard for all automation launchers without stamping a user id on the task — scheduled/webhook launches skip, merged-PR audits record a failed run with reason: no_user, and the CI-triage webhook bails before creating a run record.
  • 65b338a: the new guards in the scheduled triage runner and the suggester now complete the pre-created opts.bullmqJobId run as skipped (reason: no_user) before continuing, so manual "Run now" triggers no longer leave a run stuck in queued.

Covered by a new webhook unit test plus the full bullmq suite; lint/typecheck/knip green. The PR description reflects both fixes.

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