Try reproducing failures on Windows
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/CleanArchiveIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/CleanArchiveIntegrationTest.groovy
new file mode 100644
index 0000000..7ac3f69
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/CleanArchiveIntegrationTest.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.gradle.api.tasks.bundling
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Issue
+
+@Issue("https://github.com/gradle/gradle/issues/25752")
+class CleanArchiveIntegrationTest extends AbstractIntegrationSpec {
+
+    def setup() {
+        file("contents/hello.txt") << "hello"
+        file("contents").zipTo(file("hello.zip"))
+    }
+
+    def "clean after unzipping file to cache in task"() {
+        buildFile << """
+            plugins {
+                id 'lifecycle-base'
+            }
+            System.out.println("Executing build.gradle")
+            def helloArchive = zipTree(file("hello.zip"))
+            tasks.create("makeArchive", Zip) {
+                System.out.println("Files in the archive: " + helloArchive.files)
+                archiveFileName = "archive.zip"
+                destinationDirectory = layout.buildDirectory
+                from helloArchive
+            }
+        """
+
+        expect:
+        succeeds "clean"
+    }
+
+    def "clean after unzipping file to cache during configuration phase"() {
+        buildFile << """
+            plugins {
+                id 'lifecycle-base'
+            }
+            zipTree(file("hello.zip")).files
+        """
+
+        expect:
+        succeeds "clean"
+    }
+
+    def "clean after unzipping during configuration, then unzip again in a different task"() {
+        buildFile << """
+            plugins {
+                id 'lifecycle-base'
+            }
+            System.out.println("Files in the archive: " + zipTree(file("hello.zip")).files)
+            def helloArchive = zipTree(file("hello.zip"))
+            tasks.create("makeArchive", Zip) {
+                archiveFileName = "archive.zip"
+                destinationDirectory = layout.buildDirectory
+                from helloArchive
+                doLast {
+                    System.out.println("Files in the archive: " + helloArchive.files)
+                }
+            }
+        """
+
+        expect:
+        succeeds "clean", "makeArchive"
+    }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ConcurrentArchiveIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ConcurrentArchiveIntegrationTest.groovy
index 765cb1e..6c79099 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ConcurrentArchiveIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ConcurrentArchiveIntegrationTest.groovy
@@ -146,6 +146,59 @@
         result.assertTasksExecutedAndNotSkipped(':project1:update', ':project2:update', ':project1:verify', ':project2:verify')
     }
 
+
+    @Issue("https://github.com/gradle/gradle/issues/22685")
+    def "can visit and edit zip archive differently from two different projects with the same name in different directories in a multiproject build"() {
+        given: "an archive in the root of a multiproject build"
+        createZip('test.zip') {
+            subdir1 {
+                file ('file1.txt').text = 'original text 1'
+            }
+            subdir2 {
+                file('file2.txt').text = 'original text 2'
+                file ('file3.txt').text =  'original text 3'
+            }
+        }
+        settingsFile << """include ':lib', ':utils:lib'"""
+
+        and: "where each project edits that same archive differently via a visitor"
+        file('lib/build.gradle') << """
+            ${defineUpdateTask('zip')}
+            ${defineVerifyTask('zip')}
+            def theArchive = rootProject.file('test.zip')
+            tasks.register('update', UpdateTask) {
+                archive = theArchive
+                replacementText = 'modified by project1'
+            }
+            tasks.register('verify', VerifyTask) {
+                dependsOn tasks.named('update')
+                archive = theArchive
+                beginsWith = 'modified by project1'
+            }
+        """
+
+        file('utils/lib/build.gradle') << """
+            ${defineUpdateTask('zip')}
+            ${defineVerifyTask('zip')}
+            def theArchive = rootProject.file('test.zip')
+            tasks.register('update', UpdateTask) {
+                archive = theArchive
+                replacementText = 'edited by project2'
+            }
+            tasks.register('verify', VerifyTask) {
+                dependsOn tasks.named('update')
+                archive = theArchive
+                beginsWith = 'edited by project2'
+            }
+        """
+
+        when:
+        run 'verify'
+
+        then:
+        result.assertTasksExecutedAndNotSkipped(':lib:update', ':utils:lib:update', ':lib:verify', ':utils:lib:verify')
+    }
+
     @Requires(IntegTestPreconditions.NotEmbeddedExecutor)
     @Issue("https://github.com/gradle/gradle/issues/22685")
     def "can visit and edit zip archive differently from settings script when gradle is run in two simultaneous processes"() {
@@ -469,8 +522,7 @@
                 dependsOn tasks.named('update1'), tasks.named('update2')
                 doLast {
                     def cacheDir = file("build/tmp/.cache/expanded")
-                    assert cacheDir.list().size() == 2 // There should only be 2 files here, the .lock file and the single unzipped cache entry
-                    assert cacheDir.list().contains('expanded.lock')
+                    assert cacheDir.list().size() == 1 // There should only be 1 file here, the single unzipped cache entry
                     cacheDir.eachFile(groovy.io.FileType.DIRECTORIES) { File f ->
                         assert f.name.startsWith('tar_')
                     }
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ReuseArchiveIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ReuseArchiveIntegrationTest.groovy
new file mode 100644
index 0000000..149bf2c
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ReuseArchiveIntegrationTest.groovy
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.gradle.api.tasks.bundling
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.internal.hash.DefaultFileHasher
+import org.gradle.internal.hash.DefaultStreamHasher
+import org.gradle.internal.hash.FileHasher
+
+class ReuseArchiveIntegrationTest  extends AbstractIntegrationSpec {
+
+    /*
+     * This is a pre-existing issue: What do you do if creating a cache using a pre-existing directory
+     * happens to contain content with the same name as content you're trying to cache?  The content used
+     * by the cache no longer agrees with the content coming from the zip itself.
+     */
+    def "pre-existing content in cache dir with same hash is okay"() {
+        file("contents/hello.txt") << "hello"
+        file("contents").zipTo(file("hello.zip"))
+        FileHasher hasher = new DefaultFileHasher(new DefaultStreamHasher())
+        def hash = hasher.hash(file("hello.zip"))
+        def cachedFile = file("build/tmp/.cache/expanded/zip_${hash}/hello.txt")
+        def otherFile = file("build/tmp/.cache/expanded/zip_${hash}/other.txt")
+
+        buildFile << """
+            abstract class CopyAndList extends DefaultTask {
+                @Inject
+                abstract FileSystemOperations getFileSystemOperations()
+
+                @InputFiles
+                abstract ConfigurableFileCollection getUnzipped()
+
+                @Inject
+                abstract ProjectLayout getLayout()
+
+                @TaskAction
+                void copyAndList() {
+                    getUnzipped().getFiles().each {
+                        println it.absolutePath + ": " + it.text
+                    }
+                    getFileSystemOperations().copy {
+                        from getUnzipped()
+                        into layout.buildDirectory.dir("extract")
+                    }
+                }
+            }
+            task extract2(type: CopyAndList) {
+                unzipped.from(zipTree(file("hello.zip")))
+            }
+        """
+        when:
+        succeeds("extract")
+        then:
+        file("build/extract/hello.txt").text == "hello"
+        cachedFile.assertExists()
+        otherFile.assertDoesNotExist()
+
+        when:
+        // write into the directory used by the extracted zip file
+        cachedFile.text = "some incorrect pre-existing pre-expanded content"
+        otherFile.touch()
+
+        and:
+        succeeds "extract"
+        then:
+        // the file is not extracted again and retains the modified content
+        cachedFile.text == "some incorrect pre-existing pre-expanded content"
+        otherFile.assertExists()
+        // users of the zipTree still see the zip's contents
+        file("build/extract/hello.txt").text == "hello"
+    }
+}