chore(deps): address Copilot review rounds 8-10 on #2243

Three reviews I missed: my poll called the reviews endpoint without
--paginate, so it only ever read page one — the same pagination bug
this PR was reviewed for.

- Reconcile marked issues whose bump has left the open alert feed
  entirely. openAlerts asks for state=open, so a fixed or dismissed
  alert simply vanishes: its group is never built, the loop never
  visits it, and its issue kept asserting a vulnerability with a live
  Todo/High card. Both cases are covered — the zero-alert run, which
  used to return before loading issues at all, and a vanished group
  while other groups remain.
- Ask for a PARENT-SCOPED overrides entry when the package is also
  declared directly. npm rejects an override contradicting a direct
  dependency with EOVERRIDE, so the guidance for the mixed case would
  not have applied. The issue now prints the exact nested JSON.
- Correct the body's NOTE: severity, range, GHSA and CVE are the
  advisory's own. Only the installed versions, their paths and range
  applicability are verified against v2/main.
- Stop the new-advisory comment claiming the body marker "now covers"
  the advisory; it is posted before the edit, so that is false at
  posting time. It speaks for its own marker instead.
- Cover the successful two-field board placement, not only its failure
  modes.
- AGENTS.md: the monthly sweep NEVER boards; only the security sweep
  does, and only with a PAT. The old wording promised a card the
  monthly job cannot create.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013H6Cew3KB3jVmQ5x4Dq1sq
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-04 07:52:16 -04:00 • committed by GitHub
commit 9e516ae0a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -15,7 +15,11 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { tmpdir } from "node:os";
import {
PRIORITY_FIELD_ID,
STATUS_FIELD_ID,
buildClearedBody,
overrideAncestors,
scopedOverrideExample,
buildCommentMarker,
pickMilestone,
narrowToApplicable,
@ -467,7 +471,10 @@ test("buildIssueBody asks for BOTH edits when declared and nested copies are vul
});
assert.match(body, /Both edits are needed/);
assert.match(body, /1\. \*\*Raise the declared range/);
assert.match(body, /2\. \*\*Add an \[`overrides`\]/);
assert.match(body, /2\. \*\*Add a parent-scoped \[`overrides`\]/);
// A package-wide pin would be rejected: the manifest declares it directly.
assert.match(body, /EOVERRIDE/);
assert.match(body, /"ajv": \{\n\s+"fast-uri": "3\.1\.6"/);
// The table names the copies, so the maintainer can see why.
assert.match(
body,
@ -795,11 +802,23 @@ test("main will not update an issue whose bump differs, even for the same packag
},
],
});
inTempRepo({ "package-lock.json": lockWith("fast-uri", "3.1.5") }, () =>
withoutProjectToken(() => captureLog(() => main("o/r", spawn))),
const log = inTempRepo(
{ "package-lock.json": lockWith("fast-uri", "3.1.5") },
() =>
withoutProjectToken(() =>
captureLog(() => main("o/r", spawn, "2026-09-04")),
),
);
assert.ok(ghCall(spawn, "create"), "a different bump gets its own issue");
assert.equal(ghCall(spawn, "edit"), undefined);
// ...and the 3.1.6 issue, whose alert is no longer in the open feed, is
// cleared rather than left asserting a vulnerability nobody tracks.
const edit = ghCall(spawn, "edit");
assert.ok(edit, "the superseded issue is reconciled");
assert.match(
edit.args[edit.args.indexOf("--body") + 1],
/fixed or dismissed/,
);
assert.ok(log.some((l) => l.includes("no open alert remains")));
});
test("main comments a new advisory BEFORE rewriting the marker", () => {
@ -1116,6 +1135,166 @@ test("buildIssueBody counts the applicable alerts in its prose, not the marker",
assert.deepEqual(parseMarker(body).ghsas, ["GHSA-a", "GHSA-closed"]);
});
test("main clears an issue when its last alert is fixed or dismissed", () => {
// `openAlerts` asks for state=open, so a fixed alert simply vanishes and its
// group is never built. The issue has to be reconciled from the other side.
const [group] = groupAlerts([alert({ ghsa: "GHSA-a" })]);
const spawn = fakeSpawn({
alertPages: [[]],
issues: [
{
number: 41,
title: buildIssueTitle(group),
body: buildIssueBody(group, asInstalled()),
},
],
});
const log = inTempRepo(
{ "package-lock.json": lockWith("fast-uri", "3.1.5") },
() =>
withoutProjectToken(() =>
captureLog(() => main("o/r", spawn, "2026-09-04")),
),
);
const edit = ghCall(spawn, "edit");
assert.ok(edit, "the zero-alert run still reconciles open issues");
const body = edit.args[edit.args.indexOf("--body") + 1];
assert.match(body, /every alert it tracked has been fixed or dismissed/);
assert.deepEqual(parseMarker(body).ghsas, ["GHSA-a"]);
assert.ok(log.some((l) => l.includes("no open alert remains")));
});
test("main reconciles a vanished group even while other groups remain", () => {
// The early return is only half of it: a disappeared group is also never
// visited by the loop when the feed still has other bumps in it.
const [gone] = groupAlerts([
alert({ ghsa: "GHSA-gone", pkg: "qs", fixed: "6.16.0" }),
]);
const spawn = fakeSpawn({
alertPages: [[alert({ ghsa: "GHSA-a" })]],
issues: [
{
number: 41,
title: buildIssueTitle(gone),
body: buildIssueBody(gone, {
affected: [
{ path: "node_modules/qs", version: "6.15.3", hoisted: true },
],
declared: false,
}),
},
],
});
inTempRepo({ "package-lock.json": lockWith("fast-uri", "3.1.5") }, () =>
withoutProjectToken(() =>
captureLog(() => main("o/r", spawn, "2026-09-04")),
),
);
assert.ok(ghCall(spawn, "create"), "the live bump is still filed");
const edit = ghCall(spawn, "edit");
assert.ok(edit, "the vanished bump's issue is still cleared");
assert.equal(edit.args[2], "41");
});
test("main does not re-clear a vanished group's issue on the next run", () => {
const spawn = fakeSpawn({
alertPages: [[]],
issues: [
{
number: 41,
title:
"chore(deps): bump `fast-uri` to `3.1.6` in `package-lock.json` (1 advisory)",
body: buildClearedBody(
{
package: "fast-uri",
manifestPath: "package-lock.json",
fixedIn: "3.1.6",
},
{
ghsas: ["GHSA-a"],
reason: "every alert it tracked has been fixed or dismissed",
today: "2026-09-04",
},
),
},
],
});
inTempRepo({}, () =>
withoutProjectToken(() =>
captureLog(() => main("o/r", spawn, "2026-09-04")),
),
);
assert.equal(ghCall(spawn, "edit"), undefined);
});
test("main boards a filed issue at Todo/High using resolved option ids", () => {
// The acceptance-critical path: the two field edits that actually place the
// card. Previously only its failure modes were covered.
const spawn = fakeSpawn({ alertPages: [[alert({ ghsa: "GHSA-a" })]] });
const log = inTempRepo(
{ "package-lock.json": lockWith("fast-uri", "3.1.5") },
() => withProjectToken(() => captureLog(() => main("o/r", spawn))),
);
const add = spawn.calls.find(
(c) => c.args[0] === "project" && c.args[1] === "item-add",
);
assert.ok(add, "the card is added");
const edits = spawn.calls.filter(
(c) => c.args[0] === "project" && c.args[1] === "item-edit",
);
assert.equal(edits.length, 2, "Status and Priority are separate calls");
const optionOf = (call) =>
call.args[call.args.indexOf("--single-select-option-id") + 1];
const fieldOf = (call) => call.args[call.args.indexOf("--field-id") + 1];
assert.deepEqual(
edits.map((e) => [fieldOf(e), optionOf(e)]),
[
[STATUS_FIELD_ID, "todo-id"],
[PRIORITY_FIELD_ID, "high-id"],
],
);
// Resolved by NAME at run time, never hardcoded.
assert.ok(
spawn.calls.some(
(c) => c.args[0] === "project" && c.args[1] === "field-list",
),
);
assert.ok(log.some((l) => l.includes("boarded")));
});
test("overrideAncestors reads the parent chain, scoped names included", () => {
assert.deepEqual(
overrideAncestors("node_modules/ajv/node_modules/fast-uri"),
["ajv"],
);
assert.deepEqual(
overrideAncestors(
"node_modules/@sc/a/node_modules/b/node_modules/fast-uri",
),
["@sc/a", "b"],
);
assert.deepEqual(overrideAncestors("node_modules/fast-uri"), []);
});
test("scopedOverrideExample nests each vulnerable copy under its parents", () => {
const json = scopedOverrideExample(
[
{ path: "node_modules/fast-uri", hoisted: true },
{ path: "node_modules/ajv/node_modules/fast-uri", hoisted: false },
{ path: "node_modules/@sc/x/node_modules/fast-uri", hoisted: false },
],
{ package: "fast-uri", fixedIn: "3.1.6" },
);
// The hoisted copy is the declared one and gets no override entry.
assert.deepEqual(JSON.parse(json), {
overrides: {
ajv: { "fast-uri": "3.1.6" },
"@sc/x": { "fast-uri": "3.1.6" },
},
});
});
test("main reads every page of open dependabot issues", () => {
// The second page holds the matching marker. Truncating the lookup would
// file a duplicate issue rather than recognising this one.