Rebase fixup for the writable-copy fix. #72622 landed an early-exit on
`origin_hash == bundled_hash` after this branch was written, which returns
before either migration sweep and left the pre-existing-install case
unrepaired — the branch's own
test_preexisting_hash_identical_readonly_copy_is_repaired failed on
current main.
That fast path deliberately skips hashing the user's copy, so it is
exactly the branch a pre-fix install lands on every sync. Sweep there too,
gated on the skill root's own mode via `_is_owner_writable` so the
steady-state path stays O(1): copytree propagates source modes to
directories, so an unrepaired copy always has a read-only root and a
repaired one never re-walks. #72622 removed recursive I/O from this branch
on purpose and sync_skills runs at CLI startup — measured on a real
67-skill install, an ungated sweep cost ~11ms per startup to repair
nothing; gated it is ~3.6ms and only walks a tree that needs it.
Also drops two stray asserts left in test_clone_config_copies_files by the
rebase conflict resolution (they referenced a `model.provider` config
shape this test never sets up).
Verified against the real /nix/store bundled skills tree:
fresh sync -r--r--r-- -> -rw-r--r--, 0 non-writable, patch OK
migration -r--r--r-- -> -rw-r--r-- with copied=0 updated=0, patch OK