Replace the Delete+LoadOrStore pattern with CompareAndSwap to
atomically swap in a fresh mutex when a corrupted entry is detected.
Changes:
- Use a retry loop with CAS instead of Delete+LoadOrStore, avoiding
the race where two goroutines could create different mutexes
- Add nil check: a nil *sync.Mutex passes the type assertion but
panics on Lock() — now handled by the CAS recovery path
- Use continue-loop retry instead of unchecked second assertion
CompareAndSwap guarantees that when multiple goroutines detect a
corrupted entry, they converge on the same replacement mutex.
When os.Getwd fails, wd is empty and builtinSkillsDir resolves to relative path, causing confusing downstream errors. Fall back to config.GetHome on error.