0.8.0
Released 2026-09-09
Added
--link-mode clone: reflink (LinuxFICLONE, macOSclonefile) intovendor/, falling back to hardlink then copy where the filesystem doesn't support it (#19)viv init: write a composer.json for a new project, no prompts (#143)viv new/viv create-project: start a project in a directory that doesn't exist yet, empty or from a package skeleton (#139)update,addandrmblock versions covered by a security advisory, and abandoned packages when configured, as Composer does by default;--no-blockingandconfig.audit.*turn it off (#175)update,addandrmprint Composer's lock file operations: what changed, old version to new (#156)- Composer-type repositories with a
file://URL, such as a local Satis build (#161) viv diagnose --adapters(hidden) lists every native adapter and the upstream version it ports; a weekly workflow opens an issue when one falls behind (#127)
Changed
viv add/viv rmare now the documented commands;require/removeremain aliasesviv add/viv rmalways normalizecomposer.jsonafter editing it;--no-normalizeis now a deprecated no-op, same asinstall/dump-autoload(#145)viv updateno longer normalizescomposer.json; only commands that edit it (add,rm,init) do.--no-normalizeonupdateis now a deprecated no-opadd,rmandinitkeepcomposer.json's existing indentation, tabs included, instead of forcing four spaces (#163)- Native plugin adapters sit behind one
Adaptertrait;installnever names an adapter, and adapter tests run as their own CI job (#127)
Fixed
updatefailed on a project whose second repository redirects (asset-packagist.org): metadata requests now follow redirects (#174)updatefailed where a root constraint is met only by a branch alias underminimum-stability: dev, such as yiisoft/yii2 on yii2-app-basic; the second, require-only solve dropped every alias (#172)add,rmandinitresolved against Packagist alone and ignored--offline; they now use the project'srepositoriesand stay offline when asked (#158, #160)- The lock's
content-hashwas computed beforecomposer.jsonwas normalised, so a freshaddleft the lock stale (#155) - A metapackage with no dist and no source (shopware/conflicts) failed to install (#149)
- The phpstan/extension-installer adapter wrote a different
PHPSTAN_VERSION_CONSTRAINTfrom the real plugin when constraints intersect (#153) viv runno longer warns aboutComposer\Config::disableProcessTimeout, and prints skip notices as plain warnings (#154)
Performance
- Install hot path:
composer.jsonparsed once, no deep clone before the no-op check; Laravel no-op 5.4 to 4.7 ms (#122) - Store extraction opens each file once (#146)
- Profiled the warm update: on Laravel offline, JSON parsing is 53 percent and pool teardown 25 percent; follow-ups filed (#159)
- README speed table is now ten corpus projects, three tools, from a local mirror with no network measured (#141)
Tooling
- Bench: local mirror mode so cold and update scenarios contain no network;
update-offlinescenario; Laravel joins monolog in the CI gate; the gate compares viv to Composer on the same runner (#164, #165, #171, #173) - Compat sweep skips a failed clone instead of aborting (#148)
- Fuzz targets build again and CI builds them on every push (#147)
- Removed the JsonManipulator port and the unreachable impossible-packages optimiser pass (#144, #145)