Private/Read-TLSnapshot.ps1

function Read-TLSnapshot {
    <#
    .SYNOPSIS
        Loads a snapshot folder into one object with a property per collected area.
    .DESCRIPTION
        Accepts either the run folder (containing 'snapshot/') or the snapshot
        folder itself. Skipped areas are not added as data properties but are
        listed in _Areas so consumers can distinguish "not collected" from
        "empty" - no silent gaps.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Path
    )

    $resolved = (Resolve-Path -Path $Path -ErrorAction Stop).Path
    $snapshotDir = $resolved
    $childSnapshot = Join-Path -Path $resolved -ChildPath 'snapshot'
    if (Test-Path -Path $childSnapshot -PathType Container) { $snapshotDir = $childSnapshot }

    $jsonFiles = @(Get-ChildItem -Path $snapshotDir -Filter '*.json' -File |
            Where-Object { $_.Name -ne 'manifest.json' })
    if ($jsonFiles.Count -eq 0) {
        throw "No snapshot area files found in '$snapshotDir'."
    }

    $areas = [ordered]@{}
    $data = [ordered]@{}
    foreach ($file in ($jsonFiles | Sort-Object -Property Name)) {
        $document = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json
        if ($null -eq $document -or -not $document.PSObject.Properties['area']) {
            Write-Warning ("Snapshot file '{0}' has no area header - ignored." -f $file.Name)
            continue
        }
        $areaName = [string]$document.area
        $skipped = $false
        if ($document.PSObject.Properties['skipped']) { $skipped = [bool]$document.skipped }
        $areas[$areaName] = [pscustomobject]@{
            Skipped    = $skipped
            SkipReason = $(if ($document.PSObject.Properties['skipReason']) { $document.skipReason } else { $null })
            Errors     = $(if ($document.PSObject.Properties['errors']) { @($document.errors) } else { @() })
            File       = $file.Name
        }
        if (-not $skipped) { $data[$areaName] = $document.data }
    }

    $manifest = $null
    $manifestPath = Join-Path -Path $snapshotDir -ChildPath 'manifest.json'
    if (Test-Path -Path $manifestPath) {
        $manifest = Get-Content -Path $manifestPath -Raw | ConvertFrom-Json
    }

    $snapshot = [pscustomobject]$data
    Add-Member -InputObject $snapshot -NotePropertyName '_Areas' -NotePropertyValue ([pscustomobject]$areas)
    Add-Member -InputObject $snapshot -NotePropertyName '_Manifest' -NotePropertyValue $manifest
    Add-Member -InputObject $snapshot -NotePropertyName '_Path' -NotePropertyValue $snapshotDir
    return $snapshot
}