From cf33ba18ed61d12e0e9aeb6f3fb3cfe1f4170fa5 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Mon, 6 Apr 2026 09:28:22 -0700 Subject: [PATCH 1/3] Add workflow_dispatch trigger to collect-corrections workflow The triage feedback slash command is a preview feature only available in private repos. Add a workflow_dispatch trigger with issue_number and feedback inputs so the workflow can be dispatched manually from the Actions UI. - Add workflow_dispatch trigger with required inputs to collect-corrections.yml - Fall back to context.payload.inputs when client_payload is absent - Add integration test for the workflow_dispatch payload path --- .github/workflows/collect-corrections.yml | 10 +++++ scripts/corrections/collect-corrections.js | 2 +- .../test/collect-corrections.test.ts | 38 ++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/.github/workflows/collect-corrections.yml b/.github/workflows/collect-corrections.yml index 819e19d150..e70ab78266 100644 --- a/.github/workflows/collect-corrections.yml +++ b/.github/workflows/collect-corrections.yml @@ -3,6 +3,16 @@ name: Collect triage agent corrections on: repository_dispatch: types: [triage_feedback] + workflow_dispatch: + inputs: + issue_number: + description: "Issue number to submit feedback for" + required: true + type: string + feedback: + description: "Feedback text describing what the triage agent got wrong" + required: true + type: string concurrency: group: collect-corrections diff --git a/scripts/corrections/collect-corrections.js b/scripts/corrections/collect-corrections.js index caeca42b64..9b3b14e9b1 100644 --- a/scripts/corrections/collect-corrections.js +++ b/scripts/corrections/collect-corrections.js @@ -203,7 +203,7 @@ async function maybeAssignCCA(github, owner, repo, trackingIssue, correctionCoun */ module.exports = async ({ github, context }) => { const { owner, repo } = context.repo; - const payload = context.payload.client_payload ?? {}; + const payload = context.payload.client_payload ?? context.payload.inputs ?? {}; const sender = context.payload.sender?.login ?? "unknown"; const correction = resolveContext(payload, sender); diff --git a/scripts/corrections/test/collect-corrections.test.ts b/scripts/corrections/test/collect-corrections.test.ts index 939bae188e..8b34b939b4 100644 --- a/scripts/corrections/test/collect-corrections.test.ts +++ b/scripts/corrections/test/collect-corrections.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from "vitest"; +import { describe, expect, it, vi } from "vitest"; const mod = await import("../collect-corrections.js"); const { @@ -304,6 +304,42 @@ describe("appendCorrection", () => { }); }); +describe("module entrypoint - workflow_dispatch", () => { + it("processes feedback from workflow_dispatch inputs", async () => { + const github = mockGitHub({ + listForRepo: vi.fn().mockResolvedValue({ + data: [{ number: 50, assignees: [], body: trackingBodyForEntrypoint }], + }), + }); + const context = { + repo: { owner: OWNER, repo: REPO }, + payload: { + // workflow_dispatch has no client_payload; inputs carry the data + inputs: { issue_number: "7", feedback: "Should be enhancement" }, + sender: { login: "dispatcher" }, + }, + }; + + await mod.default({ github, context }); + + // Verify the correction was appended referencing the right issue + expect(github.rest.issues.update).toHaveBeenCalledWith( + expect.objectContaining({ + issue_number: 50, + body: expect.stringContaining("[#7]"), + }), + ); + }); +}); + +const trackingBodyForEntrypoint = [ + "# Triage Agent Corrections", + "", + "| Issue | Feedback | Submitted by | Date |", + "|-------|----------|--------------|------|", + "", +].join("\n"); + describe("maybeAssignCCA", () => { it("assigns CCA when threshold is reached", async () => { const github = mockGitHub(); From 133b4673a2f5e5d275841e0584df8b58a54a89e2 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Mon, 6 Apr 2026 09:37:29 -0700 Subject: [PATCH 2/3] Rename collect-corrections workflow to Submit triage agent feedback --- .github/workflows/collect-corrections.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/collect-corrections.yml b/.github/workflows/collect-corrections.yml index e70ab78266..5284e33427 100644 --- a/.github/workflows/collect-corrections.yml +++ b/.github/workflows/collect-corrections.yml @@ -1,4 +1,4 @@ -name: Collect triage agent corrections +name: Submit triage agent feedback on: repository_dispatch: From e9901ca9882e858fc22f969c4dffb700a47b373a Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Mon, 6 Apr 2026 09:43:31 -0700 Subject: [PATCH 3/3] Validate issue_number is a finite positive integer in resolveContext --- scripts/corrections/collect-corrections.js | 7 ++++++- .../test/collect-corrections.test.ts | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/scripts/corrections/collect-corrections.js b/scripts/corrections/collect-corrections.js index 9b3b14e9b1..a03a1c2add 100644 --- a/scripts/corrections/collect-corrections.js +++ b/scripts/corrections/collect-corrections.js @@ -82,7 +82,12 @@ function resolveContext(payload, sender) { throw new Error("Missing feedback in payload"); } - return { issueNumber: Number(issueNumber), feedback, sender }; + const parsed = Number(issueNumber); + if (!Number.isFinite(parsed) || parsed < 1 || !Number.isInteger(parsed)) { + throw new Error(`Invalid issue_number: ${issueNumber}`); + } + + return { issueNumber: parsed, feedback, sender }; } /** diff --git a/scripts/corrections/test/collect-corrections.test.ts b/scripts/corrections/test/collect-corrections.test.ts index 8b34b939b4..ade318dd96 100644 --- a/scripts/corrections/test/collect-corrections.test.ts +++ b/scripts/corrections/test/collect-corrections.test.ts @@ -134,6 +134,24 @@ describe("resolveContext", () => { resolveContext({ issue_number: "1" }, "u"), ).toThrow("Missing feedback"); }); + + it("throws on non-numeric issue number", () => { + expect(() => + resolveContext({ issue_number: "abc", feedback: "test" }, "u"), + ).toThrow("Invalid issue_number: abc"); + }); + + it("throws on negative issue number", () => { + expect(() => + resolveContext({ issue_number: "-1", feedback: "test" }, "u"), + ).toThrow("Invalid issue_number: -1"); + }); + + it("throws on decimal issue number", () => { + expect(() => + resolveContext({ issue_number: "1.5", feedback: "test" }, "u"), + ).toThrow("Invalid issue_number: 1.5"); + }); }); // ---------------------------------------------------------------------------