diff --git a/.github/workflows/smoke-gemini.lock.yml b/.github/workflows/smoke-gemini.lock.yml index d1d6955c678..3e2b7c571ba 100644 --- a/.github/workflows/smoke-gemini.lock.yml +++ b/.github/workflows/smoke-gemini.lock.yml @@ -404,7 +404,7 @@ jobs: version: "", agent_version: "", workflow_name: "Smoke Gemini", - experimental: true, + experimental: false, supports_tools_allowlist: true, run_id: context.runId, run_number: context.runNumber, diff --git a/actions/setup/js/collect_ndjson_output.test.cjs b/actions/setup/js/collect_ndjson_output.test.cjs index ba2f678f09e..0257ae2954c 100644 --- a/actions/setup/js/collect_ndjson_output.test.cjs +++ b/actions/setup/js/collect_ndjson_output.test.cjs @@ -1219,7 +1219,7 @@ describe("collect_ndjson_output.cjs", () => { parsedOutput = JSON.parse(outputCall[1]); expect(parsedOutput.items[0].body).toBe("Hey `@username` and `@org/team`, check this out! But preserve email@domain.com"); }), - it("should neutralize bot trigger phrases", async () => { + it("should not escape issue-closing keywords in output", async () => { const testFile = "/tmp/gh-aw/test-ndjson-output.txt", ndjsonContent = '{"type": "create_issue", "title": "Bot Trigger Test", "body": "This fixes #123 and closes #456, also resolves #789"}'; (fs.writeFileSync(testFile, ndjsonContent), (process.env.GH_AW_SAFE_OUTPUTS = testFile)); @@ -1228,7 +1228,7 @@ describe("collect_ndjson_output.cjs", () => { (fs.mkdirSync("/opt/gh-aw/safeoutputs", { recursive: !0 }), fs.writeFileSync(configPath, __config), await eval(`(async () => { ${collectScript}; await main(); })()`)); const outputCall = mockCore.setOutput.mock.calls.find(call => "output" === call[0]), parsedOutput = JSON.parse(outputCall[1]); - expect(parsedOutput.items[0].body).toBe("This `fixes #123` and `closes #456`, also `resolves #789`"); + expect(parsedOutput.items[0].body).toBe("This fixes #123 and closes #456, also resolves #789"); }), it("should remove ANSI escape sequences", async () => { const testFile = "/tmp/gh-aw/test-ndjson-output.txt", @@ -1488,7 +1488,10 @@ describe("collect_ndjson_output.cjs", () => { outputCall = setOutputCalls.find(call => "output" === call[0]); expect(outputCall).toBeDefined(); const parsedOutput = JSON.parse(outputCall[1]); - (expect(parsedOutput.items).toHaveLength(1), expect(parsedOutput.items[0].message).toContain("`@mention`"), expect(parsedOutput.items[0].message).toContain("`fixes #123`")); + (expect(parsedOutput.items).toHaveLength(1), + expect(parsedOutput.items[0].message).toContain("`@mention`"), + expect(parsedOutput.items[0].message).not.toContain("`fixes #123`"), + expect(parsedOutput.items[0].message).toContain("fixes #123")); }), it("should handle multiple noop messages", async () => { const testFile = "/tmp/gh-aw/test-ndjson-output.txt", diff --git a/actions/setup/js/compute_text.test.cjs b/actions/setup/js/compute_text.test.cjs index 4ec6a49be91..002b519d865 100644 --- a/actions/setup/js/compute_text.test.cjs +++ b/actions/setup/js/compute_text.test.cjs @@ -50,9 +50,9 @@ const mockCore = { const result = sanitizeIncomingTextFunction("Hello @user and @org/team"); (expect(result).toContain("`@user`"), expect(result).toContain("`@org/team`")); }), - it("should neutralize bot trigger phrases", () => { + it("should not escape issue-closing keywords in incoming text", () => { const result = sanitizeIncomingTextFunction("This fixes #123 and closes #456"); - (expect(result).toContain("`fixes #123`"), expect(result).toContain("`closes #456`")); + (expect(result).toContain("fixes #123"), expect(result).toContain("closes #456"), expect(result).not.toContain("`fixes #123`"), expect(result).not.toContain("`closes #456`")); }), it("should remove control characters", () => { const result = sanitizeIncomingTextFunction("Hello\0\bworld"); @@ -203,7 +203,7 @@ const mockCore = { it("should sanitize extracted text before output", async () => { ((mockContext.eventName = "issues"), (mockContext.payload = { issue: { title: "Test @user fixes #123", body: "Visit https://evil.com" } }), await testMain()); const outputCall = mockCore.setOutput.mock.calls[0]; - (expect(outputCall[1]).toContain("`@user`"), expect(outputCall[1]).toContain("`fixes #123`"), expect(outputCall[1]).toContain("/redacted")); + (expect(outputCall[1]).toContain("`@user`"), expect(outputCall[1]).not.toContain("`fixes #123`"), expect(outputCall[1]).toContain("fixes #123"), expect(outputCall[1]).toContain("/redacted")); }), it("should handle missing title and body gracefully", async () => { ((mockContext.eventName = "issues"), diff --git a/actions/setup/js/sanitize_content.cjs b/actions/setup/js/sanitize_content.cjs index 8d1672b1c24..7fb71fae472 100644 --- a/actions/setup/js/sanitize_content.cjs +++ b/actions/setup/js/sanitize_content.cjs @@ -19,7 +19,6 @@ const { neutralizeGitHubReferences, removeXmlComments, convertXmlTags, - neutralizeBotTriggers, applyTruncation, hardenUnicodeText, } = require("./sanitize_content_core.cjs"); @@ -102,9 +101,6 @@ function sanitizeContent(content, maxLengthOrOptions) { // Neutralize GitHub references if restrictions are configured sanitized = neutralizeGitHubReferences(sanitized, allowedGitHubRefs); - // Neutralize bot triggers - sanitized = neutralizeBotTriggers(sanitized); - // Balance markdown code regions to fix improperly nested fences // This repairs markdown where AI models generate nested code blocks at the same indentation sanitized = balanceCodeRegions(sanitized); diff --git a/actions/setup/js/sanitize_content.test.cjs b/actions/setup/js/sanitize_content.test.cjs index 668663c1c1a..8b5c9823dbc 100644 --- a/actions/setup/js/sanitize_content.test.cjs +++ b/actions/setup/js/sanitize_content.test.cjs @@ -745,33 +745,33 @@ describe("sanitize_content.cjs", () => { }); }); - describe("bot trigger neutralization", () => { - it("should neutralize 'fixes #123' patterns", () => { + describe("bot trigger passthrough", () => { + it("should not escape 'fixes #123' patterns", () => { const result = sanitizeContent("This fixes #123"); - expect(result).toBe("This `fixes #123`"); + expect(result).toBe("This fixes #123"); }); - it("should neutralize 'closes #456' patterns", () => { + it("should not escape 'closes #456' patterns", () => { const result = sanitizeContent("PR closes #456"); - expect(result).toBe("PR `closes #456`"); + expect(result).toBe("PR closes #456"); }); - it("should neutralize 'resolves #789' patterns", () => { + it("should not escape 'resolves #789' patterns", () => { const result = sanitizeContent("This resolves #789"); - expect(result).toBe("This `resolves #789`"); + expect(result).toBe("This resolves #789"); }); - it("should handle various bot trigger verbs", () => { + it("should not escape various issue-closing verbs", () => { const triggers = ["fix", "fixes", "close", "closes", "resolve", "resolves"]; triggers.forEach(verb => { const result = sanitizeContent(`This ${verb} #123`); - expect(result).toBe(`This \`${verb} #123\``); + expect(result).toBe(`This ${verb} #123`); }); }); - it("should neutralize alphanumeric issue references", () => { + it("should not escape alphanumeric issue references", () => { const result = sanitizeContent("fixes #abc123def"); - expect(result).toBe("`fixes #abc123def`"); + expect(result).toBe("fixes #abc123def"); }); }); @@ -1063,7 +1063,8 @@ describe("sanitize_content.cjs", () => { expect(result).toContain("https://github.com"); expect(result).not.toContain("