From 70f9e964905a4835c7bd2ba72c1bb6cd374642a9 Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:10:45 -0600 Subject: [PATCH] fix: redact private blocker codes in public comments --- src/github/commands.ts | 14 +++++++------- test/unit/github-commands.test.ts | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/github/commands.ts b/src/github/commands.ts index ef324a117d..10ab8622e5 100644 --- a/src/github/commands.ts +++ b/src/github/commands.ts @@ -1289,15 +1289,13 @@ function mentionsRepoOutcomePatternDetail(value: string): boolean { function publicBlockerLabel(code: string): string { const normalized = code.trim().toLowerCase(); + const privateDecisionBlockers = new Set(["open_pr_pressure", "closed_pr_credibility", "low_credibility", "maintainer_lane", "inactive_or_unknown_lane", "issue_discovery_only"]); const labels: Record = { likely_duplicate: "Possible overlap with existing work", - open_pr_pressure: "Open pull request queue pressure", - closed_pr_credibility: "Closed pull request credibility signal", - inactive_or_unknown_lane: "Repository lane is inactive or unknown", - issue_discovery_only: "Repository is issue-discovery only", - low_credibility: "Contributor credibility needs improvement", - maintainer_lane: "Maintainer-lane activity is separate from outside-contributor work", }; + if (privateDecisionBlockers.has(normalized)) { + return "Private readiness context available in authenticated Gittensory views"; + } return labels[normalized] ?? sanitizePublicComment(code.replace(/_/g, " ")); } @@ -1307,7 +1305,7 @@ function publicBlockerDetail(value: string): string { value .replace(/\blikely_duplicate\b/gi, "possible overlap with existing work") .replace(/\bcheck_duplicate_risk\b/gi, "duplicate-risk review") - .replace(/\bopen_pr_pressure\b/gi, "open pull request pressure"), + .replace(/\b(?:open_pr_pressure|closed_pr_credibility|low_credibility|maintainer_lane|inactive_or_unknown_lane|issue_discovery_only)\b/gi, "private readiness context"), ), ); } @@ -1342,6 +1340,8 @@ export function sanitizePublicComment(value: string): string { .replace(/\b(public score estimate|estimated score|score estimate|reward estimates?|payout|farming|scoreability|score preview|projected score changes?)\b/gi, "private context") .replace(/\b(private reviewability|reviewability internals?)\b/gi, "private context") .replace(/\b(private ranking|private rankings)\b/gi, "private context") + .replace(/\b(?:open_pr_pressure|closed_pr_credibility|low_credibility|maintainer_lane|inactive_or_unknown_lane|issue_discovery_only)\b/gi, "private context") + .replace(/\b(?:credibility(?: updates?)?|closed pr credibility|low credibility|open pr pressure)\b/gi, "private context") .replace(/\blikely_duplicate\b/gi, "possible overlap with existing work"); return sanitizeReviewabilityTerm(sanitized).replace(/private context(?:,\s*private context)+/gi, "private context"); } diff --git a/test/unit/github-commands.test.ts b/test/unit/github-commands.test.ts index c1db9a1c70..5eec68f558 100644 --- a/test/unit/github-commands.test.ts +++ b/test/unit/github-commands.test.ts @@ -148,6 +148,7 @@ describe("GitHub mention commands", () => { expect(sanitizePublicComment("public score estimate and scoreability should stay private")).not.toMatch(/public score estimate|scoreability/i); expect(sanitizePublicComment("public score estimate private scoreability context score preview")).not.toMatch(/public score estimate|scoreability|score preview/i); expect(sanitizePublicComment("projected score changes 12.3 -> 45.6")).not.toMatch(/projected score changes|12\.3|45\.6/i); + expect(sanitizePublicComment("open_pr_pressure closed_pr_credibility low_credibility credibility updates")).not.toMatch(/open_pr_pressure|closed_pr_credibility|low_credibility|credibility/i); expect(sanitizePublicComment("Command: @gittensory reviewability")).toContain("@gittensory reviewability"); expect(sanitizePublicComment("private ranking, wallet, payout")).toBe("private context"); }); @@ -271,7 +272,7 @@ describe("GitHub mention commands", () => { expect(blockers).toContain("**Gittensory readiness blockers**"); expect(blockers).toContain("**Readiness blockers**"); expect(blockers).toContain("Resolve queue pressure before opening more work."); - expect(blockers).toContain("Open pull request queue pressure"); + expect(blockers).toContain("Private readiness context available in authenticated Gittensory views"); expect(blockers).not.toContain("5 open PR(s)"); const duplicateCheck = buildPublicAgentCommandComment({ @@ -405,10 +406,9 @@ describe("GitHub mention commands", () => { }); expect(body).toContain("Resolve public readiness blockers before opening more work."); - expect(body).toContain("Open pull request queue pressure"); - expect(body).toContain("Closed pull request credibility signal"); - expect(body).toContain("Contributor credibility needs improvement"); - expect(body).not.toMatch(/5 open PR\(s\)|Closed PR rate is 48%|Official repo credibility is 0\.42/i); + expect(body).toContain("Private readiness context available in authenticated Gittensory views"); + expect(body).not.toMatch(/closed_pr_credibility|low_credibility|credibility/i); + expect(body).not.toMatch(/open_pr_pressure|closed_pr_credibility|low_credibility|5 open PR\(s\)|Closed PR rate is 48%|Official repo credibility is 0\.42/i); }); it("renders help, miner-context fallback, refresh, and empty-action responses", () => { @@ -933,7 +933,7 @@ describe("GitHub mention commands", () => { summary: "blockers", }, }); - expect(blockersWithDuplicateCodes.match(/Open pull request queue pressure/g)).toHaveLength(1); + expect(blockersWithDuplicateCodes.match(/Private readiness context available in authenticated Gittensory views/g)).toHaveLength(1); const blockersFromStatus = buildPublicAgentCommandComment({ command: parseGittensoryMentionCommand("@gittensory blockers")!, @@ -962,7 +962,7 @@ describe("GitHub mention commands", () => { summary: "blockers", }, }); - expect(blockersFromStatus.match(/Open pull request queue pressure/g)).toHaveLength(1); + expect(blockersFromStatus.match(/Private readiness context available in authenticated Gittensory views/g)).toHaveLength(1); const statusOnlyBlocker = buildPublicAgentCommandComment({ command: parseGittensoryMentionCommand("@gittensory blockers")!, @@ -1084,7 +1084,7 @@ describe("GitHub mention commands", () => { }, }); expect(preflightWithRerun).toContain("Rerun when:"); - expect(preflightWithRerun).toContain("Open pull request queue pressure"); + expect(preflightWithRerun).toContain("Private readiness context available in authenticated Gittensory views"); const duplicateBlockerLabels = buildPublicAgentCommandComment({ command: parseGittensoryMentionCommand("@gittensory blockers")!, @@ -1113,7 +1113,7 @@ describe("GitHub mention commands", () => { summary: "dedupe", }, }); - expect(duplicateBlockerLabels.match(/Open pull request queue pressure/g)).toHaveLength(1); + expect(duplicateBlockerLabels.match(/Private readiness context available in authenticated Gittensory views/g)).toHaveLength(1); const duplicateFallbackPick = buildPublicAgentCommandComment({ command: parseGittensoryMentionCommand("@gittensory duplicate-check")!, @@ -1365,7 +1365,7 @@ describe("GitHub mention commands", () => { summary: "blockers", }, }); - expect(duplicateBlockers.match(/Open pull request queue pressure/g)).toHaveLength(1); + expect(duplicateBlockers.match(/Private readiness context available in authenticated Gittensory views/g)).toHaveLength(1); }); it("builds maintainer-only queue digests with safe routing, sorting, and private-detail pointers", () => {