reencrypt only rewrote .age files; the inline 'encrypted = { KEY = "base64" }'
vars in doot.doot were left encrypted to the old recipients, so after adding a
recipient they stayed undecryptable by the new key.
Now each inline var is decrypted, re-encrypted to the current recipients, and
its ciphertext literal swapped in place in the source (textual replace, not an
AST reprint - so the file's formatting and comments are untouched, and an
indirected or non-literal ciphertext is skipped with a warning).
Verified on the real config: all 8 inline vars re-encrypted to the new
recipients and decrypt correctly.
- Add new `doot-utils` crate with `xdg` module for consistent cross-platform directory resolution
- Replace `dirs` crate usage with `doot_utils::xdg` functions in cli, core, and lang crates
- Use XDG layout on all platforms (including macOS) for config, data, cache, and state directories
- Add home_dir(), config_home(), data_home(), cache_home(), and state_home() helpers
- Update dependencies to use doot-utils workspace reference
- Remove unused dirs and related crates from Cargo.lock
- Improve error handling in template rendering and package installation
- Add InstalledCache for package managers to reduce process spawning
- Optimize brew package installation with parallel fetching and sequential installing
- Fix path canonicalization in e2e tests for consistent symlink handling
- Add clippy allowance for large parser errors in doot-lang