Files
DBAdmin/brain/lint_knowledge.ps1
2026-06-11 08:07:56 +00:00

141 lines
5.1 KiB
PowerShell

# PowerShell Lint Script for LLM Knowledge Base
# This script scans the knowledge/ directory for broken WikiLinks, orphan pages, and unlinked concepts/entities.
$knowledgeDir = Resolve-Path "knowledge"
$files = Get-ChildItem -Path $knowledgeDir -Recurse -Filter *.md
# Maps to keep track of files and links
$existingFiles = @{} # file name/path -> absolute path
$fileIncomingLinks = @{} # relative path -> list of incoming files
# Exclude list for orphan check (master files)
$excludeOrphans = @(
"knowledge\index.md",
"knowledge\log.md",
"knowledge\feynman_problems.md"
)
# Initialize files
foreach ($file in $files) {
# Normalize relative path (e.g. "knowledge/concepts/accidental-dba.md")
$relPath = (Resolve-Path $file.FullName -Relative) -replace "^\.\\", "" -replace "\\", "/"
$existingFiles[$relPath] = $file.FullName
# Also index by base name (without extension) for simple links, e.g. [[log]] -> "knowledge/log.md"
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
$existingFiles[$baseName] = $file.FullName
$existingFiles[$relPath -replace "\.md$", ""] = $file.FullName
# Initialize incoming links list
$fileIncomingLinks[$relPath] = [System.Collections.Generic.List[string]]::new()
}
$brokenLinks = [System.Collections.Generic.List[PSCustomObject]]::new()
# Scan each file for links
foreach ($file in $files) {
$relPath = (Resolve-Path $file.FullName -Relative) -replace "^\.\\", "" -replace "\\", "/"
$content = Get-Content -Path $file.FullName -Raw
# Match [[WikiLinks]] (can include aliases, e.g. [[link|alias]] or [[link]])
# Regex matches anything inside [[ and ]] except newlines or brackets
$matches = [regex]::Matches($content, "\[\[([^\]|]+)(?:\|[^\]]*)?\]\]")
foreach ($m in $matches) {
$linkTarget = $m.Groups[1].Value.Trim()
# Normalize target path
# Try resolving directly, with .md, or prefixing with "knowledge/"
$resolvedPath = $null
$candidates = @(
$linkTarget,
"$linkTarget.md",
"knowledge/$linkTarget",
"knowledge/$linkTarget.md"
)
foreach ($c in $candidates) {
$normalizedC = $c -replace "\\", "/"
if ($existingFiles.ContainsKey($normalizedC)) {
$resolvedPath = $existingFiles[$normalizedC]
break
}
}
if ($resolvedPath) {
# Link is valid! Log incoming link
$resolvedRelPath = (Resolve-Path $resolvedPath -Relative) -replace "^\.\\", "" -replace "\\", "/"
if ($resolvedRelPath -ne $relPath) { # ignore self-links
$fileIncomingLinks[$resolvedRelPath].Add($relPath)
}
} else {
# Link is broken!
$brokenLinks.Add([PSCustomObject]@{
SourceFile = $relPath
LinkTarget = $linkTarget
MatchText = $m.Value
})
}
}
}
# Find Orphans
$orphans = [System.Collections.Generic.List[string]]::new()
foreach ($key in $fileIncomingLinks.Keys) {
# Check if file is in exclude orphans list
$isExcluded = $false
foreach ($ex in $excludeOrphans) {
$normalizedEx = $ex -replace "\\", "/"
if ($key -eq $normalizedEx -or $key -like "knowledge/indices/*") {
$isExcluded = $true
break
}
}
# An orphan is a file that is not master index/indices and has 0 incoming links (except from index files themselves)
if (-not $isExcluded) {
$incoming = $fileIncomingLinks[$key]
# Filter out incoming links that are indices or master index
$realIncomingCount = 0
foreach ($inc in $incoming) {
if ($inc -ne "knowledge/index.md" -and $inc -notlike "knowledge/indices/*") {
$realIncomingCount++
}
}
if ($realIncomingCount -eq 0) {
$orphans.Add($key)
}
}
}
# Print Beautiful Report
Write-Host "==========================================" -ForegroundColor Green
Write-Host " KNOWLEDGE BASE LINT REPORT" -ForegroundColor Green
Write-Host "==========================================" -ForegroundColor Green
Write-Host "Total Files Scanned: $($files.Count)" -ForegroundColor Cyan
Write-Host ""
if ($brokenLinks.Count -eq 0) {
Write-Host "[OK] No broken WikiLinks found!" -ForegroundColor Green
} else {
Write-Host "[WARNING] Found $($brokenLinks.Count) broken WikiLink(s):" -ForegroundColor Yellow
foreach ($bl in $brokenLinks) {
Write-Host " - In '$($bl.SourceFile)': Link '$($bl.LinkTarget)' is broken (Match: '$($bl.MatchText)')" -ForegroundColor Red
}
}
Write-Host ""
if ($orphans.Count -eq 0) {
Write-Host "[OK] No orphan pages found!" -ForegroundColor Green
} else {
Write-Host "[INFO] Found $($orphans.Count) orphan page(s) (no incoming links from other content pages):" -ForegroundColor Yellow
foreach ($o in $orphans) {
Write-Host " - $o" -ForegroundColor DarkYellow
}
}
Write-Host ""
Write-Host "Lint completed successfully." -ForegroundColor Green