Prebuild plugin runs fine as one command, errors when split into 2

I'm messing around with prebuild plugins and I've written one that works when it is one command but fails when it is two.

It saves an arbitrary .zip file into the context.pluginWorkDirectory before every build, but thins them out so there are only 5 at a time. It does this via a single shell command (see below), not a local executable. This isn't a really good place for archives, I get that. It was more of a proof of concept test.

When I separate the placing of the new archive file and the removing of stale files into two .prebuildCommand()s, immediately there are Skipping duplicate build file in Copy Bundle Resources build phase warnings that one doesn't get with the first command. When the first delete happens the copying of that deleted resource fails and the build terminates with an error. This is on MacOS 14.1.2

Sooo... why does the build system not care about the zip files hanging out as unhandled resources in version 1 and in version 2 it very much does treat them as resources and is unhappy? In the second version the two commands run one right after the other in the prebuild. Why the different behavior down in the build?

I feel like version 1 is maybe getting away with something and version 2 is an indication that resources that go into that folder need to be handled explicitly? I'm having trouble figuring out how.

In the example WWDC 2022 Create Swift Package Plugins 20:45 those resources also go into the pluginWorkDirectory, put there by a call to xcrun which might be doing something fancier.

Let's say these were a type of resource that did belong in a build. What would be the right way to handle a put-and-cull of a resources? But more importantly why is there a difference in behavior between these two?

Note: Second command could be ANY second command. Doesn't have to be one that touches the files. The warnings and errors show up by running echo as well.

Version 1

WORKS, can run as many times as I want. Folder only ever has a max 5 items.

struct MyPreBuildPlugin:BuildToolPlugin {
    func createBuildCommands(context: PackagePlugin.PluginContext, target: PackagePlugin.Target) async throws -> [PackagePlugin.Command] {
        let outputDir = context.pluginWorkDirectory//.appending(["snapshot.zip"])
        let folder = target.directory.lastComponent
        let zipNCleanCommand = "cd \(target.directory.removingLastComponent().string) && zip -r \(outputDir)/snapshot_$(date +'%Y-%m-%dT%H-%M-%S').zip \(folder) && cd - && cd \(outputDir) && ls -1t | tail -n +6 | xargs rm -f"
        print("print from plugin.swift:", outputDir)
        var result:[PackagePlugin.Command] =  [.prebuildCommand(
            displayName: "------------ MyPreBuildPlugin ------------",
            executable: .init("/bin/zsh"), //also Path("/usr/bin/zip")
            arguments: ["-c", zipNCleanCommand],
            outputFilesDirectory: outputDir)
        ]
        
        return result
    }

Version 2

BAD: Creates warning about copying duplicate resources immediately. Fails after files have been deleted.

import PackagePlugin
import Foundation

@main
struct MyPreBuildPlugin:BuildToolPlugin {
    func createBuildCommands(context: PackagePlugin.PluginContext, target: PackagePlugin.Target) async throws -> [PackagePlugin.Command] {
        let outputDir = context.pluginWorkDirectory//.appending(["snapshot.zip"])
        let folder = target.directory.lastComponent
        let zipCommand = "cd \(target.directory.removingLastComponent().string) && zip -r \(outputDir)/snapshot_$(date +'%Y-%m-%dT%H-%M-%S').zip \(folder)"
        print("print from plugin.swift:", outputDir)
        var result:[PackagePlugin.Command] =  [.prebuildCommand(
            displayName: "------------ MyPreBuildPlugin ------------",
            executable: .init("/bin/zsh"), //also Path("/usr/bin/zip")
            arguments: ["-c", zipCommand],
            outputFilesDirectory: outputDir)
        ]
        
        //works, but problematic b/c running it creates copy resources warnings & errors e.g.
        //WARNING: Skipping duplicate build file in Copy Bundle Resources build phase: $FILENAME
        //FAILURE: CpResource... error: $FILENAME: No such file or directory (in target 'PluginExplorer_plugin-tester' from project 'PluginExplorer')
        result.append(removeExcessFiles(directory: outputDir))

        return result
    }
    
    //WARNING: file names can't have spaces.
    func removeExcessFiles(directory:Path) -> PackagePlugin.Command {
        let removeCommand = "cd \(directory.string) && ls -1t | tail -n +6 | xargs rm -f"
        return .prebuildCommand(displayName: "Remove Stalest",
                         executable: .init("/bin/zsh"),
                         arguments: ["-c", removeCommand],
                         outputFilesDirectory: directory
        )
    }
}

Repo

Build Logs

Available on request. The second obviously has two /usr/bin/sandbox-exec -p blocks instead of one, but they run one right after each other in the prebuild, so I'm having trouble seeing something that causes the trouble in the second but not the first.

Other Approaches

For what its worth I did try using the FileManager to determine which files to delete but it seemed like the command was not rebuilding and holding on to stale information.

func removeFile(directory:Path, file:String) -> PackagePlugin.Command {
    .prebuildCommand(displayName: "Remove Stalest",
                     executable: .init("/bin/rm"),
                     arguments: [directory.appending([file]).string],
                     outputFilesDirectory: directory
    )
}