releases

Remixware Now Reads pnpm, Yarn and uv Lockfiles and Runs as a GitHub Action

The dependency gate in 0.3 read package-lock.json, go.mod, requirements files and poetry.lock. If your project used pnpm, Yarn or uv, a change to its lockfile came out as not-checked. That fails by default, which is safe and also useless: you can’t run a gate that fails every pull request.

Remixware 0.4 reads pnpm-lock.yaml (lockfile versions 5, 6 and 9), yarn.lock from Yarn 1 and from Yarn 2 and later, and uv.lock. Their packages go through the same checks as the others. A new package nobody allowed fails. So does an install script the lockfile records, and an update that moves a package off the public registry.

It also ships a GitHub Action. One step runs check or deps, puts each problem on the pull request as an annotation, and writes a summary on the run’s page:

The job summary for vite’s move to Oxlint: Remixware deps FAIL, 27 new packages not on the allow list, all in pnpm-lock.yaml.

Four Real Changes

We ran the released 0.4.0 on one recent commit from each of four projects that use these formats. All runs were offline.

  • vite, pnpm 9. The commit that moved vite from ESLint to Oxlint added two direct packages, oxlint and oxlint-tsgolint, and 25 prebuilt binaries for different platforms. That makes 27 new packages, and 40 packages of the old ESLint setup are gone. An example allow list with four rules (the two tools, and a wildcard for each binary family) lets the change pass.
  • Babel, Yarn 4. A security update of glob to version 14 updated four packages and brought in one new one, @isaacs/nonrecursive-glob-match. A one-line bump in a security fix still adds a package someone should look at.
  • React, Yarn 1. React keeps 48 lockfiles in its repository: 46 yarn.lock files, a package-lock.json and a Rust Cargo.lock. All 47 JavaScript lockfiles were read. The Cargo one is a format Remixware doesn’t read, and the change didn’t touch it. The commit that added Chrome DevTools coverage brought in chrome-devtools-mcp.
  • pydantic-ai, uv. Adding a sandbox brought in boxd as a direct dependency. It ships a wheel, so the install-script check ran from the lockfile alone and found nothing to build from source.

The commands, outputs and JSON are in test/results/case-studies/deps.

The Action

on: pull_request
permissions:
  contents: read
jobs:
  deps:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: softdevstudio/[email protected]
        with:
          command: deps

On a pull request it compares with the base branch, fetching it if the checkout doesn’t have it. It uses the base branch’s policy, so a pull request can’t allow its own packages. The action downloads the release for the runner and checks it against the release’s SHA256SUMS before running it. The flags behind it, --format github and --summary, work in any workflow without the action.

What the Review Found

An independent review went through the new readers before release, and then through the fixes. It found 20 problems. Most were ways a lockfile could make a package look like something else. pnpm names a package by its key, but the reader took a name field instead. Yarn fetches the version in resolution, but the reader trusted the version field. A tarball on the registry’s host but for a different package counted as the named package from the registry. Another kind of problem: text in a policy file could print a line that GitHub’s runner reads as a workflow command. Every one has a test that failed before the fix.

The readers are strict on purpose. YAML anchors, tabs, keys given twice or content the format doesn’t have stop the command instead of being skipped. The promise test runs generated changes through all ten formats. 800 new unallowed packages failed, 1,600 unchanged or allowed sets passed, 240 new install scripts failed, and 800 broken lockfiles stopped with an error. While we were writing it, it found a stray line in a TOML array that was being read as a value.

There’s one exception to stopping. vite keeps two-line yarn.lock files as test fixtures, and they aren’t real lockfiles. A lockfile that can’t be read on either side, and that the change leaves byte for byte as it is, is now skipped with a warning. Its packages count on neither side, which can only make more packages look new, never fewer.

Limits

pnpm 9 and Yarn don’t record install scripts in their lockfiles, so for them that check needs --online. Yarn 1 reads direct dependencies from the root package.json only. In a Yarn 1 workspace, a package one of the workspaces asks for shows as transitive, which is how chrome-devtools-mcp shows in the React run. It still fails the allow list either way.

Download 0.4.0, and see the reference for every format’s rules. The 0.3 post explains the gate itself.