From b8e64d1fffe90d76a2cddbffd0cd1ba792ef8bc6 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 02:27:20 +0000 Subject: [PATCH] Keep feature-request context out of secondary-topic review Bound reordered topic declarations at all four feature-request context fields. Extend the registered form-derived parser and consumer controls to every issue template, preserving cleared reviews on context edits and restoring review only for a real revised topic. Contract-Neutral: Silent issue-label metadata only; no product runtime, frontend, dependency, access or canonical subsystem contract delta. Change-source: pulse-maintainer --- .github/scripts/issue-version-triage.cjs | 4 +++ .github/scripts/issue-version-triage.test.cjs | 34 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/scripts/issue-version-triage.cjs b/.github/scripts/issue-version-triage.cjs index 3a8e6fa8d7..31700858f8 100644 --- a/.github/scripts/issue-version-triage.cjs +++ b/.github/scripts/issue-version-triage.cjs @@ -135,6 +135,10 @@ function additionalActionableTopicsValue(body) { "Additional context", "Logs, screenshots, or diagnostics", "Confirmations", + "Problem", + "Current workflow", + "Desired outcome", + "Alternatives considered", ]); } diff --git a/.github/scripts/issue-version-triage.test.cjs b/.github/scripts/issue-version-triage.test.cjs index f706b7e679..e8ef68125d 100644 --- a/.github/scripts/issue-version-triage.test.cjs +++ b/.github/scripts/issue-version-triage.test.cjs @@ -542,8 +542,9 @@ test("topic classification stops at form fields but retains topic subheadings", function topicBoundaryFields() { const fields = new Set(["Additional context"]); - for (const name of ["bug_report.yml", "v6_rc_feedback.yml"]) { - const form = fs.readFileSync(path.resolve(__dirname, "../ISSUE_TEMPLATE", name), "utf8"); + const directory = path.resolve(__dirname, "../ISSUE_TEMPLATE"); + for (const name of fs.readdirSync(directory).filter(name => /\.ya?ml$/.test(name))) { + const form = fs.readFileSync(path.join(directory, name), "utf8"); for (const [, label] of form.matchAll(/^ label: (.+)$/gm)) { if (label !== "Additional actionable topics") fields.add(label); } @@ -612,6 +613,35 @@ test("opening or editing neighbouring context cannot invent a decomposition task } }); +test("feature context edits preserve a cleared review while real topic edits restore it", async () => { + const { github, calls } = createGithub(); + const body = (context, topic = "None") => [ + "### Additional actionable topics", topic, "", + "### Desired outcome", context, "", + "### Alternatives considered", "An existing workaround.", + ].join("\n"); + const labels = ["enhancement", "needs-human", "needs-retest-on-latest"]; + const issue = { number: 2925, title: "Existing feature request", body: body("Clarified outcome"), + labels: labels.map(name => ({ name })) }; + await syncLabels({ github, core: createCore(), context: createContext({ + action: "edited", issue, previousBody: body("Original outcome"), + }) }); + assert.deepEqual(calls.addLabels, []); + assert.deepEqual(calls.createLabel, []); + + const revised = { ...issue, body: body("Clarified outcome", "Also retain failed attempts in History.") }; + const context = createContext({ + action: "edited", issue: revised, previousBody: issue.body, + }); + github.currentIssue = { ...context.payload.issue, state: "open" }; + await syncLabels({ github, core: createCore(), context }); + assert.deepEqual(calls.addLabels.map(call => call.labels), [["needs-decomposition"]]); + assert.deepEqual(calls.removeLabel, []); + assert.deepEqual(calls.createComment, []); + assert.deepEqual(calls.getLatestRelease, []); + assert.deepEqual(calls.paginate, []); +}); + test("real revised topics still reopen review without disposing of existing tasks", async () => { for (const existingTask of [false, true]) { const { github, calls } = createGithub();