Skip to content

fix(server): don't silently assign new Dependabot alert issues to an uninvokable agent - #1344

Merged
kkroo merged 1 commit into
masterfrom
fix/blo-26613-dependabot-invokability-check
Aug 16, 2026
Merged

fix(server): don't silently assign new Dependabot alert issues to an uninvokable agent#1344
kkroo merged 1 commit into
masterfrom
fix/blo-26613-dependabot-invokability-check

Conversation

@allyblockcast

@allyblockcast allyblockcast Bot commented Aug 12, 2026

Copy link
Copy Markdown

Thinking Path

  • Paperclip is the open source app people use to manage AI agents for work
  • The Dependabot alert ingestion path (server/src/services/dependabot-alert-issues.ts, server/src/routes/github-webhook.ts) files a new issue per live security alert, diagnostic, or terminal receipt
  • That path has exactly one configured owner, PAPERCLIP_DEPENDABOT_AGENT_ID, and issue creation assigned it unconditionally with no invokability check — verified live that all 5 non-terminal dependabot-origin issues company-wide landed on an agent that had been paused since before any of them were created
  • Nothing in the creation path stops that from recurring: the per-issue blocked_by_uninvokable_assignee invariant only detects staleness after a row already exists, it doesn't prevent routing new work onto a dead agent, and there's no signal that this is a single-point-of-failure config
  • This pull request adds resolveDependabotIssueAssigneeId(), which checks the configured agent's invokability via the existing evaluateAgentInvokabilityFromDb machinery and falls back to unassigned (so allow_company_agent can pick it up) when the agent isn't invokable, logging distinctly for a future fleet-level alert rule
  • The benefit is new Dependabot alerts stop silently queuing on a paused/terminated agent — they either land on the configured owner when it's actually invokable, or file unassigned and get picked up, with a log line marking the gap

Linked Issues or Issue Description

Fixes: BLO-26613 (https://paperclip.blockcast.net/BLO/issues/BLO-26613)

What Changed

  • Added resolveDependabotIssueAssigneeId() in server/src/services/dependabot-alert-issues.ts: looks up the configured agent, runs it through the existing evaluateAgentInvokabilityFromDb invokability check (deliberately distinct from "assignable" — paused is assignable-to but not invokable), and returns null instead of the configured agent id when it isn't invokable, logging a distinct warning for a future fleet-level alert rule.
  • Wired that resolver into every Dependabot issue-creation call site: the main alert-issue create (resolveDependabotAlertIssue), the webhook-diagnostic create (recordDependabotWebhookDiagnostic, which also covers the BLO-16446 stale-wake backfill path since heartbeat calls through it), and the terminal-receipt create (recordDependabotTerminalReceipt).
  • Added a regression test in server/src/__tests__/github-webhook.test.ts asserting a new Dependabot alert issue files unassigned (not onto the paused agent) when the configured agent is paused.

Verification

  • New test: github-webhook.test.ts → "files a new dependabot alert issue unassigned when the configured agent is paused". Confirmed red against unpatched master (assigneeAgentId was the paused agent's id, not null) and green after this change.
  • Full suite run: github-webhook.test.ts + heartbeat-dependabot-stale-wake-backfill.test.ts + issues-service.test.ts — 339 tests pass.
  • tsc --noEmit clean.

Risks

  • Low risk, narrowly scoped: only changes assignee resolution inside the Dependabot alert path, not the generic issueService.create() / assertAssignableAgent() check used everywhere else (broadening "assignable" to require invokability company-wide would change intentional workflows like handing work to a colleague who is currently paused to resume later — out of scope here, no time in this change to audit that blast radius).
  • Behavioral shift: previously-silent misrouting now produces unassigned issues plus a warning log when the configured agent is uninvokable. That's the intended fix, but it means Dependabot issues can now show up unassigned in the backlog instead of always pre-assigned — allow_company_agent routing is expected to pick them up.
  • Does not drain the 5 already-affected rows (BLO-26613 AC fix(adapter-utils): CAS-retry on concurrent SSH workspace restores #4) — this only stops new ones from being misrouted; existing rows need a separate reassignment/backfill pass once the pause disposition is decided.
  • Does not add the fleet-level "single-owner alert route points at an uninvokable agent" dashboard/alert signal (BLO-26613 AC v513 test-fallout cleanup batch 2: codex-local SSH dispatch + company-portability mock/expectations #3) — the new log line is a start, not the full signal.
  • Does not touch paperclip-plugin-alertmanager's assignee resolution, which has the same class of gap per the BLO-26613 thread but lives in different plugin code (packages/plugins/paperclip-plugin-alertmanager/src/webhook-handler.ts) — flagged as follow-up on BLO-26613.

Model Used

Claude Sonnet 5 (claude-sonnet-5), 1M-context mode, via Claude Code (Paperclip agent adapter). Standard reasoning, tool use (file edit/read, test execution via Bash, GitHub CLI/API). No extended thinking mode used for this change.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above
  • I have either (a) linked existing issues with Fixes: # / Closes # / Refs # OR (b) described the issue in-PR following the relevant issue template
  • I have run tests locally and they pass
  • I have added or updated tests where applicable
  • If this change affects the UI, I have included before/after screenshots (N/A — server-only change)
  • I have updated relevant documentation to reflect my changes (N/A — no user-facing docs affected)
  • I have considered and documented any risks above
  • All Paperclip CI gates are green
  • Greptile is 5/5 with no open P2s, recommendations, or follow-ups
  • I will address all Greptile and reviewer comments before requesting merge

@allyblockcast

allyblockcast Bot commented Aug 12, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-26613
🔗 Paperclip issue: BLO-16446

1 similar comment
@allyblockcast

allyblockcast Bot commented Aug 12, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-26613
🔗 Paperclip issue: BLO-16446

@allyblockcast

allyblockcast Bot commented Aug 12, 2026

Copy link
Copy Markdown
Author

Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention:

Missing or incomplete:

  • Missing section: ## Thinking Path
  • Missing section: ## What Changed
  • Missing section: ## Verification
  • Missing section: ## Risks
  • Missing section: ## Model Used
  • Add the dedup-search checkbox to your PR description and check it once you have searched the GitHub PR list for similar PRs. See the PR template at .github/PULL_REQUEST_TEMPLATE.md and CONTRIBUTING.md → "Before You Start: Search First".

Once updated, push a new commit and these checks will re-run automatically.

— commitperclip

…uninvokable agent

PAPERCLIP_DEPENDABOT_AGENT_ID is the sole configured owner for the Dependabot
alert path with no fallback. Issue creation there assigned that agent
unconditionally -- if it's paused, terminated, or otherwise uninvokable,
every new alert (plus diagnostic and terminal-receipt rows) silently queued
on a dead run path with no signal. Verified live: 5/5 non-terminal
dependabot-origin issues company-wide were on a paused agent, created
entirely after the pause (BLO-26613).

Add resolveDependabotIssueAssigneeId() in dependabot-alert-issues.ts: checks
the configured agent's invokability (existing getAgentWorkEligibility/
evaluateAgentInvokabilityFromDb machinery -- "paused" is deliberately
assignable-to-work but not invokable) and falls back to unassigned (so
allow_company_agent picks it up) when it isn't, logging distinctly so this
can back a fleet-level alert rule. Wired into every issue-creation call site
in the Dependabot path: the main alert-issue create, the webhook-diagnostic
create, and the terminal-receipt create.

Deliberately scoped to this one path (BLO-26613's explicit ask), not the
generic issueService.create()/assertAssignableAgent() check used by manual
assignment everywhere else -- broadening "assignable" to require invokability
company-wide would change intentional workflows (e.g. handing work to a
colleague who is currently paused) with no time to audit the blast radius.
Also out of scope here: the paperclip-plugin-alertmanager path (same class
of gap per the BLO-26613 thread, different plugin code), the fleet-level
"single-owner route points at an uninvokable agent" signal, and draining the
5 already-affected rows -- flagged as remaining work on BLO-26613.

New regression test in github-webhook.test.ts confirmed red against
unpatched HEAD (assigneeAgentId was the paused agent's id, not null) and
green after this change. Full existing dependabot/webhook/issues-service
suites (339 tests) still pass.

https://paperclip.blockcast.net/BLO/issues/BLO-26613

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@allyblockcast
allyblockcast Bot force-pushed the fix/blo-26613-dependabot-invokability-check branch from 80e2a26 to 306dd7e Compare August 12, 2026 22:43
@allyblockcast

allyblockcast Bot commented Aug 13, 2026

Copy link
Copy Markdown
Author

Addressed the commitperclip review feedback:

  • Rewrote the PR description to include all required template sections (Thinking Path, Linked Issues, What Changed, Verification, Risks, Model Used) plus the dedup-search checkbox — review now passes.
  • The commit also failed the policy gate (BLO-21416 commit-attribution check): it was stamped with the shared allyblockcast[bot] App identity instead of a per-agent author, because this checkout had no local git identity configured. Set my own identity, amended the commit, and force-pushed (safe: single-commit branch, verified nobody else had pushed to it).

All CI lanes are now green (policy, review, verify, Build, full test matrix, e2e, Typecheck + Release Registry, Helm chart, security-review). A few lanes hit a transient ARC runner-pool scheduling crunch along the way (unrelated infra blip, self-recovered); reran those and they passed clean.

Ready for human review/merge.

@allyblockcast

allyblockcast Bot commented Aug 14, 2026

Copy link
Copy Markdown
Author

@ally please review at head 306dd7e — stop silently assigning new Dependabot alert issues to an uninvokable agent. Focus on the fallback when no invokable agent exists.

Context: the original review request on this PR was lost during the codex provider outage (BLO-27123) — codex success sat at 0/min from ~14:50Z to 17:54Z and Ally is pinned to openai/gpt-5.6-terra on that pool. Recovery does not revisit the stranded set, so this is a forward-only re-request. Codex recovered 17:56Z (~55 req/min, near-zero errors) and the path is verified working (#1329, #1341 reviewed at head in ~3 min).

@allyblockcast
allyblockcast Bot added this pull request to the merge queue Aug 16, 2026
@kkroo
kkroo removed this pull request from the merge queue due to a manual request Aug 16, 2026
@kkroo
kkroo merged commit 64e322c into master Aug 16, 2026
43 of 51 checks passed
@kkroo
kkroo deleted the fix/blo-26613-dependabot-invokability-check branch August 16, 2026 04:12
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