lockrot 0.8.0
Added
--explain=vendor/package: one package, everything it was decided on, one call. The verdict and priority with how the package is reached; every signal with its summary and raw data (the dates the years were computed from, one line per advisory with what fixes it and where); thecomposer.lockentry; the repository metadata with the table S8 reads — every release branch, its highest tag and that tag's date, the installed branch marked, and a line saying so when that branch's highest tag is undated and S8 therefore does not measure it; the repository activity; the thresholds and target PHP; the run's notes. Text, or the same as JSON with--format=json. Exit 0 — it answers a question, it does not gate; a package not in the lock, or inpackages-devwithout--dev, is a configuration error (exit 2). See Explaining one package.left-behindsays what to require. S8 carriessuggested_constraint— the constraint that follows the upstream onto the branch fixes land on, written ascomposer requirewrites it (^8.2from 8.2.0,^0.4.3below 1.0) — and for a package the project requires itself the evidence ends…; 8.x released 8.2.0 (2026-09-06); require ^8.2 to follow. A transitive package's parent owns that line, so there the clause stays off the row and the constraint stays on the signal's data.no fix expectedsays where to go when there is somewhere. On anabandonedpackage whose repository names a replacement, an advisory nothing fixes readsno fix expected; migrate to symfony/mailer— the fix is not coming here, and the package that took over is where it lands.
Fixed
- A false
left-behindon packages split out of a monorepo. A subtree split (illuminate/*,symfony/*) cuts a tag on every release whether or not the directory changed, so tags pile up on one commit and Packagist dates each of them by that commit:illuminate/macroablehas 83 stable tags on the commit behindv10.49.0, all dated 2023-06-05, and a lock on 10.x read asbranch 10.x last released 2023-06-05 (3.3 years ago)while Laravel 10 kept releasing. A tag that shares its commit with two or more other stable tags is now read as undated — the date is the directory's, not the release's — so S8 does not measure the branch and S2 does not measure the package. Two tags on one commit keep their date: a re-tag, or a branch's last two releases cut with nothing changed between them (symfony/*3.4.46 and 3.4.47), where the date is one release interval off at most — so a Symfony 3.4 lock still readsleft-behindon every component. The cost is the other way: a split branch that really did stop and piled up more tags (illuminate/contracts8.x, 31 on one commit) is no longer reportedleft-behind, since its last tag is dated the same way. Dev branches and pre-releases on a tag's commit do not count.
Changed
- The footer's advisory line says why
composer auditcounts more. Without--devit now reads… the report does not flag; see composer audit (it counts packages-dev too, which this run skipped; pass --dev to include them): plaincomposer audittotalspackages-devand a plain lockrot run does not, and the difference should read as the scope it is.--format=jsonrecords the scope asinclude_dev. - The JSON
schemanumber stays1:include_devat the top level andsuggested_constraintin S8's data are additions, nothing removed or renamed.
Verify this release
curl -fsSL -O https://github.com/somework/lockrot/releases/download/v0.8.0/lockrot.phar
curl -fsSL -O https://github.com/somework/lockrot/releases/download/v0.8.0/lockrot.phar.sha256
sha256sum -c lockrot.phar.sha256
gpg --keyserver hkps://keys.openpgp.org --recv-keys 39ECC3F64AE8D06A9A63FD99AB6F7F52AE513141
curl -fsSL -O https://github.com/somework/lockrot/releases/download/v0.8.0/lockrot.phar.asc
gpg --verify lockrot.phar.asc lockrot.phar
gh attestation verify lockrot.phar --repo somework/lockrotOr rebuild it: check out v0.8.0, run build/build-phar.sh with Composer 2.10.3, and compare the sha256 — see the PHAR page.
Full changelog: CHANGELOG.md.