Private/Invoke-KadenIntegrationMigration.ps1

function Invoke-KadenIntegrationMigration {
    <#
    .SYNOPSIS
        Migrate recognized old Kaden-managed artifact names without destroying consumer content.
    .DESCRIPTION
        Evaluates each required rename. Old-only managed content moves to the new name.
        Both-present or unproven destinations are left unchanged and reported as collisions.
        Already-migrated and new-only states report no remaining migration work.
        Unproven Kaden-named destinations are returned as protected skip paths for managed apply.
        Caller must hold the child update lock before invoking this function.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)][string]$ChildRoot,
        [Parameter(Mandatory = $true)]$Manifest
    )

    $results = New-Object System.Collections.Generic.List[object]
    $protected = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
    $expectedByDestination = @{}
    foreach ($entry in @($Manifest.files)) {
        $key = ConvertTo-KadenNormalizedManifestPath -RelativePath ([string]$entry.destination)
        $expectedByDestination[$key] = [string]$entry.digest
    }

    foreach ($pair in @(Get-KadenIntegrationRenameMap)) {
        $oldRel = [string]$pair.OldName
        $newRel = [string]$pair.NewName
        $newKey = ConvertTo-KadenNormalizedManifestPath -RelativePath $newRel
        $expectedDigest = $null
        if ($expectedByDestination.ContainsKey($newKey)) {
            $expectedDigest = [string]$expectedByDestination[$newKey]
        }

        $state = Resolve-KadenIntegrationPairState -ChildRoot $ChildRoot -OldRel $oldRel `
            -NewRel $newRel -ExpectedDigest $expectedDigest
        if ($state.ProtectNew) {
            [void]$protected.Add($newRel)
        }
        if ($null -ne $state.Result) {
            $results.Add($state.Result)
        }
    }

    $remaining = 0
    foreach ($row in $results) {
        if ([string]$row.Outcome -eq 'collision') {
            $remaining++
        }
    }
    $protectedArray = New-Object string[] $protected.Count
    $protected.CopyTo($protectedArray)

    return [pscustomobject]@{
        Results               = $results.ToArray()
        ProtectedDestinations = $protectedArray
        MigrationRemaining    = $remaining
    }
}