From ecee76b688c3fadb4e64cf6d1bf24810c342db33 Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:01:18 -0600 Subject: [PATCH] fix: redact private score projection deltas --- src/github/commands.ts | 3 ++- test/unit/github-commands.test.ts | 32 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/github/commands.ts b/src/github/commands.ts index 2c35c16c21..ef324a117d 100644 --- a/src/github/commands.ts +++ b/src/github/commands.ts @@ -1337,8 +1337,9 @@ function sanitizeFeedbackAnswerId(answerId: string): string { export function sanitizePublicComment(value: string): string { const sanitized = value + .replace(/\bprojected score changes?\b(?:\s+from)?\s+[-+]?\d+(?:\.\d+)?\s*(?:->|→|to)\s*[-+]?\d+(?:\.\d+)?/gi, "private context") .replace(/\b(raw trust score|trust score|wallet|hotkey|coldkey|seed phrase|mnemonic)\b/gi, "private context") - .replace(/\b(public score estimate|estimated score|score estimate|reward estimates?|payout|farming|scoreability|score preview)\b/gi, "private context") + .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(/\blikely_duplicate\b/gi, "possible overlap with existing work"); diff --git a/test/unit/github-commands.test.ts b/test/unit/github-commands.test.ts index 02172dfffc..c1db9a1c70 100644 --- a/test/unit/github-commands.test.ts +++ b/test/unit/github-commands.test.ts @@ -147,10 +147,42 @@ 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("Command: @gittensory reviewability")).toContain("@gittensory reviewability"); expect(sanitizePublicComment("private ranking, wallet, payout")).toBe("private context"); }); + it("redacts private score projection deltas from public command rerun guidance", () => { + const baseBundle = sampleBundle(); + const bundle = { + ...baseBundle, + actions: [ + { + ...baseBundle.actions[0]!, + actionType: "prepare_pr_packet" as const, + publicSafeSummary: "Prepare public PR packet after validation completes.", + rerunWhen: + "Rerun after pending PRs merge/close or after open PR count is at or below 3; projected score changes 12.3 -> 45.6.", + }, + ], + }; + + for (const mention of ["@gittensory preflight", "@gittensory reviewability", "@gittensory packet"]) { + const body = buildPublicAgentCommandComment({ + command: parseGittensoryMentionCommand(mention)!, + repo: { fullName: "owner/repo" } as any, + issue: { number: 12, title: "PR", state: "open", pull_request: {} }, + pullRequest: null, + actorKind: "author", + bundle, + }); + + expect(body).toContain("Rerun when:"); + expect(body).toContain("private context"); + expect(body).not.toMatch(/projected score changes|12\.3|45\.6/i); + } + }); + it("adds parseable aggregate-only feedback context without public leak terms", () => { const body = buildPublicAgentCommandComment({ command: parseGittensoryMentionCommand("@gittensory preflight")!,