fix(agent-actions): scope the global open-item cap query by installation - #2687
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2687 +/- ##
==========================================
- Coverage 96.15% 96.14% -0.01%
==========================================
Files 240 240
Lines 26867 26875 +8
Branches 9751 9752 +1
==========================================
+ Hits 25833 25839 +6
- Misses 424 425 +1
- Partials 610 611 +1
🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-03 06:05:08 UTC
⏸️ Suggested Action - Manual Review
Review summary Blockers
Nits — 5 non-blocking
Concerns raised — review before merging
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
countOpenItemsForAuthorAcrossRepos (merged via #2678, closing #2562) counted an author's open PRs/issues across the ENTIRE D1 database with no installation scoping at all -- on a database shared by multiple installations (the hosted product's normal shape, and possible on self-host too), a contributor's activity on one installation could wrongly trigger GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP closes on a completely unrelated installation that never gated them. Scope the query through repositories.installationId first (matching the existing markRepositoriesRemovedFromInstallation precedent), then inArray(...) against the resulting repoFullNames -- this codebase has no Drizzle joins to lean on instead. Also fixes 5 AiReviewCacheInput test fixtures in queue.test.ts left broken by an unrelated already-merged PR (#2675, security-focused review profile) that added a required securityFocus field without updating these fixtures -- main's typecheck was red without this, which this PR's own CI would otherwise have inherited.
…rop it silently listRepoFullNamesForInstallation's .limit(20_000) meant an installation with more tracked repos than that would silently undercount toward GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP with no signal anything was dropped. Records an audit event on the rare install where the limit is still hit, mirroring the same observability pattern already used for the per-author item-count truncation in this file. Addresses a gate review finding on #2687.
9e3afcc to
0a74156
Compare
Summary
countOpenItemsForAuthorAcrossRepos(shipped in feat(agent-actions): add an install-wide contributor open-item cap across repos #2678, closing feat(agent-actions): add an install-wide contributor open-item cap across repos #2562) counts an author's open PRs/issues with no installation scoping at all — a plain author-login filter against the whole D1 database. On a database shared by multiple installations (the normal shape for the hosted product, and possible on self-host too if the same App is installed against more than one org/account), a contributor's open items on a completely unrelated installation can push another installation's count overGLOBAL_CONTRIBUTOR_OPEN_ITEM_CAPand trigger a wrongful close.listRepoFullNamesForInstallation, mirroring the existingmarkRepositoriesRemovedFromInstallationprecedent), then scoping both the PR and issue count queries viainArray(...)— this codebase has no Drizzle joins to lean on instead.AiReviewCacheInputtest fixtures inqueue.test.tsthat were left broken by an unrelated, already-merged PR (security-focused review profile) adding a requiredsecurityFocusfield without updating them — main's typecheck was red without this, which this PR's own CI would otherwise have inherited. (These were independently fixed on main during this PR's rebase; kept here as a no-op for safety.)Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlint(vianpm run test:ci)npm run db:migrations:check— no new migration, no-opnpm run typechecknpm run test:coveragelocally — full coverage confirmed; added a direct regression test proving cross-installation isolation (countOpenItemsForAuthorAcrossReposscoped to installation A does not see installation B's rows on the same D1), plus fixed 2 pre-existing integration tests whose setup relied on the unscoped (buggy) behavior to find a second repo's rows.npm run test:workers(vianpm run test:ci)npm run build:mcp(vianpm run test:ci)npm run test:mcp-pack(vianpm run test:ci)npm run ui:openapi:check— no API-visible schema touched, no-opnpm run ui:lint(vianpm run test:ci)npm run ui:typecheck(vianpm run test:ci)npm run ui:build(vianpm run test:ci)npm audit --audit-level=moderateSafety
UI Evidencesection below with screenshots. — N/A, no UI change.Notes
Regression found while independently implementing the same feature (#2562) in parallel — my own implementation caught this exact cross-installation scoping gap via the gate's own AI review before I discovered #2678 had already shipped without it. Filing as a direct fix rather than reopening the closed issue.