0.15.0

Released 2026-09-23

Added

  • viv lock convert translates an existing composer.lock into chapter 1's viv.lock without re-solving (#273)
  • viv lock merge is a git merge driver for composer.lock/viv.lock: it merges the three inputs by name-keyed package record instead of by text line. --no-resolve skips the divergent-name re-solve, --as-of pins that re-solve's registry view to an RFC 3339 timestamp (#275)
  • viv update --lock native solves normally and, alongside the unchanged composer.lock, writes viv.lock in chapter 1's research format (#272)
  • viv workspace list discovers a repository's extra.viv.workspace members and reports each one's name, version, path and inter-member requirements (#276)
  • package repositories: packages declared inline in composer.json rather than fetched from a registry (#294)
  • viv lock merge re-solves what diverged in three rungs, the divergent closure, then pinned packages that directly require it, then a full solve that prefers every locked version; --max-scope caps it and the report names the rung and every package that moved (#296). viv.lock inputs re-solve the same way, taking the pinned set's requires from the sibling composer.lock (#295)
  • viv install reads viv.lock beside composer.lock when present and refuses if the two disagree in either direction; viv update implies --lock native once viv.lock exists (#297)
  • viv install on a lock left with git conflict markers names the file, the first marker's line and the packages in conflict (#274); inside a git checkout mid-merge it resolves the conflict itself from the index stages, the same way the merge driver would, and continues (#299)
  • viv init writes composer.lock merge=viv and viv.lock merge=viv to .gitattributes; viv install sets merge.viv.driver in any clone whose .gitattributes names it, so git merges locks through viv without a manual step (#298)
  • make bench-ab BEFORE=<bin> AFTER=<bin> grades a pull request's own binary against main's, viv against itself, as a pre-merge gate; make bench-check now runs on bench/laravel and make bench-smoke covers the runner-sized monolog fixture CI actually gates on (#293)

Fixed

  • A git subprocess viv spawns (clone, checkout) no longer inherits the caller's own repository as its working directory (#289)
  • A private GitHub package keeps its SSH source.url instead of falling back to the API's HTTPS one (#282, #283)