Managed items with local modifications were kept (skip + warn) with no
escape hatch other than deleting the deployed file by hand — after an
upstream change the deployed content silently stayed old, which reads
exactly like a stale cache.
--force turns the two skip cases into update (repository version wins)
and remove (upstream deleted + modified). Unmanaged items and never-
managed path occupancies stay untouched even with --force; the default
behavior is unchanged.
- Plan is a pure function (inventory, manifest, disk facts, injected path
mapping) emitting exactly six actions: deploy, update, skip+warn,
leave+warn, remove, keep — deterministic order, no filesystem access
- full 3x3 matrix (disk unmodified/user-modified/never-managed x upstream
added/changed/removed) table-tested plus missing-disk restore cases,
a mixed fixture and a purity/determinism guarantee test
- executor applies plans item by item (atomic deploy/remove per item),
rewrites the manifest once, appends timestamped SKIP/LEAVE lines with
item name and reason to the sync log
- sync now plans before mutating: unmanaged occupants block new deploys,
upstream deletions remove only unmodified copies, local modifications
always win and are warned about