param( [string]$Root = (Split-Path -Parent $PSScriptRoot) ) $ErrorActionPreference = 'Stop' $failures = [System.Collections.Generic.List[string]]::new() $requiredFiles = @( 'AGENTS.md', 'docs\README.md', 'docs\DOCUMENTATION_STANDARD.md', 'docs\modules\README.md', 'docs\modules\TEMPLATE.md', 'targets\DEVELOPMENT_ROADMAP.md' ) foreach ($relative in $requiredFiles) { if (-not (Test-Path -LiteralPath (Join-Path $Root $relative))) { $failures.Add("Missing required documentation file: $relative") } } $agentGuide = Join-Path $Root 'AGENTS.md' if (Test-Path -LiteralPath $agentGuide) { $agentContent = Get-Content -Raw -Encoding UTF8 -LiteralPath $agentGuide if ($agentContent -notmatch 'DOCUMENTATION_STANDARD\.md') { $failures.Add('AGENTS.md does not reference docs/DOCUMENTATION_STANDARD.md') } } $requiredHeadings = @( '## Metadata', '## Purpose', '## Non-goals', '## Context and boundaries', '## Public API', '## Inputs and outputs', '## Data flow', '## Ownership, threading and resources', '## Errors, cancellation and recovery', '## Verification', '## Known gaps and risks', '## Source map' ) $modulesDir = Join-Path $Root 'docs\modules' $moduleCount = 0 if (Test-Path -LiteralPath $modulesDir) { $moduleFiles = Get-ChildItem -LiteralPath $modulesDir -Filter '*.md' -File | Where-Object { $_.Name -notin @('README.md', 'TEMPLATE.md') } foreach ($file in $moduleFiles) { ++$moduleCount $content = Get-Content -Raw -Encoding UTF8 -LiteralPath $file.FullName foreach ($heading in $requiredHeadings) { if (-not $content.Contains($heading)) { $failures.Add("docs/modules/$($file.Name): missing heading '$heading'") } } if ($content -notmatch '(?s)```mermaid\s+flowchart') { $failures.Add("docs/modules/$($file.Name): missing Mermaid data-flow diagram") } if ($content -notmatch '\| Status \|') { $failures.Add("docs/modules/$($file.Name): missing Status metadata") } if ($content -notmatch '\| Last verified \|') { $failures.Add("docs/modules/$($file.Name): missing Last verified metadata") } } } $documentationRoots = @('docs', 'targets', 'coordination') foreach ($relativeRoot in $documentationRoots) { $path = Join-Path $Root $relativeRoot if (-not (Test-Path -LiteralPath $path)) { continue } foreach ($file in Get-ChildItem -LiteralPath $path -Recurse -Filter '*.md' -File) { $content = Get-Content -Raw -Encoding UTF8 -LiteralPath $file.FullName foreach ($match in [regex]::Matches($content, '\[[^\]]+\]\(([^)#]+)(?:#[^)]+)?\)')) { $target = $match.Groups[1].Value if ($target -match '^(https?:|mailto:)') { continue } $resolved = Join-Path $file.DirectoryName $target if (-not (Test-Path -LiteralPath $resolved)) { $relativeFile = Resolve-Path -LiteralPath $file.FullName -Relative $failures.Add("$relativeFile`: broken relative link '$target'") } } } } if ($failures.Count -gt 0) { foreach ($failure in $failures) { Write-Error $failure } exit 1 } Write-Output "Documentation check passed: module_specs=$moduleCount required_files=$($requiredFiles.Count)" exit 0