private/Resolve-TaskDependencies.ps1

function Resolve-TaskDependencies {
    <#
    .SYNOPSIS
    Performs a depth-first topological sort with cycle detection for a single task.

    .DESCRIPTION
    Recursively walks the dependency graph from the given task key, appending
    each task to $Order in post-order (dependencies before dependents).
    Detected validation errors are written to the pipeline.

    .OUTPUTS
    [string] Validation error messages, if any.
    #>

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

        [Parameter(Mandatory = $true)]
        [hashtable]$TaskMap,

        [Parameter(Mandatory = $true)]
        [hashtable]$Aliases,

        [Parameter(Mandatory = $False)]
        [hashtable]$InStack = @{},

        [Parameter(Mandatory = $False)]
        [hashtable]$Visited = @{},

        [Parameter(Mandatory = $False)]
        [System.Collections.Generic.List[string]]
        $Order = [System.Collections.Generic.List[string]]::new()
    )
    begin {
        Write-Debug "Resolving dependencies for task(s): $($TaskKey -join ', ')"
        Write-Debug "Current stack: $($InStack.Keys -join ' -> ')"
        $ValidationErrors = @()
    }
    process {
        foreach ($key in $TaskKey) {
            if ($InStack.ContainsKey($key)) {
                $ValidationErrors += "Circular reference found for task '$key'."
                return
            }
            if ($Visited.ContainsKey($key)) {
                return
            }
            Write-Debug "Visited tasks: $($Visited.Keys -join ', ')"


            $InStack[$key] = $true

            $task = $TaskMap[$key]
            if ($null -eq $task) {
                $ValidationErrors += "Task '$key' does not exist."
                $InStack.Remove($key)
                return
            }

            foreach ($dep in $task.DependsOn) {
                $depKey = $dep.ToLower()
                # Resolve alias
                if ($Aliases.ContainsKey($depKey)) {
                    $depKey = $Aliases[$depKey].Name.ToLower()
                }
                if (-not $TaskMap.ContainsKey($depKey)) {
                    $ValidationErrors += "Task '$dep' (dependency of '$key') does not exist."
                    continue
                }
                $resolved = Resolve-TaskDependencies -TaskKey $depKey -TaskMap $TaskMap -Aliases $Aliases -InStack $InStack -Visited $Visited -Order $Order
                $ValidationErrors += $resolved.ValidationErrors
            }

            $InStack.Remove($key)
            $Visited[$key] = $true
            $Order.Add($key)
        }
    }

    end {
        Write-Debug "Finished resolving dependencies for task(s): $($TaskKey -join ', ')"
        return @{
            'Order'            = $Order
            'Visited'          = $Visited
            'InStack'          = $InStack
            'ValidationErrors' = $ValidationErrors
        }
    }
}