# Exercise the Windows setup workflow with a fully stubbed local toolchain.
[CmdletBinding()]
param()

$ErrorActionPreference = 'Stop'
$scriptPath = Join-Path $PSScriptRoot 'dev-setup.ps1'
$powerShell = Join-Path $PSHOME 'powershell.exe'
$tempRoot = Join-Path ([IO.Path]::GetTempPath()) "gc-dev-setup-test-$([guid]::NewGuid().ToString('N'))"
$stubBin = Join-Path $tempRoot 'system-bin'
$emptyBin = Join-Path $tempRoot 'empty-bin'
$fakeLocalAppData = Join-Path $tempRoot 'local-app-data'
$dispatcher = Join-Path $tempRoot 'stub-command.ps1'
$stubExecutable = Join-Path $tempRoot 'stub.exe'
$tokenSentinel = 'gc-token-must-not-reach-child'
$legacyTokenSentinel = 'legacy-token-must-not-reach-child'
$userPathBefore = [Environment]::GetEnvironmentVariable('Path', 'User')

function Assert-True {
    param([bool]$Condition, [string]$Message)
    if (-not $Condition) { throw $Message }
}

function Assert-Equal {
    param($Expected, $Actual, [string]$Message)
    if ($Expected -ne $Actual) {
        throw "$Message (expected=$Expected actual=$Actual)"
    }
}

function Set-TestFile {
    param([string]$Path, [string[]]$Lines)
    $parent = Split-Path -Parent $Path
    if ($parent) { New-Item -ItemType Directory -Force -Path $parent | Out-Null }
    Set-Content -LiteralPath $Path -Value $Lines -Encoding ASCII
}

function Restore-TestEnvironment {
    param([hashtable]$Saved)
    foreach ($name in $Saved.Keys) {
        if ($null -eq $Saved[$name]) {
            Remove-Item "Env:$name" -ErrorAction SilentlyContinue
        } else {
            Set-Item "Env:$name" $Saved[$name]
        }
    }
}

function Invoke-Setup {
    param(
        [string]$ToolsRoot,
        [string]$LogPath,
        [string]$SystemPath = $stubBin,
        [string]$GoVersion = 'go1.22.5',
        [hashtable]$ExtraEnvironment = @{},
        [switch]$Check
    )

    $variables = @{
        GC_DEV_TOOLS_DIR = $ToolsRoot
        GC_TOKEN = $tokenSentinel
        GITCODE_TOKEN = $legacyTokenSentinel
        GC_TEST_CHILD_LOG = $LogPath
        GC_TEST_STUB_EXE = $stubExecutable
        GC_TEST_GO_VERSION = $GoVersion
        GC_TEST_GO_LIST_EXIT = '0'
        GOCACHE = 'parent-gocache-sentinel'
        GOTMPDIR = 'parent-gotmp-sentinel'
        GOPROXY = 'http://127.0.0.1:1'
        APPDATA = (Join-Path $tempRoot 'default-outside-appdata')
        GOENV = 'outside-goenv-sentinel'
        GOPATH = (Join-Path $tempRoot 'module-gopath')
        GOMODCACHE = (Join-Path $tempRoot 'module-gopath\pkg\mod')
        LOCALAPPDATA = $fakeLocalAppData
        Path = "$SystemPath;$env:SystemRoot\System32;$env:SystemRoot"
    }
    foreach ($name in $ExtraEnvironment.Keys) { $variables[$name] = $ExtraEnvironment[$name] }
    $saved = @{}
    foreach ($name in $variables.Keys) {
        $saved[$name] = [Environment]::GetEnvironmentVariable($name, 'Process')
        if ($null -eq $variables[$name]) {
            Remove-Item "Env:$name" -ErrorAction SilentlyContinue
        } else {
            Set-Item "Env:$name" $variables[$name]
        }
    }

    try {
        $arguments = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $scriptPath)
        if ($Check) { $arguments += '-Check' }
        $oldErrorAction = $ErrorActionPreference
        $ErrorActionPreference = 'Continue'
        $output = & $powerShell @arguments 2>&1 | Out-String
        $status = $LASTEXITCODE
        $ErrorActionPreference = $oldErrorAction
        return [pscustomobject]@{ Status = $status; Output = $output }
    } finally {
        $ErrorActionPreference = 'Stop'
        Restore-TestEnvironment $saved
    }
}

function Get-NewLogLines {
    param([string]$Path, [int]$Start)
    if (-not (Test-Path $Path)) { return @() }
    return @(Get-Content -LiteralPath $Path | Select-Object -Skip $Start)
}

try {
    New-Item -ItemType Directory -Force -Path $tempRoot, $stubBin, $emptyBin | Out-Null

    $executableSource = @'
using System;
using System.IO;

public static class Program
{
    public static int Main(string[] args)
    {
        string log = Environment.GetEnvironmentVariable("GC_TEST_CHILD_LOG");
        if (!String.IsNullOrEmpty(log))
        {
            string token = Environment.GetEnvironmentVariable("GC_TOKEN") ?? "";
            string legacy = Environment.GetEnvironmentVariable("GITCODE_TOKEN") ?? "";
            string cache = Environment.GetEnvironmentVariable("GOCACHE") ?? "";
            string tmp = Environment.GetEnvironmentVariable("GOTMPDIR") ?? "";
            string appData = Environment.GetEnvironmentVariable("APPDATA") ?? "";
            string goEnv = Environment.GetEnvironmentVariable("GOENV") ?? "";
            File.AppendAllText(log, "exe|GC=" + token + "|LEGACY=" + legacy +
                "|CACHE=" + cache + "|TMP=" + tmp + "|APPDATA=" + appData +
                "|GOENV=" + goEnv + Environment.NewLine);
        }
        string executable = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
        string wingetMarker = Environment.GetEnvironmentVariable("GC_TEST_WINGET_MARKER");
        if (String.Equals(executable, "winget.exe", StringComparison.OrdinalIgnoreCase) &&
            !String.IsNullOrEmpty(wingetMarker))
        {
            File.WriteAllText(wingetMarker, "executed");
        }
        if (args.Length > 0 && args[0] == "--version")
        {
            if (executable.StartsWith("pre-commit", StringComparison.OrdinalIgnoreCase) &&
                Environment.GetEnvironmentVariable("PYTHONDONTWRITEBYTECODE") != "1")
            {
                return 91;
            }
            string version = Environment.GetEnvironmentVariable("GC_TEST_PRECOMMIT_VERSION");
            Console.WriteLine(String.IsNullOrEmpty(version) ? "pre-commit 4.6.1" : version);
        }
        if (args.Length > 1 && args[0] == "-m" && args[1] == "pip" &&
            Environment.GetEnvironmentVariable("GC_TEST_PRECOMMIT_PIP_FAIL") == "1")
        {
            return 23;
        }
        return 0;
    }
}
'@
    Add-Type -TypeDefinition $executableSource -Language CSharp `
        -OutputAssembly $stubExecutable -OutputType ConsoleApplication

    $dispatcherSource = @'
param(
    [Parameter(Position = 0)]
    [string]$Tool,
    [Parameter(Position = 1, ValueFromRemainingArguments = $true)]
    [string[]]$Arguments,
    [Parameter()]
    [Alias('o')]
    [string]$OutputPath
)

$ErrorActionPreference = 'Stop'
$record = "$Tool|$($Arguments -join ' ')|GC=$env:GC_TOKEN|LEGACY=$env:GITCODE_TOKEN" +
    "|CACHE=$env:GOCACHE|TMP=$env:GOTMPDIR|APPDATA=$env:APPDATA|GOENV=$env:GOENV" +
    "|GOPATH=$env:GOPATH|GOMODCACHE=$env:GOMODCACHE|GOPROXY=$env:GOPROXY|GOBIN=$env:GOBIN"
Add-Content -LiteralPath $env:GC_TEST_CHILD_LOG -Value $record

if ($Tool -eq 'go') {
    if ($env:GC_TEST_WRITE_GO_CONFIG -eq '1') {
        $telemetry = Join-Path $env:APPDATA 'go\telemetry'
        New-Item -ItemType Directory -Force -Path $telemetry | Out-Null
        Set-Content -LiteralPath (Join-Path $telemetry 'stub-write') -Value 'isolated'
    }
    if ($Arguments[0] -eq 'version' -and $Arguments.Count -eq 1) {
        Write-Output "go version $env:GC_TEST_GO_VERSION windows/amd64"
        exit 0
    }
    if ($Arguments[0] -eq 'env' -and $Arguments[1] -eq 'GOVERSION') {
        Write-Output $env:GC_TEST_GO_VERSION
        exit 0
    }
    if ($Arguments[0] -eq 'version' -and $Arguments[1] -eq '-m') {
        $binary = $Arguments[2]
        if (-not (Test-Path -LiteralPath $binary)) { exit 1 }
        $content = Get-Content -Raw -LiteralPath $binary
        $module = [regex]::Match($content, '(?m)^module=(.+)$').Groups[1].Value.Trim()
        $version = [regex]::Match($content, '(?m)^version=(.+)$').Groups[1].Value.Trim()
        if (-not $module -or -not $version) { exit 1 }
        Write-Output $binary
        Write-Output "`tmod`t$module`t$version"
        exit 0
    }
    if ($Arguments[0] -eq 'list') {
        if ($env:GC_TEST_GO_LIST_STDERR) {
            [Console]::Error.WriteLine($env:GC_TEST_GO_LIST_STDERR)
        }
        exit [int]$env:GC_TEST_GO_LIST_EXIT
    }
    if ($Arguments[0] -eq 'mod' -and $Arguments[1] -eq 'download') { exit 0 }
    if ($Arguments[0] -eq 'install') {
        $spec = $Arguments[1]
        $at = $spec.LastIndexOf('@')
        $package = $spec.Substring(0, $at)
        $version = $spec.Substring($at + 1)
        if ($package -eq 'github.com/golangci/golangci-lint/v2/cmd/golangci-lint') {
            $name = 'golangci-lint'
            $module = 'github.com/golangci/golangci-lint/v2'
        } elseif ($package -eq 'github.com/zricethezav/gitleaks/v8') {
            $name = 'gitleaks'
            $module = $package
        } else {
            exit 12
        }
        New-Item -ItemType Directory -Force -Path $env:GOBIN | Out-Null
        Set-Content -LiteralPath (Join-Path $env:GOBIN "$name.exe") -Encoding ASCII -Value @(
            'GC_STUB'
            "module=$module"
            "version=$version"
        )
        exit 0
    }
    if ($Arguments[0] -eq 'build') {
        if (-not $OutputPath) { exit 13 }
        Copy-Item -LiteralPath $env:GC_TEST_STUB_EXE -Destination $OutputPath -Force
        exit 0
    }
    if ($Arguments[0] -eq 'test') {
        if ($env:GC_TEST_GO_TEST_STDERR) {
            [Console]::Error.WriteLine($env:GC_TEST_GO_TEST_STDERR)
        }
        if ($env:GC_TEST_GO_TEST_EXIT) { exit [int]$env:GC_TEST_GO_TEST_EXIT }
        exit 0
    }
    exit 14
}

if ($Tool -in @('python', 'python3')) {
    if ($Arguments[0] -eq '--version') {
        Write-Output 'Python 3.12.4'
        exit 0
    }
    if ($Arguments[0] -eq '-m' -and $Arguments[1] -eq 'venv') {
        $scripts = Join-Path $Arguments[2] 'Scripts'
        New-Item -ItemType Directory -Force -Path $scripts | Out-Null
        Copy-Item -LiteralPath $env:GC_TEST_STUB_EXE -Destination (Join-Path $scripts 'python.exe')
        Copy-Item -LiteralPath $env:GC_TEST_STUB_EXE -Destination (Join-Path $scripts 'pre-commit.exe')
        exit 0
    }
    exit 0
}

if ($Arguments[0] -eq '--version') { Write-Output "$Tool stub 1.0" }
exit 0
'@
    Set-Content -LiteralPath $dispatcher -Value $dispatcherSource -Encoding UTF8
    foreach ($tool in @('go', 'git', 'python', 'python3', 'make', 'mingw32-make', 'gcc')) {
        Set-TestFile (Join-Path $stubBin "$tool.cmd") @(
            '@echo off'
            "`"$powerShell`" -NoProfile -ExecutionPolicy Bypass -File `"$dispatcher`" $tool %*"
            'exit /b %ERRORLEVEL%'
        )
    }

    $gitBash = Join-Path $fakeLocalAppData 'Programs\Git\bin\bash.exe'
    New-Item -ItemType Directory -Force -Path (Split-Path -Parent $gitBash) | Out-Null
    Copy-Item -LiteralPath $stubExecutable -Destination $gitBash

    Write-Host '[test] installation and idempotency'
    $installTools = Join-Path $tempRoot 'install-tools'
    $installLog = Join-Path $tempRoot 'install.log'
    $first = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog
    Assert-Equal 0 $first.Status "first installation failed`n$($first.Output)"
    Assert-True ([bool]($first.Output -match [regex]::Escape(
        "`$env:Path = `"$installTools\bin;`$env:Path`""))) `
        'setup output did not provide the current-shell PATH command'
    $installLines = @(Get-Content -LiteralPath $installLog)
    Assert-True ([bool]($installLines -match
        '^go\|install github\.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2\.12\.2\|')) `
        'golangci-lint was not installed from its cmd package'
    Assert-True ([bool]($installLines -match
        '^go\|install github\.com/zricethezav/gitleaks/v8@v8\.30\.1\|')) `
        'gitleaks install package was not used'
    Assert-True ([bool]($installLines -match
        ('^python3\|-m venv {0}\\pre-commit-4\.6\.1\|' -f [regex]::Escape($installTools)))) `
        'pre-commit was not created in its versioned final venv'
    foreach ($name in @('golangci-lint.exe', 'gitleaks.exe', 'make.cmd', 'python3.cmd', 'pre-commit.cmd')) {
        Assert-True (Test-Path (Join-Path $installTools "bin\$name")) "missing managed artifact: $name"
    }
    $goInstallCount = @($installLines -match '^go\|install ').Count
    $venvInstallCount = @($installLines -match '^python3\|-m venv ').Count
    $second = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog
    Assert-Equal 0 $second.Status "second installation failed`n$($second.Output)"
    $secondInstallCount = @((Get-Content -LiteralPath $installLog) -match '^go\|install ').Count
    Assert-Equal $goInstallCount $secondInstallCount 'second installation was not idempotent'
    $secondVenvCount = @((Get-Content -LiteralPath $installLog) -match '^python3\|-m venv ').Count
    Assert-Equal $venvInstallCount $secondVenvCount 'second installation rebuilt the pre-commit venv'
    $leftovers = @(Get-ChildItem -Force -Recurse -LiteralPath $installTools |
        Where-Object {
            $_.Name -like '.*-install-*' -or $_.Name -like '.pre-commit-backup-*' -or
            $_.Name -like '*.tmp'
        })
    Assert-Equal 0 $leftovers.Count 'temporary publish files were left behind'

    Write-Host '[test] complete and incomplete check mode'
    $beforeCheck = @(Get-Content -LiteralPath $installLog).Count
    $outsideAppData = Join-Path $tempRoot 'outside-check-appdata'
    $checkGoPath = Join-Path $tempRoot 'check-gopath'
    $checkModCache = Join-Path $tempRoot 'check-modcache'
    $checkDownloadCache = Join-Path $checkModCache 'cache\download'
    New-Item -ItemType Directory -Force -Path $outsideAppData, $checkDownloadCache | Out-Null
    Set-TestFile (Join-Path $checkDownloadCache 'sentinel') @('read-only-source')
    $checkModCacheEntriesBefore = @(Get-ChildItem -Force -Recurse -LiteralPath $checkModCache).Count
    $expectedLocalProxy = ([Uri]::new([IO.Path]::GetFullPath($checkDownloadCache))).AbsoluteUri
    $complete = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog -Check -ExtraEnvironment @{
        APPDATA = $outsideAppData
        GOENV = 'outside-goenv-sentinel'
        GOPATH = $checkGoPath
        GOMODCACHE = $checkModCache
        GC_TEST_WRITE_GO_CONFIG = '1'
    }
    Assert-Equal 0 $complete.Status "complete check mode failed`n$($complete.Output)"
    $checkLines = Get-NewLogLines $installLog $beforeCheck
    $checkChildLines = @($checkLines | Where-Object { $_ -match '\|APPDATA=' })
    Assert-True ($checkChildLines.Count -gt 0) 'check mode did not launch any observable child process'
    foreach ($line in $checkChildLines) {
        Assert-True ($line -match '\|APPDATA=([^|]*gc-dev-check-[^|]*\\appdata)\|GOENV=off') `
            "check child did not observe isolated APPDATA/GOENV: $line"
    }
    $goCheckLines = @($checkLines | Where-Object { $_ -like 'go|*' })
    Assert-True ($goCheckLines.Count -gt 0) 'check mode did not invoke the Go stub'
    foreach ($line in $goCheckLines) {
        Assert-True ($line -match '\|CACHE=([^|]*gc-dev-check-[^|]*\\gocache)\|TMP=([^|]*gc-dev-check-[^|]*\\gotmp)') `
            "check mode did not isolate Go cache/temp: $line"
        Assert-True (-not (Test-Path $Matches[1])) "isolated GOCACHE was not removed: $($Matches[1])"
        Assert-True (-not (Test-Path $Matches[2])) "isolated GOTMPDIR was not removed: $($Matches[2])"
        Assert-True ($line -match '\|APPDATA=([^|]*gc-dev-check-[^|]*\\appdata)\|GOENV=off\|') `
            "check mode did not isolate APPDATA/GOENV: $line"
        Assert-True (-not (Test-Path $Matches[1])) "isolated APPDATA was not removed: $($Matches[1])"
        Assert-True ($line -match
            '\|GOPATH=([^|]*gc-dev-check-[^|]*\\gopath)\|GOMODCACHE=([^|]*gc-dev-check-[^|]*\\modcache)\|') `
            "check mode did not isolate GOPATH/GOMODCACHE: $line"
        Assert-True (-not (Test-Path $Matches[1])) "isolated GOPATH was not removed: $($Matches[1])"
        Assert-True (-not (Test-Path $Matches[2])) "isolated GOMODCACHE was not removed: $($Matches[2])"
        Assert-True ($line -match ("\|GOPROXY={0}\|" -f [regex]::Escape($expectedLocalProxy))) `
            "check mode did not use the original download cache as a local proxy: $line"
    }
    Assert-Equal 0 @(Get-ChildItem -Force -LiteralPath $outsideAppData).Count `
        'check mode wrote Go user config outside the isolated APPDATA'
    Assert-Equal $checkModCacheEntriesBefore `
        @(Get-ChildItem -Force -Recurse -LiteralPath $checkModCache).Count `
        'check mode mutated the original module cache'

    $persistedGoPath = Join-Path $tempRoot 'persisted go#path'
    $persistedModCache = Join-Path $tempRoot 'persisted mod#cache'
    $persistedDownloadCache = Join-Path $persistedModCache 'cache\download'
    $persistedGoEnv = Join-Path $tempRoot 'persisted-go-env'
    New-Item -ItemType Directory -Force -Path $persistedDownloadCache | Out-Null
    Set-TestFile $persistedGoEnv @(
        "GOPATH=$persistedGoPath"
        "GOMODCACHE=$persistedModCache"
    )
    $persistedGoEnvBefore = Get-Content -Raw -LiteralPath $persistedGoEnv
    $beforePersistedCheck = @(Get-Content -LiteralPath $installLog).Count
    $persistedCheck = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog -Check `
        -ExtraEnvironment @{
            GOENV = $persistedGoEnv
            GOPATH = $null
            GOMODCACHE = $null
        }
    Assert-Equal 0 $persistedCheck.Status "persisted Go env check failed`n$($persistedCheck.Output)"
    $persistedLines = Get-NewLogLines $installLog $beforePersistedCheck
    $expectedPersistedProxy = ([Uri]::new([IO.Path]::GetFullPath($persistedDownloadCache))).AbsoluteUri
    Assert-True ([bool]($persistedLines -match
        ("\|GOPROXY={0}\|" -f [regex]::Escape($expectedPersistedProxy)))) `
        'check mode ignored persisted GOMODCACHE'
    Assert-Equal $persistedGoEnvBefore (Get-Content -Raw -LiteralPath $persistedGoEnv) `
        'check mode modified the persisted Go env file'

    $moduleGap = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog -Check `
        -ExtraEnvironment @{
            GC_TEST_GO_LIST_EXIT = '17'
            GC_TEST_GO_LIST_STDERR = 'module cache miss'
        }
    Assert-Equal 1 $moduleGap.Status "module cache miss did not produce a gap`n$($moduleGap.Output)"
    Assert-True ($moduleGap.Output -match 'module dependencies \(run without -Check to download\)') `
        'native stderr aborted check mode before the module gap was recorded'
    Assert-True ($moduleGap.Output -match 'incomplete: 1 dependency gap') `
        'module cache miss did not reach the final gap summary'

    $raceGap = Invoke-Setup -ToolsRoot $installTools -LogPath $installLog -Check `
        -ExtraEnvironment @{
            GC_TEST_GO_TEST_EXIT = '18'
            GC_TEST_GO_TEST_STDERR = 'race module cache miss'
        }
    Assert-Equal 1 $raceGap.Status "race failure did not produce a gap`n$($raceGap.Output)"
    Assert-True ($raceGap.Output -match 'race-enabled test') `
        'native stderr aborted check mode before the race gap was recorded'
    Assert-True ($raceGap.Output -match 'incomplete: 1 dependency gap') `
        'race failure did not reach the final gap summary'

    $missingTools = Join-Path $tempRoot 'missing-tools'
    $missing = Invoke-Setup -ToolsRoot $missingTools -LogPath (Join-Path $tempRoot 'missing.log') `
        -SystemPath $emptyBin -Check
    Assert-Equal 1 $missing.Status "missing dependency check did not fail`n$($missing.Output)"
    Assert-True (-not (Test-Path $missingTools)) 'check mode created the managed tools directory'

    Write-Host '[test] child credential isolation'
    $allLog = Get-Content -Raw -LiteralPath $installLog
    Assert-True ($allLog -notmatch [regex]::Escape($tokenSentinel)) 'GC_TOKEN reached a child process'
    Assert-True ($allLog -notmatch [regex]::Escape($legacyTokenSentinel)) `
        'GITCODE_TOKEN reached a child process'

    Write-Host '[test] forged managed wrapper content'
    $managedMarker = 'rem Managed by gitcode-cli scripts/dev-setup.ps1'
    $makeWrapper = Join-Path $installTools 'bin\make.cmd'
    $savedMakeWrapper = [IO.File]::ReadAllText($makeWrapper, [Text.Encoding]::ASCII)
    $forgedWrapperMarker = Join-Path $tempRoot 'forged-wrapper-was-run'
    [IO.File]::WriteAllText($makeWrapper, [string]::Join([Environment]::NewLine, @(
        $managedMarker
        '@echo off'
        "echo forged>>`"$forgedWrapperMarker`""
    )) + [Environment]::NewLine, [Text.Encoding]::ASCII)
    try {
        $forged = Invoke-Setup -ToolsRoot $installTools -LogPath (Join-Path $tempRoot 'forged.log')
        Assert-Equal 1 $forged.Status "forged wrapper scenario unexpectedly passed`n$($forged.Output)"
        Assert-True (-not (Test-Path $forgedWrapperMarker)) 'forged marker wrapper was executed'
        Assert-True ($forged.Output -match 'refusing to overwrite unmanaged wrapper') `
            'forged wrapper content was not rejected'
    } finally {
        [IO.File]::WriteAllText($makeWrapper, $savedMakeWrapper, [Text.Encoding]::ASCII)
    }

    $preCommitWrapper = Join-Path $installTools 'bin\pre-commit.cmd'
    $savedPreCommitWrapper = [IO.File]::ReadAllText($preCommitWrapper, [Text.Encoding]::ASCII)
    $forgedPreCommitMarker = Join-Path $tempRoot 'forged-precommit-was-run'
    $forgedPreCommitTarget = Join-Path $tempRoot 'forged-precommit.cmd'
    Set-TestFile $forgedPreCommitTarget @(
        '@echo off'
        "echo bad>>`"$forgedPreCommitMarker`""
        '@echo pre-commit 4.6.1'
        'exit /b 0'
    )
    [IO.File]::WriteAllText($preCommitWrapper, [string]::Join([Environment]::NewLine, @(
        $managedMarker
        '@echo off'
        "`"$forgedPreCommitTarget`" %*"
    )) + [Environment]::NewLine, [Text.Encoding]::ASCII)
    try {
        $forgedPreCommit = Invoke-Setup -ToolsRoot $installTools `
            -LogPath (Join-Path $tempRoot 'forged-precommit.log')
        Assert-Equal 1 $forgedPreCommit.Status `
            "forged pre-commit wrapper unexpectedly passed`n$($forgedPreCommit.Output)"
        Assert-True (-not (Test-Path $forgedPreCommitMarker)) 'forged pre-commit target was executed'
        Assert-True ($forgedPreCommit.Output -match 'refusing forged or unmanaged pre-commit wrapper') `
            'forged pre-commit target was not rejected'
    } finally {
        [IO.File]::WriteAllText($preCommitWrapper, $savedPreCommitWrapper, [Text.Encoding]::ASCII)
    }

    Write-Host '[test] unmanaged and failed pre-commit installation'
    $unmanagedPreCommitTools = Join-Path $tempRoot 'unmanaged-precommit-tools'
    $unmanagedVenv = Join-Path $unmanagedPreCommitTools 'pre-commit-4.6.1'
    New-Item -ItemType Directory -Force -Path $unmanagedVenv | Out-Null
    Set-TestFile (Join-Path $unmanagedVenv 'keep.txt') @('do-not-modify')
    $unmanagedPreCommit = Invoke-Setup -ToolsRoot $unmanagedPreCommitTools `
        -LogPath (Join-Path $tempRoot 'unmanaged-precommit.log')
    Assert-Equal 1 $unmanagedPreCommit.Status `
        "unmanaged pre-commit scenario unexpectedly passed`n$($unmanagedPreCommit.Output)"
    Assert-Equal 'do-not-modify' ((Get-Content -Raw -LiteralPath `
        (Join-Path $unmanagedVenv 'keep.txt')).Trim()) 'unmanaged pre-commit content was modified'
    Assert-True ($unmanagedPreCommit.Output -match 'refusing to replace unmanaged pre-commit environment') `
        'unmanaged pre-commit environment was not rejected'

    $failedPreCommitTools = Join-Path $tempRoot 'failed-precommit-tools'
    $failedPreCommit = Invoke-Setup -ToolsRoot $failedPreCommitTools `
        -LogPath (Join-Path $tempRoot 'failed-precommit.log') `
        -ExtraEnvironment @{ GC_TEST_PRECOMMIT_PIP_FAIL = '1' }
    Assert-Equal 1 $failedPreCommit.Status `
        "failed pre-commit installation unexpectedly passed`n$($failedPreCommit.Output)"
    Assert-True (-not (Test-Path (Join-Path $failedPreCommitTools 'pre-commit-4.6.1'))) `
        'failed pre-commit install left a final venv'
    Assert-True (-not (Test-Path (Join-Path $failedPreCommitTools 'bin\pre-commit.cmd'))) `
        'failed pre-commit install left a wrapper'
    $failedPreCommitLeftovers = @(Get-ChildItem -Force -LiteralPath $failedPreCommitTools |
        Where-Object { $_.Name -like '.pre-commit-*' })
    Assert-Equal 0 $failedPreCommitLeftovers.Count 'failed pre-commit install left staging or backup state'

    Write-Host '[test] nested pre-commit reparse point'
    $preCommitScripts = Join-Path $installTools 'pre-commit-4.6.1\Scripts'
    $nestedPreCommitTarget = Join-Path $tempRoot 'nested-precommit-target'
    [IO.Directory]::Move($preCommitScripts, $nestedPreCommitTarget)
    New-Item -ItemType Junction -Path $preCommitScripts -Target $nestedPreCommitTarget | Out-Null
    try {
        $nestedPreCommit = Invoke-Setup -ToolsRoot $installTools `
            -LogPath (Join-Path $tempRoot 'nested-precommit.log')
        Assert-Equal 1 $nestedPreCommit.Status `
            "nested pre-commit reparse scenario unexpectedly passed`n$($nestedPreCommit.Output)"
        Assert-True ($nestedPreCommit.Output -match 'pre-commit environment containing a reparse point') `
            'nested pre-commit reparse point was not rejected'
    } finally {
        [IO.Directory]::Delete($preCommitScripts)
        [IO.Directory]::Move($nestedPreCommitTarget, $preCommitScripts)
    }

    Write-Host '[test] unmanaged artifact protection and system PATH filtering'
    $unmanagedTools = Join-Path $tempRoot 'unmanaged-tools'
    $unmanagedBin = Join-Path $unmanagedTools 'bin'
    New-Item -ItemType Directory -Force -Path $unmanagedBin | Out-Null
    Set-TestFile (Join-Path $unmanagedBin 'golangci-lint.exe') @('do-not-overwrite')
    Set-TestFile (Join-Path $unmanagedBin 'make.cmd') @('@echo unmanaged-wrapper')
    $hijackMarker = Join-Path $tempRoot 'managed-go-was-run'
    Set-TestFile (Join-Path $unmanagedBin 'go.cmd') @(
        '@echo off'
        "echo bad>>`"$hijackMarker`""
        'exit /b 77'
    )
    $unmanagedBinAlias = Join-Path $tempRoot 'unmanaged-bin-alias'
    New-Item -ItemType Junction -Path $unmanagedBinAlias -Target $unmanagedBin | Out-Null
    $unmanaged = Invoke-Setup -ToolsRoot $unmanagedTools -LogPath (Join-Path $tempRoot 'unmanaged.log') `
        -SystemPath "$unmanagedBinAlias;$stubBin"
    Assert-Equal 1 $unmanaged.Status "unmanaged overwrite scenario unexpectedly passed`n$($unmanaged.Output)"
    Assert-Equal 'do-not-overwrite' ((Get-Content -Raw -LiteralPath `
        (Join-Path $unmanagedBin 'golangci-lint.exe')).Trim()) 'unmanaged Go tool was overwritten'
    Assert-Equal '@echo unmanaged-wrapper' ((Get-Content -Raw -LiteralPath `
        (Join-Path $unmanagedBin 'make.cmd')).Trim()) 'unmanaged wrapper was overwritten'
    Assert-True (-not (Test-Path $hijackMarker)) 'ManagedBin hijacked system Go resolution'
    Assert-True ($unmanaged.Output -match 'refusing to overwrite unmanaged Go tool') `
        'unmanaged Go tool refusal was not reported'
    Assert-True ($unmanaged.Output -match 'refusing to overwrite unmanaged wrapper') `
        'unmanaged wrapper refusal was not reported'

    Write-Host '[test] reparse-point protection'
    $reparseTools = Join-Path $tempRoot 'reparse-tools'
    $reparseTarget = Join-Path $tempRoot 'reparse-target'
    New-Item -ItemType Directory -Force -Path $reparseTools, $reparseTarget | Out-Null
    New-Item -ItemType Junction -Path (Join-Path $reparseTools 'bin') -Target $reparseTarget | Out-Null
    $reparse = Invoke-Setup -ToolsRoot $reparseTools -LogPath (Join-Path $tempRoot 'reparse.log')
    Assert-Equal 1 $reparse.Status "reparse-point scenario unexpectedly passed`n$($reparse.Output)"
    Assert-Equal 0 @(Get-ChildItem -Force -LiteralPath $reparseTarget).Count `
        'script wrote through the ManagedBin reparse point'
    Assert-True ($reparse.Output -match 'refusing to write through reparse point') `
        'reparse-point refusal was not reported'

    Write-Host '[test] malicious winget path and old Go guidance'
    $maliciousWingetMarker = Join-Path $tempRoot 'malicious-winget-was-run'
    $maliciousWinget = Join-Path $stubBin 'winget.exe'
    Copy-Item -LiteralPath $stubExecutable -Destination $maliciousWinget
    $oldGoTools = Join-Path $tempRoot 'old-go-tools'
    $oldGo = Invoke-Setup -ToolsRoot $oldGoTools -LogPath (Join-Path $tempRoot 'old-go.log') `
        -GoVersion 'go1.21.13' -ExtraEnvironment @{
            GC_DEV_WINGET_PATH = $maliciousWinget
            GC_TEST_WINGET_MARKER = $maliciousWingetMarker
        }
    Assert-Equal 1 $oldGo.Status "old Go scenario unexpectedly passed`n$($oldGo.Output)"
    Assert-True (-not (Test-Path $maliciousWingetMarker)) 'untrusted winget from PATH was executed'
    Assert-True ($oldGo.Output -match 'ignoring untrusted winget path') `
        'untrusted winget path was not reported'
    Assert-True ($oldGo.Output -match 'winget unavailable; download and install from https://go.dev/dl/') `
        'old Go without winget did not provide actionable guidance'

    Assert-Equal $userPathBefore ([Environment]::GetEnvironmentVariable('Path', 'User')) `
        'tests or setup script changed the user PATH'
    Write-Host 'Windows dev setup tests passed.'
} finally {
    if (Test-Path $tempRoot) {
        Remove-Item -LiteralPath $tempRoot -Recurse -Force -ErrorAction SilentlyContinue
    }
}