feat(repo-appearance): wire icon and color picker into repo settings
Surface the new RepositoryAppearance through the per-repo Settings UI
so users can actually pick an icon and a color. The plumbing is set up
to fan out to sidebar / shelf / canvas in the next phases — this commit
only changes the Settings tab itself.
- Parameterize TabIconPickerView with `presets`, `title`, `subtitle` so
the same picker code can serve both the tab and repo flows. Existing
callers stay unchanged thanks to defaulted parameters.
- Repository-flavored SF Symbol presets (folders / boxes / tools / web /
tech / ornament) live in `RepositoryIconPresets`, separate from the
terminal-themed tab list.
- New `RepositoryIconImage` is the single source of truth for rendering
any RepositoryIconSource — SF Symbol, bundled asset, or user PNG/SVG.
Tinting respects `isTintable` (PNG never tinted; SVG and SF Symbols
do); missing user images surface a dashed placeholder so a deleted
file is debuggable instead of invisible.
- `RepositoryAppearancePickerView` is the inline Settings section: icon
preview, "Choose Symbol…" sheet (TabIconPickerView with repo presets),
"Choose Image…" fileImporter (PNG/SVG only), "Clear Icon", and a
10-color palette plus an explicit "No color" swatch matching Finder.
- RepositorySettingsFeature now carries `appearance`, loads the entry
for `repositoryID` on `.task`, and routes mutations through explicit
actions (`setAppearanceColor`, `setAppearanceIcon`, `importUserImage`,
`resetAppearance`, `userImageImportFailed`) so the SwiftLint rule
against direct store mutation in views stays clean. Replacing or
clearing a `.userImage` icon cleans up the previous file via
`RepositoryIconAssetStore` so disk doesn't accumulate orphans.
- AppFeature passes `repository.id` so the canonical key is what hits
the @Shared dict.
Tests (RepositorySettingsAppearanceTests, 14 cases) cover persist /
clear / replace / reset paths, old-image cleanup semantics for every
icon transition, importer success and failure surfaces, and the
appearance-loaded init path. AppFeatureSettingsSelectionTests updated
to expect the new `repositoryID` field.