Skip to content

ci: vitest 4 to clear npm audit, Node 18.18 moves to a runtime smoke job - #31

Merged
freema merged 1 commit into
mainfrom
ci/dev-deps-audit
Nov 6, 2026
Merged

freema merged 1 commit into
mainfrom
ci/dev-deps-audit

Conversation

@freema

@freema freema commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Summary

npm audit in plugins/cursor reported 15 advisories (3 critical, 6 high, 6 moderate), all in dev dependencies: vitest 2.1.9 and @vitest/coverage-v8 with tinypool, @vitest/mocker, vite, esbuild, glob and minimatch below them, plus postcss, nanoid, source-map-js, js-yaml and brace-expansion. After this PR it reports 0.

Plugin users are not affected either way: the plugin ships with zero dependencies and nobody runs npm install in the plugin cache. No runtime file, plugin.json or version changes here.

The part that needs a decision: Node 18.18 in CI

No vitest release without known advisories runs on Node 18. vitest 2.x and 3.x depend on tinypool ^1 (critical, no backport), and vitest 4 fails at startup on 18.18 because rolldown imports styleText from node:util. A clean audit and "the suite runs on Node 18.18" cannot both hold, so this PR does the following:

  • vitest and @vitest/coverage-v8 go to ^4.1.12 (the smallest step that clears the advisories; vitest 5 would also drop Node 20). Everything else is a lockfile update.
  • The test matrix runs on Node 20 and 22 (Ubuntu and macOS).
  • engines.node stays >=18.18. It describes the shipped scripts, which have no dependencies.
  • A new node-18 job keeps that floor checked without any dev dependencies: on Node 18.18 it parses every script (node --check), loads every script (which resolves all their node: imports), and runs scripts/status.mjs end to end. This is weaker than the full suite, but it catches a script that starts using an API newer than 18.18 at load time.
  • AGENTS.md, CONTRIBUTING.md and the README (FAQ and Contributing) now describe the CI as it is.

If dropping Node 18 from engines is preferred instead (it has been end-of-life since April 2025), the node-18 job can simply be removed in the release that raises the floor.

Coverage

vitest 4 remaps V8 coverage through the AST, so statements are no longer counted as lines. The unchanged suite then reads 79.7 % statements against the 80 % threshold of npm run test:coverage (CI does not run it). The thresholds stay as they are. Two small additions bring statements to 80.7 %:

  • tests/invoked.test.mjs: invokedAsScript for the module itself, through a symlink, for another entry point, with no entry point, and with a missing one.
  • tests/review-output.test.mjs: non-object top level, missing or blank summary, and each way a single finding can be malformed.

Test plan

  • npm test — all specs green (20 files, 188 passed, 4 skipped) on Node 20.19 and 22.21
  • npm run lint — prettier + eslint clean
  • npm run typecheck clean; npm run test:coverage passes its thresholds
  • npm audit: 0 vulnerabilities; npm ci works with npm 10 (Node 20 and 22)
  • Smoke-tested affected commands locally: the three node-18 steps run in node:18.18-alpine (28 modules load on 18.18.2, status.mjs exits 0)
  • Docs updated (README.md, AGENTS.md, CONTRIBUTING.md) when relevant; no CHANGELOG.md entry because nothing user-visible changes
  • New tests added (see Coverage)

Checklist

  • No new runtime dependencies (see AGENTS.md)
  • No build step, no new dist/ or .ts files
  • $ARGUMENTS is quoted in any new / edited commands/*.md (none touched)
  • New slash command (if any) follows the recipe in CONTRIBUTING.md (none)
  • User-visible behaviour change is noted under ## Unreleased in CHANGELOG.md (none)

Note on the lockfile: npm 10 crashes while resolving this bump (Cannot read properties of null (reading 'edgesOut')), so the tree was resolved with npm 11 and completed with npm 10. npm ci and a no-op npm install succeed on npm 10 with the committed file.

🤖 Generated with Claude Code

`npm audit` in plugins/cursor reported 15 advisories (3 critical, 6 high,
6 moderate), all in dev dependencies: vitest 2.1.9 and
@vitest/coverage-v8 with tinypool, @vitest/mocker, vite, esbuild, glob and
minimatch below them, plus postcss, nanoid, source-map-js, js-yaml and
brace-expansion. Users are not affected: the plugin ships with zero
dependencies and nobody runs `npm install` in the plugin cache.

No vitest release without known advisories runs on Node 18 (2.x and 3.x
depend on tinypool ^1; 4.x fails at startup because rolldown imports
`styleText` from `node:util`). So:

- vitest and @vitest/coverage-v8 go to ^4.1.12; the rest is a lockfile
  update. `npm audit` reports 0 vulnerabilities.
- The test matrix runs on Node 20 and 22. `engines.node` stays >=18.18,
  because that describes the shipped scripts, which have no dependencies.
- A new `node-18` job keeps that floor checked without dev dependencies:
  on Node 18.18 it parses and loads every script and runs
  `scripts/status.mjs`.
- vitest 4 remaps V8 coverage through the AST, so statements are no
  longer counted as lines and the same suite reads 79.7 % statements
  against the 80 % threshold of `npm run test:coverage`. The thresholds
  stay; tests for `invokedAsScript` and for the rejection paths of the
  structured review output bring it to 80.7 %.
- AGENTS.md, CONTRIBUTING.md and the README describe the CI as it is now.

No runtime file, plugin.json or version changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@freema freema left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeForge Review

Verdict: approve | Score: 9/10

Clean, well-scoped maintenance PR: bumps vitest 2→4 (clearing an npm audit advisory), narrows the main CI matrix to Node 20/22 since vitest 4 requires it, adds a lightweight Node 18.18 'runtime smoke' job (syntax-check + import every script + run one command) to keep verifying the zero-dependency plugin still works on the minimum supported Node version, and updates AGENTS.md/CONTRIBUTING.md/README.md consistently to describe the new CI shape. Also adds solid new unit tests for invokedAsScript (symlink handling, missing entry point, REPL case) and additional malformed-input coverage for parseReviewOutput. The package-lock.json changes are consistent with the vitest major bump and all resolved packages point to the official npm registry — nothing suspicious. No logic in the shipped plugin scripts is touched.


Reviewed by CodeForge

Comment thread .github/workflows/ci.yml
run:
working-directory: plugins/cursor

steps:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MINOR] The for f in scripts/*.mjs scripts/lib/*.mjs loop relies on bash glob expansion; if either directory ever had no matching .mjs files, the unexpanded literal pattern would be passed to node --check and fail with a confusing 'file not found' error rather than a clear message about the glob not matching.

Suggestion: Optional: shopt -s nullglob before the loop, or add an explicit count check, so a future empty directory fails with a clearer message. Not a blocker since both directories currently contain files.


it('rejects a missing or blank summary', () => {
// `undefined` is dropped by JSON.stringify, so the key is absent.
for (const summary of [undefined, ' ']) {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SUGGESTION] The new 'rejects a missing or blank summary' test uses { ...GOOD, summary } with summary: undefined, relying on the fact that JSON.stringify drops undefined properties (and the comment calls this out) — correct but a bit implicit/fragile if withBlock ever changes its serialization approach.

Suggestion: No action needed; the inline comment already documents the subtlety, which is sufficient.

@freema
freema merged commit e6ff7d4 into main Nov 6, 2026
6 checks passed
@freema
freema deleted the ci/dev-deps-audit branch November 6, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant