From 96766f4249b03c915da5030a6e330916389dbd21 Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:42:46 -0700 Subject: [PATCH] fix(settings): preserve install-wide contributor cap --- src/settings/global-contributor-cap.ts | 9 +++------ test/unit/global-contributor-cap.test.ts | 7 +++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/settings/global-contributor-cap.ts b/src/settings/global-contributor-cap.ts index 9f9a605e08..126f0ac898 100644 --- a/src/settings/global-contributor-cap.ts +++ b/src/settings/global-contributor-cap.ts @@ -8,20 +8,17 @@ // whole, mirroring how global_contributor_blacklist is a tenant-free singleton rather than a per-repo column. // Off by default (unset/invalid ⇒ null ⇒ no cap): zero behavior change for a single-repo install or one that // hasn't opted in. -import { MAX_CONTRIBUTOR_OPEN_ITEM_CAP } from "../types"; - const GLOBAL_ENV_KEY = "GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP"; /** Parse+validate the install-wide open-item cap from env. Same non-rounding shape as the per-repo caps' * normalizeOpenItemCap (db/repositories.ts): a discrete count of open items, not a score, so a * fractional/non-positive/non-numeric value is a malformed cap and is dropped to `null` (no cap) rather than - * coerced into a nonsensical threshold. Never throws. Clamped to {@link MAX_CONTRIBUTOR_OPEN_ITEM_CAP} for the - * same reason normalizeOpenItemCap is: live enforcement only ever samples a fixed 100-row budget, so a - * configured value above that is silently unenforceable. */ + * coerced into a nonsensical threshold. Never throws. Unlike the per-repo cap, this install-wide cap is not clamped to the + * per-repo live-check budget because the install-wide verifier loads and verifies a larger row set. */ export function resolveGlobalContributorOpenItemCap(env: { GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP?: string | undefined }): number | null { const raw = env[GLOBAL_ENV_KEY]; if (typeof raw !== "string" || raw.trim() === "") return null; const parsed = Number(raw); if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed <= 0) return null; - return Math.min(parsed, MAX_CONTRIBUTOR_OPEN_ITEM_CAP); + return parsed; } diff --git a/test/unit/global-contributor-cap.test.ts b/test/unit/global-contributor-cap.test.ts index 58386be6ed..7a33aab578 100644 --- a/test/unit/global-contributor-cap.test.ts +++ b/test/unit/global-contributor-cap.test.ts @@ -14,10 +14,9 @@ describe("resolveGlobalContributorOpenItemCap (#2562)", () => { expect(resolveGlobalContributorOpenItemCap({ GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP: "1" })).toBe(1); }); - // Live enforcement only ever samples a fixed 100-row budget (MAX_CONTRIBUTOR_OPEN_ITEM_CAP), so a configured - // value above that is silently unenforceable -- mirrors normalizeOpenItemCap's own clamp (db/repositories.ts). - it("clamps a value above the live-check sample budget to 100, and preserves exactly 100 unclamped", () => { - expect(resolveGlobalContributorOpenItemCap({ GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP: "500" })).toBe(100); + it("preserves install-wide caps above the per-repo live-check sample budget (regression for unintended 100-item clamp)", () => { + expect(resolveGlobalContributorOpenItemCap({ GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP: "500" })).toBe(500); + expect(resolveGlobalContributorOpenItemCap({ GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP: "101" })).toBe(101); expect(resolveGlobalContributorOpenItemCap({ GLOBAL_CONTRIBUTOR_OPEN_ITEM_CAP: "100" })).toBe(100); });