<#
Generate .protected-files automatically based on repo heuristics.
Run: pwsh .\scripts\generate_protected_files.ps1
#>
$repoRoot = (Get-Location).Path
$outFile = Join-Path $repoRoot ".protected-files"
# Files to always include (exact names)
$exactFiles = @(
'package.json',
'package-lock.json',
'openapi.yaml',
'.env',
'.env.*',
'mcp.json',
'README.md',
'Cargo.toml'
)
# Directories to include (as prefixes, trailing slash will be added)
$dirs = @(
'specification',
'docs',
'src/backend',
'src/frontend/components'
)
$results = [System.Collections.Generic.List[string]]::new()
# Exclude common generated or vendored directories
$excludePattern = '(?:^|/)(node_modules|target|dist|\.git)(?:/|$)'
# Add exact files if they exist in repo root or anywhere
foreach ($name in $exactFiles) {
$matches = Get-ChildItem -Path $repoRoot -Recurse -Force -File -Filter $name -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName -ErrorAction SilentlyContinue
foreach ($m in $matches) {
if ($m.StartsWith($repoRoot)) { $rel = $m.Substring($repoRoot.Length) } else { $rel = $m }
$rel = $rel.TrimStart('\','/') -replace '\\','/'
if (-not [string]::IsNullOrWhiteSpace($rel)) {
if ($rel -notmatch $excludePattern) { $results.Add($rel) }
}
}
}
# Add directories as prefixes (with trailing slash)
foreach ($d in $dirs) {
$dirPath = Join-Path $repoRoot $d
if (Test-Path $dirPath) {
$prefix = ($d.TrimEnd('/','\\') + '/') -replace '\\','/'
if ($prefix -notmatch $excludePattern) { $results.Add($prefix) }
}
}
# Heuristic: include top-level build/config files
$heuristic = @('tsconfig.json','yarn.lock','.github','LICENSE')
foreach ($h in $heuristic) {
$p = Join-Path $repoRoot $h
if (Test-Path $p) {
if ((Get-Item $p).PSIsContainer) {
$entry = ($h.TrimEnd('/','\\') + '/') -replace '\\','/'
if ($entry -notmatch $excludePattern) { $results.Add($entry) }
} else {
# only add file if not in excluded paths
$full = Join-Path $repoRoot $h
$rel = $full.Substring($repoRoot.Length).TrimStart('\\','/') -replace '\\','/'
if ($rel -notmatch $excludePattern) { $results.Add($h) }
}
}
}
# Unique, sorted
$unique = $results | Sort-Object -Unique
# Write header and contents
$header = @("# .protected-files (auto-generated)", "# Do NOT edit manually unless you know what you're doing.", "# To regenerate run: pwsh .\\scripts\\generate_protected_files.ps1", "")
$body = $unique
$all = $header + $body
$all | Out-File -FilePath $outFile -Encoding UTF8 -Force
Write-Host "Generated $outFile with $($body.Count) entries."