The problem is that PrepareInnerClone always runs but other steps that mutate the source have "complete" semaphones (e.g. ApplyPatches and UpdateGlobalJsonVersions). This means if you are iterating on a build failure, subsequent builds will re-clone the source, but not re-apply patches which then fail the build. To workaround this you need to either clean the entire repo or delete the appropriate semaphores.