diff --git a/.agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs b/.agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs
index c71ed0a6027a..f123b24f002e 100644
--- a/.agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs
+++ b/.agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs
@@ -684,7 +684,7 @@ export function contributionRecordTarget(section) {
}
export function pullRequestTitleFromCommitSubject(subject, number) {
- const match = subject.match(/^(?
\S(?:.*?\S)?)(? \(#(?[1-9]\d*)\))\k*$/u);
+ const match = subject.match(/^(?\S(?:.*\S)?)(?[1-9]\d*)\)$/u);
return match?.groups?.number === String(number) ? match.groups.title : undefined;
}
@@ -839,7 +839,7 @@ function appendReferences(references, additions) {
function normalizedCommitSubject(subject) {
return subject
- .replace(/\s+\(#\d+\)\s*$/, "")
+ .replace(/(?:\s+\(#\d+\))+\s*$/, "")
.replace(/\s+/g, " ")
.trim()
.toLowerCase();
diff --git a/test/scripts/verify-release-notes.test.ts b/test/scripts/verify-release-notes.test.ts
index e7c80e9a024b..e63845dee4d8 100644
--- a/test/scripts/verify-release-notes.test.ts
+++ b/test/scripts/verify-release-notes.test.ts
@@ -58,13 +58,13 @@ describe("release-note verification", () => {
});
it("accepts only canonical commit PR suffixes", () => {
+ const repeated = "Fix status (#102147) (#102147)";
+ const distinct = "Fix status (#120582) (#120584)";
expect(pullRequestTitleFromCommitSubject("Fix status (#102147)", 102147)).toBe("Fix status");
- expect(pullRequestTitleFromCommitSubject("Fix status (#102147) (#102147)", 102147)).toBe(
- "Fix status",
- );
+ expect(pullRequestTitleFromCommitSubject(repeated, 102147)).toBeUndefined();
+ expect(pullRequestTitleFromCommitSubject(distinct, 120584)).toBeUndefined();
expect(pullRequestTitleFromCommitSubject("Fix status(#102147)", 102147)).toBeUndefined();
expect(pullRequestTitleFromCommitSubject("Fix status (#0102147)", 102147)).toBeUndefined();
- expect(pullRequestTitleFromCommitSubject("Fix status (#0)", 0)).toBeUndefined();
expect(pullRequestTitleFromCommitSubject(" Fix status (#102147)", 102147)).toBeUndefined();
expect(pullRequestTitleFromCommitSubject("Fix status (#102147) ", 102147)).toBeUndefined();
expect(pullRequestTitleFromCommitSubject("Fix status (#102148)", 102147)).toBeUndefined();
@@ -481,6 +481,12 @@ describe("release-note verification", () => {
},
]),
).toEqual([mainCommit.hash]);
+ const backportSubject = "fix(gateway): retain work admission across hosted wizard steps";
+ mainCommit.subject = `${backportSubject} (#120582)`;
+ integratedBackport.subject = `${mainCommit.subject} (#120584)`;
+ expect(canonicalMainCommitMatches(integratedBackport, [mainCommit])).toEqual([mainCommit.hash]);
+ const malformed = { ...integratedBackport, subject: `${backportSubject}(#120582) (#120584)` };
+ expect(canonicalMainCommitMatches(malformed, [mainCommit])).toEqual([]);
expect(canonicalPullRequests([456], [123])).toEqual([123]);
});