feat(installer): back up what a run is about to overwrite #11
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/backup-before-overwrite"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
PLAN.md §5.3 (scope decision in docs#96). Before anything is written, every file this run will replace is copied into
<state>/backups/<utc-stamp>/beside amanifest.jsonnaming where each came from.--no-backupopts out;--verifytakes none.Scoped by what cannot be fetched again
The sidecar binary and the overlay files are re-downloadable and hash-named in the bundle. The database is a cache with a schema —
link/sidecar/src/store.rscreates every tableIF NOT EXISTS, and every one holds shard state the sweeps repopulate. Copying those would be bulk with no recovery value, and the bulk is not free: it would bury the two things that matter.What a run can destroy for good is short:
.csfile. Phase 1 overwrites those unconditionally and by design (Bridge.cfgis the one exception) — so the one place this tool knowingly discards work is the one place it should keep a copy first.sidecar.toml, whose token the website already holds.Two deviations from §5.3 as written, both found by building it
update, or aninstallover an existing record". §5.3 justified the latter with "a first install overwrites nothing" — which is not true of a tree deployed by hand per INSTALL.md Appendix A2, a path this project documents and recommends while the binary is unreleased. There, a firstinstallfinds.csfiles that differ, plans them asChange, and overwrites them with no record anywhere of what was there. The direct test covers that and still writes nothing for a genuine first install, because there is nothing to copy. docs#96 is updated to match.sidecar.tomljoins a backup that is already being taken and is never the reason for one. Nothing in the installer rewrites it, so making it a trigger would leave a dated directory after every no-opupdate— the same failure as an empty backup, one step along. It is copied so a restored set of files arrives with the token that matches them.Details that are load-bearing
list/pruneconsider only those — so a run interrupted mid-copy can neither be mistaken for a backup nor evict a good one by being newer. It is left on disk for a human rather than silently deleted.KEEP). An unbounded directory of ServUO source copies on a shard host is its own support problem.uninstallkeeps them and lists them in the report — the durable artifact, since by the time it is read the run that took the backup is long out of the scrollback.--purgeremoves them, alongside the config, the database and the cached patch set. Same rule, same reason: they are the only offline record of what was here before.doctorreports the newest, always✓: having no backup is correct on a host that has never overwritten anything..csback over a newer overlay eats work rather than saving it.How it was tested
fmt,clippy -D warningsand 144 tests on both Linux (Docker) and the Windows host. Then live, against two scratch ServUO trees built from the real 57.4 files:backups/directory created at allupdateafter editing a deployed.cssidecar.tomlupdate--no-backupwith an edit present--verifywith an edit presentdoctor✓ Backups 2026-08-05T10:44:46Z — 2 file(s) replaced by update to bundle 2026.08.04uninstalluninstall --purgeinstall --patchesLogging.cscaptured (diff confirms the backup has noOnWritehook, the tree does); the two rung-0 patches wrote nothing and correctly captured nothingChecklist
AI-assisted contributions (required)
Claude Code (Opus 5). I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with aCo-Authored-Bytrailer.License