Private/New-KadenManagedApplyPlan.ps1

function New-KadenManagedApplyPlan {
    <#
    .SYNOPSIS
        Build the journaled managed-file apply plan, honoring skip destinations and delimited instruction paths.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Private planner stages payload bytes under an already-confirmed update transaction; ShouldProcess is owned by Initialize-KadenRepo / Update-KadenRepo.')]
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]$Manifest,
        [Parameter(Mandatory = $true)][string]$PayloadRoot,
        [Parameter(Mandatory = $true)][string]$StagingRoot,
        [Parameter(Mandatory = $false)][string[]]$SkipDestinations = @()
    )

    $skipSet = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
    foreach ($skip in @($SkipDestinations)) {
        if (-not [string]::IsNullOrWhiteSpace($skip)) {
            [void]$skipSet.Add((ConvertTo-KadenNormalizedManifestPath -RelativePath $skip))
        }
    }

    $operations = @()
    foreach ($entry in @($Manifest.files)) {
        $destRel = [string]$entry.destination
        if (Test-KadenDelimitedInstructionDestination -Destination $destRel) {
            continue
        }
        $destKey = ConvertTo-KadenNormalizedManifestPath -RelativePath $destRel
        if ($skipSet.Contains($destKey)) {
            continue
        }
        $sourceRel = [string]$entry.source
        $expected = [string]$entry.digest
        $sourcePath = Resolve-KadenContainedPath -Root $PayloadRoot -RelativePath $sourceRel
        $stagedPath = Join-Path $StagingRoot ($destRel -replace '[\\/]', '__')
        Copy-Item -LiteralPath $sourcePath -Destination $stagedPath -Force

        $operations += [pscustomobject]@{
            destination         = $destRel
            expectedDigest      = $expected
            previousDigest      = $null
            backupPath          = $null
            stagedPath          = $stagedPath
            intentStatus        = 'planned'
            backupStatus        = 'pending'
            replacementStatus   = 'pending'
            verificationStatus  = 'pending'
        }
    }

    return $operations
}