Reference
The rules
Ten checks over one question: do the places this project declares a toolchain version agree with each other? Each rule names the sources it compares and carries a fixed code.
What a run reads
lockstep scans a single project directory. Every source below is optional; a missing file is skipped, not an error. Nothing is written back to the project.
package.json—engines.node,engines.bun,packageManager, andvolta..nvmrcand.node-version— the Node version each manager would install..tool-versionsandmise.toml— the asdf and mise pins.- The committed lockfile —
package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lock, orbun.lockb. - Every
.github/workflows/*.yml—setup-node,setup-bun,pnpm/action-setup, corepack, and whether the install is frozen.
The ten rules
| Code | Severity | Check |
|---|---|---|
LOCK-001 | error | Conflicting Node versions across sources |
LOCK-002 | error | packageManager conflicts with the committed lockfile |
LOCK-003 | error | Multiple lockfiles from different managers |
LOCK-004 | warning | Lockfile committed but CI does not install frozen |
LOCK-005 | warning | No lockfile committed |
LOCK-006 | warning | packageManager declared but CI never enables corepack |
LOCK-007 | info | engines.node range does not include the CI-pinned Node |
LOCK-008 | info | .nvmrc and .node-version differ only cosmetically |
LOCK-009 | warning | CI bun-version major disagrees with engines.bun |
LOCK-010 | info | No GitHub Actions workflow found so CI cannot be verified |
How the checks behave
LOCK-001 — conflicting Node versions
Every Node declaration is reduced to its major, and the majors must be a single value. Two sources claiming Node 18 and Node 20 is an error; a range such as >=18 is compared by the major it names.
LOCK-002 — packageManager versus the lockfile
The manager named in packageManager must own the committed lockfile. Declaring pnpm while committing a package-lock.json is an error, because the next contributor will install with a different manager than the one the project pins.
LOCK-003 — multiple lockfiles
More than one manager's lockfile in the tree is an error. Two lockfiles mean two resolution graphs, and whichever a tool happens to pick silently wins.
LOCK-004 — frozen installs
A committed lockfile is only authoritative if CI installs from it without rewriting it. When a lockfile exists and a workflow does not use npm ci, --frozen-lockfile, or --immutable, lockstep warns.
LOCK-005 — no lockfile
With no lockfile committed, dependency resolution is not pinned at all. This warns rather than errors, because some libraries intentionally ship without one.
LOCK-006 — corepack never enabled
A packageManager field does nothing unless a workflow activates it. lockstep warns when the field is present but no workflow enables Corepack or pins the same package-manager version through an action.
LOCK-007 — engines versus CI
When engines.node is a simple range, its major should include the Node version CI pins. A range that excludes the CI runtime is informational, because the two can drift without the build failing outright.
LOCK-008 — cosmetic difference
.nvmrc and .node-version that differ only by a v prefix or trailing whitespace still resolve to the same version. lockstep reports it so the two files can be made identical.
LOCK-009 — Bun version
When engines.bun and a workflow's bun-version disagree by major, lockstep warns. The same drift that applies to Node applies to Bun.
LOCK-010 — CI cannot be verified
With no .github/workflows/*.yml, lockstep cannot confirm how the project installs or which runtime it uses. It reports that as informational, so a green result is never mistaken for a verified one.
How a run is assembled
The pipeline is static. There is no rendering step and no network access.
-
Scan
Read
package.json, the version files, the lockfiles, and the workflow directory, collecting each version declaration with the file it came from. -
Normalize
Reduce each value to a comparable form: a major for runtimes, a manager name for lockfiles, and a pinned version for actions.
-
Compare
Run the ten rule functions over the collected facts. Each emits an issue with a code, a severity, a location, and a message.
-
Report
Print text or JSON, optionally write SARIF 2.1.0, and exit
0,1,2, or3for CI.