Public/Get-DocumentationDrift.ps1

function Get-DocumentationDrift {
    <#
    .SYNOPSIS
        Full pipeline orchestrator: Import -> Extract -> Verify -> Report.
    .DESCRIPTION
        Processes documentation files through the complete living documentation
        pipeline. Imports documents, extracts facts via AI, verifies against the
        live environment, and generates an HTML drift report.
    .PARAMETER DocumentPath
        Path(s) to documentation files to process.
    .PARAMETER FactsPath
        Path to the facts database JSON file. Default is .\facts.json.
    .PARAMETER OutputPath
        Directory for report output. Default is .\Reports.
    .PARAMETER Provider
        AI provider for fact extraction.
    .PARAMETER ApiKey
        API key for the AI provider.
    .PARAMETER Model
        AI model to use.
    .PARAMETER Endpoint
        Custom API endpoint URL.
    .PARAMETER ComputerName
        Additional servers to check.
    .PARAMETER SkipExtraction
        Use existing facts database; just re-verify and report.
    .EXAMPLE
        Get-DocumentationDrift -DocumentPath "C:\Docs\*.md" -Provider OpenAI -ApiKey $key
    .EXAMPLE
        Get-DocumentationDrift -DocumentPath "C:\Docs" -SkipExtraction -FactsPath .\facts.json
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position = 0)]
        [string[]]$DocumentPath,

        [Parameter()]
        [string]$FactsPath = '.\facts.json',

        [Parameter()]
        [string]$OutputPath = '.\Reports',

        [Parameter()]
        [ValidateSet('Anthropic', 'OpenAI', 'Ollama', 'Custom')]
        [string]$Provider = 'Anthropic',

        [Parameter()]
        [string]$ApiKey,

        [Parameter()]
        [string]$Model,

        [Parameter()]
        [string]$Endpoint,

        [Parameter()]
        [string[]]$ComputerName,

        [Parameter()]
        [switch]$SkipExtraction
    )

    $pipelineStart = Get-Date
    Write-Verbose "Starting Documentation Drift pipeline..."

    # Ensure output directory exists
    if (-not (Test-Path $OutputPath)) {
        New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
    }

    # Step 1: Import documentation
    Write-Verbose "Step 1: Importing documentation..."
    $documents = Import-Documentation -Path $DocumentPath

    if (-not $documents -or $documents.Count -eq 0) {
        Write-Error "No documents found at the specified path(s)."
        return
    }

    Write-Verbose " Imported $($documents.Count) document(s)."

    # Step 2: Extract facts (or skip if requested)
    if (-not $SkipExtraction) {
        Write-Verbose "Step 2: Extracting facts via AI ($Provider)..."

        foreach ($doc in $documents) {
            $extractParams = @{
                DocumentText   = $doc.Content
                SourceDocument = $doc.FileName
                Provider       = $Provider
                FactsPath      = $FactsPath
            }
            if ($ApiKey) { $extractParams['ApiKey'] = $ApiKey }
            if ($Model) { $extractParams['Model'] = $Model }
            if ($Endpoint) { $extractParams['Endpoint'] = $Endpoint }

            try {
                $extractedFacts = Extract-EnvironmentFacts @extractParams
                Write-Verbose " Extracted $($extractedFacts.Count) facts from $($doc.FileName)."
            }
            catch {
                Write-Warning " Failed to extract facts from $($doc.FileName): $($_.Exception.Message)"
            }
        }
    }
    else {
        Write-Verbose "Step 2: Skipped (using existing facts database)."
        if (-not (Test-Path $FactsPath)) {
            Write-Error "SkipExtraction specified but facts database not found at $FactsPath"
            return
        }
    }

    # Step 3: Verify facts against live environment
    Write-Verbose "Step 3: Verifying facts against live environment..."

    $verifyParams = @{
        FactsPath = $FactsPath
    }
    if ($ComputerName) { $verifyParams['ComputerName'] = $ComputerName }

    try {
        $verificationSummary = Test-EnvironmentFacts @verifyParams
        Write-Verbose " Verification complete: $($verificationSummary.Verified) verified, $($verificationSummary.Drift) drift, $($verificationSummary.Unreachable) unreachable."
    }
    catch {
        Write-Warning "Verification encountered errors: $($_.Exception.Message)"
        $verificationSummary = [PSCustomObject]@{
            TotalClaims  = 0
            Verified     = 0
            Drift        = 0
            Unreachable  = 0
            Unverifiable = 0
            Pending      = 0
        }
    }

    # Step 4: Generate HTML drift report
    Write-Verbose "Step 4: Generating drift report..."

    try {
        $factsDatabase = Get-Content -Path $FactsPath -Raw -Encoding UTF8 | ConvertFrom-Json

        $reportFileName = "drift-report-$(Get-Date -Format 'yyyyMMdd-HHmmss').html"
        $reportPath = Join-Path $OutputPath $reportFileName

        $reportFile = New-HtmlDashboard -FactsDatabase $factsDatabase -OutputPath $reportPath
        Write-Verbose " Report saved to: $reportPath"
    }
    catch {
        Write-Warning "Failed to generate HTML report: $($_.Exception.Message)"
        $reportPath = $null
    }

    $elapsed = (Get-Date) - $pipelineStart

    # Build drift summary
    $driftSummary = [PSCustomObject]@{
        DocumentsProcessed = $documents.Count
        DocumentNames       = @($documents | Select-Object -ExpandProperty FileName)
        FactsPath          = (Resolve-Path $FactsPath -ErrorAction SilentlyContinue).Path
        ReportPath         = $reportPath
        TotalClaims        = $verificationSummary.TotalClaims
        Verified           = $verificationSummary.Verified
        Drift              = $verificationSummary.Drift
        Unreachable        = $verificationSummary.Unreachable
        Unverifiable       = $verificationSummary.Unverifiable
        Duration           = $elapsed
        CompletedAt        = (Get-Date).ToString('o')
    }

    Write-Verbose "Pipeline complete in $([Math]::Round($elapsed.TotalSeconds, 1)) seconds."

    return $driftSummary
}