feat(triage): add detectDelivered with confidence grading

This commit is contained in:
diegosouzapw
2026-05-19 02:45:31 -03:00
parent 8cca3630ae
commit 3fbec5065e
2 changed files with 113 additions and 0 deletions

View File

@@ -37,3 +37,52 @@ export function parseChangelog(text, issueNumber) {
}
return null;
}
function isExplicitClose(pr, issueNumber) {
const text = `${pr.title ?? ""}\n${pr.body ?? ""}`;
const re = new RegExp(`\\b(closes?|fixes?|fixed|resolves?|resolved)\\s+#${issueNumber}\\b`, "i");
return re.test(text);
}
function justMentions(pr, issueNumber) {
const text = `${pr.title ?? ""}\n${pr.body ?? ""}`;
return new RegExp(`#${issueNumber}\\b`).test(text);
}
export function detectDelivered(issueNumber, signals) {
const { mergedPrs = [], changelog = "", gitCommits = [] } = signals;
const closesPr = mergedPrs.find((p) => isExplicitClose(p, issueNumber));
const mentionPr = closesPr || mergedPrs.find((p) => justMentions(p, issueNumber));
const changelogHit = parseChangelog(changelog, issueNumber);
const gitHit = gitCommits.length > 0 ? gitCommits[0] : null;
const A = !!closesPr;
const B = !!(mentionPr && !closesPr);
const C = !!changelogHit;
const D = !!gitHit;
let confidence = "none";
if (A) confidence = "high";
else if ((C && D) || (B && C) || (B && D)) confidence = "medium";
else if (B || C || D) confidence = "low";
const evidence = {};
if (closesPr) {
evidence.pr_merged = {
number: closesPr.number,
merged_at: closesPr.mergedAt,
ref: `closes #${issueNumber}`,
};
} else if (mentionPr) {
evidence.pr_merged = {
number: mentionPr.number,
merged_at: mentionPr.mergedAt,
ref: `mentions #${issueNumber}`,
};
}
if (changelogHit) evidence.changelog_section = changelogHit.section;
if (gitHit) evidence.git_commits = gitCommits.slice(0, 5).map((c) => c.hash);
return { confidence, evidence };
}

View File

@@ -47,3 +47,67 @@ describe("parseChangelog", () => {
assert.match(r.line, /#980/);
});
});
import { detectDelivered } from "../../../scripts/features/lib/delivered.mjs";
const CLOSES_PR = {
number: 2380,
title: "feat: add native playground",
body: "closes #1046",
mergedAt: "2026-03-10T00:00:00Z",
mergeCommit: { oid: "abc1234" },
};
const MENTION_PR = {
number: 2381,
title: "Improve foo",
body: "Related to #1046 and others",
mergedAt: "2026-03-12T00:00:00Z",
mergeCommit: { oid: "def5678" },
};
describe("detectDelivered", () => {
it("HIGH confidence when PR merged with 'closes #N'", () => {
const r = detectDelivered(1046, {
mergedPrs: [CLOSES_PR],
changelog: "",
gitCommits: [],
});
assert.equal(r.confidence, "high");
assert.equal(r.evidence.pr_merged.number, 2380);
assert.match(r.evidence.pr_merged.ref, /closes/i);
});
it("MEDIUM confidence when PR-mention + CHANGELOG", () => {
const r = detectDelivered(1046, {
mergedPrs: [MENTION_PR],
changelog: "## [3.7.2]\n- Foo (#1046)\n",
gitCommits: [],
});
assert.equal(r.confidence, "medium");
assert.equal(r.evidence.pr_merged.number, 2381);
assert.equal(r.evidence.changelog_section, "## [3.7.2]");
});
it("MEDIUM confidence when CHANGELOG + git log", () => {
const r = detectDelivered(1046, {
mergedPrs: [],
changelog: "## [3.7.2]\n- Foo (#1046)\n",
gitCommits: [{ hash: "abc", date: new Date("2026-03-10"), subject: "feat: thing #1046" }],
});
assert.equal(r.confidence, "medium");
});
it("LOW confidence when only CHANGELOG", () => {
const r = detectDelivered(1046, {
mergedPrs: [],
changelog: "## [3.7.2]\n- Foo (#1046)\n",
gitCommits: [],
});
assert.equal(r.confidence, "low");
});
it("NONE when no signals", () => {
const r = detectDelivered(1046, { mergedPrs: [], changelog: "", gitCommits: [] });
assert.equal(r.confidence, "none");
});
});