Skip to content

v2.12.0 ·

Every release is installed before it is published

Until now, nothing checked the package you actually install from npm until after it was on npm.

The release job ran the whole test suite against the source tree, then published. After that, one step ran npm install -g and compared aidlc --version with the tag. That was the only look at the real package. It caught nothing past a version string, and only once the release was already live.

A package can pass every test here and still break once installed. The worst case is quiet. The content package reads its skills and templates by listing a directory, so a skill file that never made it into the tarball is simply dropped. No command fails. You just get one skill fewer.

What changed

Before either package is published, the release job now runs scripts/smoke-test-packed.mjs. It packs both packages, then does three things.

It compares each tarball with git. Every tracked file under a shipped directory, skills and templates included, must be in the tarball, or the job stops and names the missing file.

It installs the two tarballs into a new git repository in a temporary directory, and checks the lockfile to make sure both packages came from the tarballs and not from the registry.

Then it runs the installed CLI the way a new user would: init, start a small task, finish its first phase with transition, check it with gate, and status. Any failure stops the job before npm publish. The old check after publishing is still there.

Why this way

The CLI is called by its full path inside the scratch install. The release machine may have a global aidlc, since the step after publishing installs one, and a check that runs a different binary than the one you changed passes no matter what.

I had planned to pin the content package with an npm override. In testing it turned out npm did not need it. Worse, it hid a real defect: a CLI pointing at a different content version would have been forced onto the packed one and passed. So the pin is gone, and the lockfile check catches that case.

What it does not do

It runs only on release, not on every commit. The run takes 9 seconds on a quiet machine and 18 under load. The tests that need the registry run only when asked, because the release job runs the real thing anyway.