171 lines
6.3 KiB
PowerShell
171 lines
6.3 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$Root = (Join-Path $PSScriptRoot '..'),
|
|
[switch]$FailOnWarning,
|
|
[string[]]$LongPageAllowlist = @(
|
|
'Glossary.md',
|
|
'concepts/Harness-Engineering-Complete-Guide.md',
|
|
'concepts/Meta-Harness.md',
|
|
'practices/OpenAI-Codex-Harness-Engineering.md',
|
|
'queries/What-is-Harness-Engineering-in-Simple-Terms.md'
|
|
)
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$Root = [IO.Path]::GetFullPath($Root)
|
|
$Wiki = Join-Path $Root 'wiki'
|
|
$Index = Join-Path $Wiki 'INDEX.md'
|
|
$State = Join-Path $Wiki 'compile-results.tsv'
|
|
|
|
$errors = [Collections.Generic.List[string]]::new()
|
|
$warnings = [Collections.Generic.List[string]]::new()
|
|
$infos = [Collections.Generic.List[string]]::new()
|
|
$longPageAllowlistSet = @{}
|
|
foreach ($relativePath in $LongPageAllowlist) {
|
|
$normalizedPath = $relativePath.Replace('\', '/')
|
|
$longPageAllowlistSet[$normalizedPath] = $true
|
|
}
|
|
|
|
function Add-Error([string]$Message) { $script:errors.Add("ERROR $Message") }
|
|
function Add-Warning([string]$Message) { $script:warnings.Add("WARNING $Message") }
|
|
function Add-Info([string]$Message) { $script:infos.Add("INFO $Message") }
|
|
|
|
if (-not (Test-Path -LiteralPath $Wiki -PathType Container)) {
|
|
Add-Error "wiki directory does not exist: $Wiki"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $Index -PathType Leaf)) {
|
|
Add-Error "wiki index does not exist: $Index"
|
|
}
|
|
|
|
$pages = @()
|
|
if (Test-Path -LiteralPath $Wiki -PathType Container) {
|
|
$pages = @(Get-ChildItem -LiteralPath $Wiki -Recurse -File -Filter '*.md' |
|
|
Where-Object { $_.DirectoryName -ne (Join-Path $Wiki '_meta') })
|
|
}
|
|
|
|
$byBaseName = @{}
|
|
foreach ($page in $pages) {
|
|
if ($byBaseName.ContainsKey($page.BaseName)) {
|
|
Add-Error "duplicate Wiki basename: $($page.BaseName)"
|
|
} else {
|
|
$byBaseName[$page.BaseName] = $page.FullName
|
|
}
|
|
|
|
}
|
|
|
|
foreach ($page in $pages) {
|
|
$firstLine = Get-Content -LiteralPath $page.FullName -TotalCount 1
|
|
if ($firstLine -ne '---') {
|
|
Add-Error "missing frontmatter: $($page.FullName)"
|
|
}
|
|
|
|
$lineCount = @(Get-Content -LiteralPath $page.FullName).Count
|
|
if ($lineCount -gt 200) {
|
|
$relativeWikiPath = [IO.Path]::GetRelativePath($Wiki, $page.FullName).Replace('\', '/')
|
|
if (-not $longPageAllowlistSet.ContainsKey($relativeWikiPath)) {
|
|
Add-Warning "long page ($lineCount lines): $($page.FullName)"
|
|
}
|
|
}
|
|
|
|
$text = [IO.File]::ReadAllText($page.FullName)
|
|
foreach ($match in [regex]::Matches($text, '\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]')) {
|
|
$target = $match.Groups[1].Value.Trim()
|
|
if (-not $byBaseName.ContainsKey($target)) {
|
|
Add-Error "broken Wiki link in $($page.FullName): $target"
|
|
}
|
|
}
|
|
|
|
foreach ($match in [regex]::Matches($text, '!\[[^\]]*\]\(([^)]+)\)')) {
|
|
$reference = $match.Groups[1].Value.Trim()
|
|
if ($reference -match '^https?://' -or $reference -match '^data:') {
|
|
continue
|
|
}
|
|
$candidate = [IO.Path]::GetFullPath([IO.Path]::Combine($page.DirectoryName, $reference))
|
|
if (-not (Test-Path -LiteralPath $candidate -PathType Leaf)) {
|
|
Add-Error "missing image in $($page.FullName): $reference"
|
|
}
|
|
}
|
|
|
|
foreach ($match in [regex]::Matches($text, '(?m)^\s*- path:\s*["'']?([^"''\r\n]+)')) {
|
|
$sourcePath = $match.Groups[1].Value.Trim()
|
|
if ($sourcePath -match '^https?://') {
|
|
continue
|
|
}
|
|
$candidate = Join-Path $Root $sourcePath
|
|
if (-not (Test-Path -LiteralPath $candidate -PathType Leaf)) {
|
|
Add-Warning "missing raw_sources path in $($page.FullName): $sourcePath"
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Test-Path -LiteralPath $Index -PathType Leaf) {
|
|
$indexText = [IO.File]::ReadAllText($Index)
|
|
foreach ($page in ($pages | Where-Object { $_.Name -notin @('INDEX.md', 'Glossary.md', 'sources.md') })) {
|
|
if ($indexText -notmatch [regex]::Escape($page.BaseName)) {
|
|
Add-Error "page is not indexed by INDEX.md: $($page.FullName)"
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Test-Path -LiteralPath $State -PathType Leaf) {
|
|
try {
|
|
$rows = @(Import-Csv -LiteralPath $State -Delimiter ([char]9))
|
|
$seenPaths = @{}
|
|
foreach ($row in $rows) {
|
|
if ([string]::IsNullOrWhiteSpace($row.raw_path) -or [string]::IsNullOrWhiteSpace($row.hash)) {
|
|
Add-Error "compile-results.tsv contains an incomplete row"
|
|
continue
|
|
}
|
|
if ($seenPaths.ContainsKey($row.raw_path)) {
|
|
Add-Error "duplicate compile-results raw_path: $($row.raw_path)"
|
|
}
|
|
$seenPaths[$row.raw_path] = $true
|
|
if ($row.hash -match 'initial|pending|to-be-computed|placeholder') {
|
|
Add-Error "placeholder hash in compile-results.tsv: $($row.raw_path)"
|
|
}
|
|
$candidate = Join-Path $Root $row.raw_path
|
|
if (-not (Test-Path -LiteralPath $candidate -PathType Leaf)) {
|
|
Add-Warning "compile row points to missing raw file: $($row.raw_path)"
|
|
}
|
|
}
|
|
Add-Info "compile rows: $($rows.Count)"
|
|
} catch {
|
|
Add-Error "compile-results.tsv cannot be parsed: $($_.Exception.Message)"
|
|
}
|
|
} else {
|
|
Add-Error "compile-results.tsv does not exist: $State"
|
|
}
|
|
|
|
$allTextFiles = @(Get-ChildItem -LiteralPath $Root -Recurse -File -Include '*.md', '*.tsv', '*.log' -ErrorAction SilentlyContinue)
|
|
$deletedSourceRefs = @()
|
|
foreach ($file in $allTextFiles) {
|
|
$text = [IO.File]::ReadAllText($file.FullName)
|
|
if ($text -match 'MiniMax-M27-Self-Evolution|raw/MiniMax M2\.7|MiniMax M2\.7 开启模型的自我进化') {
|
|
if ($text -notmatch '用户已删除|同步移除|delete \|') {
|
|
$deletedSourceRefs += $file.FullName
|
|
}
|
|
}
|
|
}
|
|
foreach ($file in ($deletedSourceRefs | Sort-Object -Unique)) {
|
|
Add-Warning "possible stale MiniMax source/page reference: $file"
|
|
}
|
|
|
|
$linkCount = 0
|
|
foreach ($page in $pages) {
|
|
$linkCount += ([regex]::Matches([IO.File]::ReadAllText($page.FullName), '\[\[')).Count
|
|
}
|
|
Add-Info "Wiki Markdown pages: $($pages.Count)"
|
|
Add-Info "Wiki links scanned: $linkCount"
|
|
Add-Info "long-page allowlist entries: $($longPageAllowlistSet.Count)"
|
|
Add-Info "errors: $($errors.Count)"
|
|
Add-Info "warnings: $($warnings.Count)"
|
|
|
|
$errors
|
|
$warnings
|
|
$infos
|
|
|
|
if ($errors.Count -gt 0 -or ($FailOnWarning -and $warnings.Count -gt 0)) {
|
|
exit 1
|
|
}
|
|
exit 0
|