Recognise declared Pro server artifacts during issue intake (#3219)

The published native Pro archive and paid registry image currently
become missing-version reports, unlike the Community server artifact.
Accept those server naming shapes without mining unknown fields, link
destinations, signatures or companion binaries. Exercise the actual
silent label consumer and preserve Community-owned state and the
live-read fence.

Contract-Neutral: Silent issue version classification and registered
regression controls only; no Pulse runtime, rendered product surface,
subsystem contract, dependency, access or public-contact change.

---
Fleet candidate `20261024T201018Z-product-intelligence` from the
`product-intelligence` lane. Reviewed tip
`18d7e0d2d74ba1b5f1325d11584bd5095a48fa2e` on `main`.
Lands together with: pulse-pro
https://github.com/rcourtman/pulse-pro/pull/529.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
This commit is contained in:
pulse-triage[bot]
2026-10-24 22:25:22 +01:00
committed by GitHub
2 changed files with 58 additions and 4 deletions
+4 -4
View File
@@ -165,12 +165,12 @@ function normalizeLegacyVersionValue(value) {
const visible = text.trim().replace(/^[`*_]+/, "");
// Failed-install forms explicitly accept an attempted server archive. Its
// packaging suffix is not part of the release version. Recognise only the
// server archive names; companion binaries and signatures cannot establish
// the attempted server executable's version.
// Community and Pro server archive names; companion binaries and signatures
// cannot establish the attempted server executable's version.
const filename = visible.match(/^pulse-[^\s`*_]+/i)?.[0];
if (filename && /\.(?:tar\.gz|tgz|zip|exe|sha256|sig|sshsig)(?:\.|$)/i.test(filename)) {
const archive = filename.match(
/^pulse-v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\.(?:tar\.gz|tgz)$/i
/^pulse-(?:pro-)?v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\.(?:tar\.gz|tgz)$/i
);
return archive ? normalizeVersion(archive[1].replace(
/-linux-(?:386|amd64|arm64|armv6|armv7)$/i, ""
@@ -178,7 +178,7 @@ function normalizeLegacyVersionValue(value) {
}
// Keep an explicitly shared server/agent version (as in #1788), without
// mining a sentence such as "unknown; agent version 6.5.0" for a number.
return /^(?:v?\d+\.\d+\.\d+\b|(?:pulse|server(?:[ \t]*\+[ \t]*pulse-agent)?)[ \t]+v?\d+\.\d+\.\d+\b|(?:[a-z0-9._/-]+\/)?pulse:|pulse[-_])/i.test(visible)
return /^(?:v?\d+\.\d+\.\d+\b|(?:pulse|server(?:[ \t]*\+[ \t]*pulse-agent)?)[ \t]+v?\d+\.\d+\.\d+\b|(?:[a-z0-9._/-]+\/)?pulse(?:-pro)?:|pulse[-_])/i.test(visible)
? normalizeVersion(visible) : null;
}
@@ -1821,6 +1821,60 @@ test("non-server artifacts cannot supply an attempted server version", () => {
}
});
test("Pro server artifacts retain their declared version without borrowing agent evidence", () => {
const { extractPulseVersion } = triage.internals;
for (const version of ["6.5.0", "6.6.0-beta.3", "6.6.0-rc.6"]) {
for (const artifact of [
`pulse-pro-v${version}-linux-amd64.tar.gz`,
`pulse-pro-v${version}-linux-arm64.tar.gz`,
`license.pulserelay.pro/pulse-pro:${version}`,
]) {
for (const value of [artifact, `**\`${artifact}\`**`, `[${artifact}](https://example.invalid/6.4.5)`]) {
for (const field of ["### Pulse version\n", "Pulse version: ", "- **Pulse version**: "]) {
for (const newline of ["\n", "\r\n"]) {
const body = `${field}${value}\n\n### Agent version\n6.4.5`.replaceAll("\n", newline);
assert.equal(extractPulseVersion("Upgrade from v6.4.5", body), version, body);
}
}
}
}
}
for (const value of [
"pulse-pro-agent-v6.6.0-rc.6-linux-amd64.tar.gz",
"pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz.sshsig",
"pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz.sha256",
"pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz.sig",
"unknown; downloaded pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz",
"[unknown](https://example.invalid/pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz)",
]) {
assert.equal(extractPulseVersion("Upgrade from v6.4.5",
`### Pulse version\n${value}\n### Agent version\n6.4.5`), null, value);
}
});
for (const value of [
"pulse-pro-v6.6.0-rc.6-linux-amd64.tar.gz",
"pulse-pro-v6.6.0-rc.6-linux-arm64.tar.gz",
"license.pulserelay.pro/pulse-pro:6.6.0-rc.6",
]) {
test(`Pro server intake updates only silent version metadata: ${value}`, async () => {
const { github, calls } = createGithub();
const issue = { number: 2923, title: "Failed install", labels: [
"bug", "affects-6.4.5", "needs-version-info", "needs-human", "release-blocker",
"needs-decomposition", "needs-retest-on-latest",
].map(name => ({ name })),
body: `### Pulse version\n${value}\n### Agent version\n6.4.5` };
await syncLabels({ github, context: createContext({ issue }), core: createCore() });
assert.deepEqual(calls.addLabels.map(call => call.labels), [["affects-6.6.0-rc.6"]]);
assert.deepEqual(calls.removeLabel.map(call => call.name), ["affects-6.4.5", "needs-version-info"]);
assert.deepEqual(calls.createLabel.map(call => call.name), ["affects-6.6.0-rc.6"]);
assert.deepEqual(calls.createComment, []);
assert.deepEqual(calls.getLatestRelease, []);
assert.deepEqual(calls.paginate, []);
assert.equal(calls.getIssue.length, 2);
});
}
test("archive recognition neither borrows a later filename nor shortens bare prereleases", () => {
const { extractPulseVersion } = triage.internals;
assert.equal(extractPulseVersion("Upgrade from v6.4.5",