diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 0a608b7..727102f 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -209,8 +209,8 @@ $leftoverPlaceholders = @(Get-ChildItem $output -File -Recurse | ForEach-Object # __AI_CONFIG_ROOT__ is resolved at install time, once the destination is known; it is # expected to remain in generated output. -cmatch keeps this case-sensitive so Python # dunder names (__main__, __name__) in flashbang.sh are not mistaken for placeholders. - $content = (Get-Content -LiteralPath $_.FullName -Raw) -replace '__AI_CONFIG_ROOT__|__POWERSHELL_COMMAND__', '' - if ($content -cmatch '__[A-Z0-9_]+__' -and $content -notmatch '__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY__') { $_.FullName } + $content = (Get-Content -LiteralPath $_.FullName -Raw) -replace '__AI_CONFIG_ROOT__|__POWERSHELL_COMMAND__|__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY__', '' + if ($content -cmatch '__[A-Z0-9_]+__') { $_.FullName } }) if ($leftoverPlaceholders.Count) { throw "Unresolved template placeholders in: $($leftoverPlaceholders -join ', ')" } diff --git a/scripts/test-build-validation.ps1 b/scripts/test-build-validation.ps1 index de821ff..16d02ff 100644 --- a/scripts/test-build-validation.ps1 +++ b/scripts/test-build-validation.ps1 @@ -24,6 +24,9 @@ function Test-BuildFails([string]$Label, [scriptblock]$Mutate) { if (-not $failed) { throw "Expected build to fail for case '$Label' but it succeeded." } } +$baseline = New-RepoCopy +& (Join-Path $baseline 'scripts/build.ps1') -Summary | Out-Null + Test-BuildFails 'invalid Claude settings.json' { param($copy) Add-Content (Join-Path $copy 'adapters/claude/config/settings.json') '} this is not json {' @@ -47,6 +50,12 @@ Test-BuildFails 'leftover template placeholder' { Add-Content (Join-Path $copy 'shared/global-instructions.md') "`n__NOT_A_REAL_PLACEHOLDER__" } +Test-BuildFails 'unknown placeholder beside an allowed installer placeholder' { + param($copy) + $path = Join-Path $copy 'adapters/claude/config/settings.json' + (Get-Content $path -Raw).Replace('__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY__', '__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY____UNKNOWN_PLACEHOLDER__') | Set-Content $path +} + Remove-Item $work -Recurse -Force -ErrorAction SilentlyContinue if ($Summary) { Write-Output 'Tests: PASS | build validation' } else { Write-Output 'PASS build validation: invalid JSON, duplicate agent, duplicate plugin, and leftover placeholders are all rejected' } exit 0 diff --git a/scripts/test-build-validation.sh b/scripts/test-build-validation.sh index d80bda5..32534bc 100755 --- a/scripts/test-build-validation.sh +++ b/scripts/test-build-validation.sh @@ -31,6 +31,9 @@ test_build_fails() { rm -rf -- "$copy" } +baseline=$(new_repo_copy) +bash "$baseline/scripts/build.sh" --summary >/dev/null + mutate_invalid_json() { printf '} this is not json {' >> "$1/adapters/claude/config/settings.json" } @@ -52,4 +55,9 @@ mutate_leftover_placeholder() { } test_build_fails 'leftover template placeholder' mutate_leftover_placeholder +mutate_mixed_placeholders() { + sed -i 's/__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY__/__CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY__ __UNKNOWN_PLACEHOLDER__/' "$1/adapters/claude/config/settings.json" +} +test_build_fails 'unknown placeholder beside an allowed installer placeholder' mutate_mixed_placeholders + if [ "$summary" = true ]; then printf 'Tests: PASS | build validation\n'; else printf 'PASS build validation: invalid JSON, duplicate agent, duplicate plugin, and leftover placeholders are all rejected\n'; fi