Public/Update-Documentation.ps1

function Update-Documentation {
    <#
    .SYNOPSIS
        Sends drift results to AI to generate a corrected version of the original document.
    .DESCRIPTION
        Reads the original document and verified facts with drift data, then uses an AI
        to rewrite the document with corrections. Optionally highlights changes with
        [UPDATED] and [UNVERIFIED] tags.
    .PARAMETER DocumentPath
        Path to the original document.
    .PARAMETER FactsPath
        Path to the verified facts.json database.
    .PARAMETER OutputPath
        Directory to save the corrected document. Default is .\Updated.
    .PARAMETER Format
        Output format. Default is Markdown.
    .PARAMETER Provider
        AI provider to use.
    .PARAMETER ApiKey
        API key for the provider.
    .PARAMETER Model
        AI model to use.
    .PARAMETER Endpoint
        Custom API endpoint URL.
    .PARAMETER HighlightChanges
        Mark corrections with [UPDATED] and [UNVERIFIED] tags.
    .EXAMPLE
        Update-Documentation -DocumentPath ".\docs\overview.md" -FactsPath .\facts.json -HighlightChanges
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position = 0)]
        [ValidateScript({ Test-Path $_ })]
        [string]$DocumentPath,

        [Parameter(Mandatory, Position = 1)]
        [ValidateScript({ Test-Path $_ })]
        [string]$FactsPath,

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

        [Parameter()]
        [ValidateSet('Markdown', 'HTML')]
        [string]$Format = 'Markdown',

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

        [Parameter()]
        [string]$ApiKey,

        [Parameter()]
        [string]$Model,

        [Parameter()]
        [string]$Endpoint,

        [Parameter()]
        [switch]$HighlightChanges
    )

    # Read original document
    Write-Verbose "Reading original document: $DocumentPath"
    $docItem = Get-Item $DocumentPath
    $originalText = ''

    switch ($docItem.Extension.ToLower()) {
        '.docx' {
            $originalText = Read-WordDocument -Path $docItem.FullName
        }
        '.xlsx' {
            $originalText = Read-ExcelDocument -Path $docItem.FullName
        }
        default {
            $originalText = Get-Content -Path $docItem.FullName -Raw -Encoding UTF8
        }
    }

    if ([string]::IsNullOrWhiteSpace($originalText)) {
        Write-Error "Original document is empty or could not be read."
        return
    }

    # Read facts database
    Write-Verbose "Reading facts database: $FactsPath"
    try {
        $factsDatabase = Get-Content -Path $FactsPath -Raw -Encoding UTF8 | ConvertFrom-Json
    }
    catch {
        throw "Failed to load facts database: $($_.Exception.Message)"
    }

    # Filter to relevant facts (from this document and verified/drift facts)
    $relevantFacts = $factsDatabase.facts | Where-Object {
        $_.overall_status -in @('verified', 'drift', 'unreachable')
    }

    if (-not $relevantFacts -or @($relevantFacts).Count -eq 0) {
        Write-Warning "No verified or drifted facts found in database. Cannot generate updated document."
        return
    }

    $factsJson = $relevantFacts | ConvertTo-Json -Depth 10

    # Load update prompt template
    $templatePath = Join-Path (Join-Path $script:ModuleRoot 'Templates') 'update-prompt.txt'
    if (-not $script:ModuleRoot) {
        $templatePath = Join-Path (Join-Path $PSScriptRoot '..') (Join-Path 'Templates' 'update-prompt.txt')
    }

    if (Test-Path $templatePath) {
        $promptTemplate = Get-Content -Path $templatePath -Raw -Encoding UTF8
    }
    else {
        Write-Warning "Update prompt template not found. Using built-in template."
        $promptTemplate = @'
You are an IT documentation writer. Below is an original IT document followed by verified facts about the current environment.
 
Rewrite the document to be accurate based on the verified facts. Rules:
1. Keep the same structure and style as the original
2. Correct any information that has drifted from reality
3. If highlight_changes is true, mark corrections with [UPDATED: old value -> new value]
4. Add a "Last Verified" date at the top
5. Do not remove information that couldn't be verified -- mark it as [UNVERIFIED]
6. Add any discovered items not in the original under a "New Discoveries" section
 
ORIGINAL DOCUMENT:
{original_text}
 
VERIFIED FACTS:
{facts_json}
 
HIGHLIGHT CHANGES: {highlight_changes}
'@

    }

    # Build the prompt
    $highlightValue = if ($HighlightChanges) { 'true' } else { 'false' }
    $userPrompt = $promptTemplate `
        -replace '\{original_text\}', $originalText `
        -replace '\{facts_json\}', $factsJson `
        -replace '\{highlight_changes\}', $highlightValue

    # Call the AI
    Write-Verbose "Sending document and facts to AI for rewriting..."

    $aiParams = @{
        Provider     = $Provider
        UserPrompt   = $userPrompt
        SystemPrompt = 'You are an IT documentation writer. Rewrite documentation to be accurate based on verified facts.'
        Temperature  = 0.2
        MaxTokens    = 4096
    }
    if ($ApiKey) { $aiParams['ApiKey'] = $ApiKey }
    if ($Model) { $aiParams['Model'] = $Model }
    if ($Endpoint) { $aiParams['Endpoint'] = $Endpoint }

    try {
        $updatedContent = Invoke-AICompletion @aiParams
    }
    catch {
        throw "AI document update failed: $($_.Exception.Message)"
    }

    # Clean up AI response (remove markdown code blocks if present)
    if ($updatedContent -match '```markdown\s*([\s\S]*?)\s*```') {
        $updatedContent = $Matches[1]
    }
    elseif ($updatedContent -match '```\s*([\s\S]*?)\s*```') {
        $updatedContent = $Matches[1]
    }
    $updatedContent = $updatedContent.Trim()

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

    # Determine output filename
    $baseName = [System.IO.Path]::GetFileNameWithoutExtension($docItem.Name)
    $extension = switch ($Format) {
        'Markdown' { '.md' }
        'HTML'     { '.html' }
    }
    $outputFileName = "${baseName}-updated${extension}"
    $outputFilePath = Join-Path $OutputPath $outputFileName

    # If HTML format, wrap in basic HTML
    if ($Format -eq 'HTML') {
        $updatedContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$baseName - Updated Documentation</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; max-width: 900px; margin: 2rem auto; padding: 0 1rem; line-height: 1.7; color: #e6edf3; background: #0d1117; }
        h1, h2, h3 { color: #a371f7; }
        .updated { background: #0f2d1a; padding: 0.1rem 0.3rem; border-radius: 3px; color: #3fb950; }
        .unverified { background: #3d2e00; padding: 0.1rem 0.3rem; border-radius: 3px; color: #d29922; }
        pre { background: #161b22; padding: 1rem; border-radius: 6px; overflow-x: auto; }
        code { background: #161b22; padding: 0.15rem 0.3rem; border-radius: 3px; }
    </style>
</head>
<body>
$updatedContent
</body>
</html>
"@

    }

    # Save the updated document
    $updatedContent | Out-File -FilePath $outputFilePath -Encoding UTF8 -Force
    Write-Verbose "Updated document saved to: $outputFilePath"

    # Return file info
    $result = [PSCustomObject]@{
        OriginalDocument = $docItem.FullName
        UpdatedDocument  = (Resolve-Path $outputFilePath).Path
        Format           = $Format
        HighlightChanges = $HighlightChanges.IsPresent
        FactsUsed        = @($relevantFacts).Count
        GeneratedAt      = (Get-Date).ToString('o')
    }

    return $result
}