Pass-2 candidate 5: unify the key=value config codec into loot-cli::kv
ferry::parse_kv and workspace::parse_config_text were byte-for-byte identical
(trim, skip #/blank, split_once('=') → BTreeMap), and three call sites
hand-rolled the matching `{k} = {v}\n` encode (ferry::write_kv, Config::save,
GlobalConfig::save). One `kv::{parse, encode}` module now owns the dialect;
ferry (git_config / git_identity_map spine files), the per-repo .loot/config,
and the global config all call it. Behaviour-preserving; the module carries its
own round-trip/comment-skip/ordering tests (4). loot-cli lib suite green (227,
+4 kv).
This is the non-blocked core of pass-1's candidate 6 — pure text, no WipState →
loot-cli-ledger cross-crate coupling. 9b171a5c · dbf3dbe6…
Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.