benchmark/benchmark.ps1

#Requires -Version 5.1
<#
    .SYNOPSIS
    Maintainer-only benchmark script (FR-016). Never installs, downloads, or runs
    Windows11Debloat - measures only Octa's own before/after impact. Not part of the shipped
    module; end users never run this. Results feed the README comparison table (T039) by
    hand - this script only produces the underlying, cross-validated numbers.

    .EXAMPLE
    .\benchmark.ps1 -Phase Before -Samples 5
    .\benchmark.ps1 -Phase After -Samples 5
#>

param(
    [Parameter(Mandatory)][ValidateSet('Before', 'After')][string]$Phase,
    [int]$Samples = 5,
    [string]$OutputPath = (Join-Path $PSScriptRoot "results-$Phase.json")
)

. (Join-Path $PSScriptRoot 'BenchmarkHelpers.ps1')

$ramMetric = Measure-OctaMetricSamples -Name 'IdleRamMb' -Samples $Samples -TolerancePercent 10 `
    -Primary { [Math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1KB, 0) } `
    -CrossCheck { [Math]::Round((Get-Counter '\Memory\Available MBytes' -ErrorAction Stop).CounterSamples[0].CookedValue, 0) }

$processMetric = Measure-OctaMetricSamples -Name 'BackgroundProcessCount' -Samples $Samples -TolerancePercent 15 `
    -Primary { (Get-Process).Count } `
    -CrossCheck { (Get-CimInstance Win32_Process).Count }

$timeMetric = Measure-OctaMetricSamples -Name 'ExecutionTimeMs' -Samples $Samples -TolerancePercent 25 `
    -Primary { (Measure-Command { Get-Process | Out-Null }).TotalMilliseconds } `
    -CrossCheck {
        $sw = [System.Diagnostics.Stopwatch]::StartNew()
        Get-Process | Out-Null
        $sw.Stop()
        $sw.Elapsed.TotalMilliseconds
    }

# FR-012/SC-003: environment metadata the maintainer fills in for a real run, so results are
# reproducible by a third party rather than just asserted.
$environment = [pscustomobject]@{
    WindowsBuild          = (Get-CimInstance Win32_OperatingSystem).BuildNumber
    BaselineAppSet        = 'unspecified - fill in for a real benchmark run'
    VmSnapshotOrBareMetal = 'unspecified - fill in for a real benchmark run'
}

$report = [pscustomobject]@{
    ToolMeasured = 'Octa'
    Phase        = $Phase
    Metrics      = @($ramMetric, $processMetric, $timeMetric)
    Environment  = $environment
    CapturedAt   = (Get-Date).ToString('o')
}

$rejected = @($report.Metrics | Where-Object { -not $_.CrossCheckAgreedWithinTolerance })
if ($rejected.Count -gt 0) {
    Write-Warning ("The following metrics did not cross-validate and are withheld from the report (FR-020): {0}" -f ($rejected.Metric -join ', '))
    $report.Metrics = @($report.Metrics | Where-Object { $_.CrossCheckAgreedWithinTolerance })
}

$report | ConvertTo-Json -Depth 6 | Set-Content -Path $OutputPath -Encoding utf8
Write-Host "Benchmark report written to $OutputPath"
$report | Format-List