microsoft/hve-core
Publicmirrored from https://github.com/microsoft/hve-coreAvailable
scripts/agents/activation-harness/Update-AgentActivationBaseline.ps1
133lines · modecode
| 1 | #!/usr/bin/env pwsh |
| 2 | # Copyright (c) Microsoft Corporation. |
| 3 | # SPDX-License-Identifier: MIT |
| 4 | |
| 5 | #Requires -Version 7.0 |
| 6 | |
| 7 | <# |
| 8 | .SYNOPSIS |
| 9 | Regenerates baseline.json for the agent activation harness. |
| 10 | |
| 11 | .DESCRIPTION |
| 12 | Computes activation fingerprints for every canonical scenario |
| 13 | (CleanWorkspace, SteadyState, GovernEntry, AdoptTemplate) and writes |
| 14 | the deterministic JSON payload consumed by |
| 15 | scripts/tests/agents/activation-harness/Test-AdrCreationActivation.Tests.ps1. |
| 16 | |
| 17 | Use this script after intentional changes to the agent body, attached |
| 18 | instructions, or any file referenced via #file: directives, so the |
| 19 | drift gate compares against an updated baseline rather than failing |
| 20 | on expected churn. |
| 21 | |
| 22 | Defaults target the @adr-creation agent. Override -AgentPath and |
| 23 | -BaselinePath to manage baselines for additional agents. |
| 24 | |
| 25 | .PARAMETER AgentPath |
| 26 | Repo-relative or absolute path to the agent .agent.md file. |
| 27 | |
| 28 | .PARAMETER BaselinePath |
| 29 | Repo-relative or absolute path to the baseline JSON file to write. |
| 30 | |
| 31 | .PARAMETER RepoRoot |
| 32 | Absolute path to the repository root. Defaults to three levels above |
| 33 | this script. |
| 34 | |
| 35 | .PARAMETER DryRun |
| 36 | Compute the new payload and report drift against the existing baseline, |
| 37 | but do not write the file. Exits 1 when drift is detected so the |
| 38 | command can be wired into CI as a staleness gate. |
| 39 | |
| 40 | .EXAMPLE |
| 41 | ./Update-AgentActivationBaseline.ps1 |
| 42 | |
| 43 | .EXAMPLE |
| 44 | ./Update-AgentActivationBaseline.ps1 -DryRun |
| 45 | |
| 46 | .NOTES |
| 47 | The fingerprint module already returns ordered hashtables with sorted |
| 48 | LoadedFiles, so ConvertTo-Json output is deterministic across runs and |
| 49 | operating systems. |
| 50 | #> |
| 51 | |
| 52 | [CmdletBinding()] |
| 53 | param( |
| 54 | [Parameter(Mandatory = $false)] |
| 55 | [string]$AgentPath = '.github/agents/project-planning/adr-creation.agent.md', |
| 56 | |
| 57 | [Parameter(Mandatory = $false)] |
| 58 | [string]$BaselinePath = 'scripts/agents/activation-harness/baseline.json', |
| 59 | |
| 60 | [Parameter(Mandatory = $false)] |
| 61 | [string]$RepoRoot, |
| 62 | |
| 63 | [Parameter(Mandatory = $false)] |
| 64 | [switch]$DryRun |
| 65 | ) |
| 66 | |
| 67 | $ErrorActionPreference = 'Stop' |
| 68 | |
| 69 | if (-not $RepoRoot) { |
| 70 | $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '../../..')).Path |
| 71 | } |
| 72 | |
| 73 | $modulePath = Join-Path $RepoRoot 'scripts/agents/activation-harness/Get-AgentActivationFingerprint.psm1' |
| 74 | Import-Module -Name $modulePath -Force |
| 75 | |
| 76 | $resolvedAgentPath = if ([System.IO.Path]::IsPathRooted($AgentPath)) { |
| 77 | $AgentPath |
| 78 | } else { |
| 79 | Join-Path $RepoRoot $AgentPath |
| 80 | } |
| 81 | |
| 82 | $resolvedBaselinePath = if ([System.IO.Path]::IsPathRooted($BaselinePath)) { |
| 83 | $BaselinePath |
| 84 | } else { |
| 85 | Join-Path $RepoRoot $BaselinePath |
| 86 | } |
| 87 | |
| 88 | if (-not (Test-Path -LiteralPath $resolvedAgentPath -PathType Leaf)) { |
| 89 | throw "Agent file not found: $resolvedAgentPath" |
| 90 | } |
| 91 | |
| 92 | $scenarios = @('CleanWorkspace', 'SteadyState', 'GovernEntry', 'AdoptTemplate') |
| 93 | |
| 94 | $payload = [ordered]@{} |
| 95 | foreach ($scenario in $scenarios) { |
| 96 | $payload[$scenario] = Get-AgentActivationFingerprint ` |
| 97 | -AgentPath $resolvedAgentPath ` |
| 98 | -ScenarioName $scenario ` |
| 99 | -RepoRoot $RepoRoot |
| 100 | } |
| 101 | |
| 102 | $newJson = (($payload | ConvertTo-Json -Depth 6) -replace "`r`n", "`n") + "`n" |
| 103 | |
| 104 | $existingJson = if (Test-Path -LiteralPath $resolvedBaselinePath -PathType Leaf) { |
| 105 | [System.IO.File]::ReadAllText($resolvedBaselinePath, [System.Text.Encoding]::UTF8) -replace "`r`n", "`n" |
| 106 | } else { |
| 107 | '' |
| 108 | } |
| 109 | |
| 110 | $drift = $newJson -ne $existingJson |
| 111 | |
| 112 | if ($drift) { |
| 113 | Write-Host 'Activation baseline drift detected:' -ForegroundColor Yellow |
| 114 | foreach ($scenario in $scenarios) { |
| 115 | $current = $payload[$scenario] |
| 116 | Write-Host (" {0,-15} ColdStartBytes={1} Hash={2}" -f $scenario, $current.ColdStartBytes, $current.Hash) |
| 117 | } |
| 118 | } else { |
| 119 | Write-Host 'Activation baseline is up to date.' -ForegroundColor Green |
| 120 | } |
| 121 | |
| 122 | if ($DryRun) { |
| 123 | if ($drift) { |
| 124 | Write-Host "Dry run: baseline file not written. Re-run without -DryRun to update $BaselinePath." -ForegroundColor Yellow |
| 125 | exit 1 |
| 126 | } |
| 127 | exit 0 |
| 128 | } |
| 129 | |
| 130 | if ($drift) { |
| 131 | [System.IO.File]::WriteAllText($resolvedBaselinePath, $newJson, [System.Text.UTF8Encoding]::new($false)) |
| 132 | Write-Host "Wrote $BaselinePath" -ForegroundColor Green |
| 133 | } |
| 134 | |