microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
feat/1873-devcontainer

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/evals/Get-ChangedAIArtifact.ps1

185lines · modecode

1#!/usr/bin/env pwsh
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4#Requires -Version 7.0
5
6<#
7.SYNOPSIS
8 Emits a JSON manifest of AI customization artifacts changed between two git refs.
9
10.DESCRIPTION
11 Runs `git diff --name-status <BaseRef>...<HeadRef>` (three-dot diff to use the merge base)
12 and classifies each entry as an agent / prompt / instruction / skill artifact via the
13 ArtifactDetection module. Writes a manifest JSON array to `-OutFile` (default
14 `logs/changed-ai-artifacts.json`) where each entry has `kind`, `path`, `artifactId`,
15 `status`, and (for renames/copies) `previousPath`. Repo-root-only artifacts and nested
16 collection-scoped artifacts are both detected.
17
18 Exit codes:
19 0 = manifest written successfully (manifest may be empty).
20 2 = git invocation failed.
21
22.PARAMETER BaseRef
23 Base git ref for the diff. Defaults to `origin/main`.
24
25.PARAMETER HeadRef
26 Head git ref for the diff. Defaults to `HEAD`.
27
28.PARAMETER OutFile
29 Output JSON path. Defaults to `logs/changed-ai-artifacts.json` (relative to RepoRoot).
30
31.PARAMETER RepoRoot
32 Repository root. Defaults to the git toplevel or this script's parent directory.
33
34.EXAMPLE
35 pwsh -File scripts/evals/Get-ChangedAIArtifact.ps1
36 Diff origin/main...HEAD and emit logs/changed-ai-artifacts.json.
37
38.EXAMPLE
39 pwsh -File scripts/evals/Get-ChangedAIArtifact.ps1 -BaseRef origin/main -HeadRef feature/branch
40 Diff a specific branch pair.
41
42.NOTES
43 Used by the PR-time eval coverage workflow to feed Test-StimulusPresence.ps1.
44#>
45
46[CmdletBinding()]
47param(
48 [Parameter(Mandatory = $false)]
49 [string]$BaseRef = 'origin/main',
50
51 [Parameter(Mandatory = $false)]
52 [string]$HeadRef = 'HEAD',
53
54 [Parameter(Mandatory = $false)]
55 [string]$OutFile,
56
57 [Parameter(Mandatory = $false)]
58 [string]$RepoRoot
59)
60
61Set-StrictMode -Version Latest
62$ErrorActionPreference = 'Stop'
63
64Import-Module (Join-Path $PSScriptRoot 'Modules/ArtifactDetection.psm1') -Force
65Import-Module (Join-Path $PSScriptRoot 'Modules/AffectedAgents.psm1') -Force
66
67function Resolve-RepoRoot {
68 [CmdletBinding()]
69 [OutputType([string])]
70 param([string]$Hint)
71
72 if (-not [string]::IsNullOrWhiteSpace($Hint)) {
73 return (Resolve-Path -LiteralPath $Hint).ProviderPath
74 }
75
76 try {
77 $gitRoot = git rev-parse --show-toplevel 2>$null
78 if ($LASTEXITCODE -eq 0 -and -not [string]::IsNullOrWhiteSpace($gitRoot)) {
79 return (Resolve-Path -LiteralPath $gitRoot.Trim()).ProviderPath
80 }
81 }
82 catch {
83 $null = $_
84 }
85
86 return (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '../..')).ProviderPath
87}
88
89function Invoke-ChangedArtifactScan {
90 <#
91 .SYNOPSIS
92 Runs git diff and classifies the results into an artifact manifest.
93
94 .OUTPUTS
95 [hashtable] `@{ baseRef; headRef; artifacts = @(...) }`.
96 #>
97 [CmdletBinding()]
98 [OutputType([hashtable])]
99 param(
100 [Parameter(Mandatory = $true)]
101 [string]$BaseRef,
102
103 [Parameter(Mandatory = $true)]
104 [string]$HeadRef,
105
106 [Parameter(Mandatory = $true)]
107 [string]$RepoRoot
108 )
109
110 Push-Location -LiteralPath $RepoRoot
111 try {
112 $diffOutput = & git diff --name-status "$BaseRef...$HeadRef" 2>&1
113 $exit = $LASTEXITCODE
114 }
115 finally {
116 Pop-Location
117 }
118
119 if ($exit -ne 0) {
120 throw "git diff failed (exit $exit): $($diffOutput -join [Environment]::NewLine)"
121 }
122
123 $lines = @($diffOutput | Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) })
124 $changes = ConvertFrom-GitDiffNameStatus -Lines $lines
125
126 $artifacts = [System.Collections.Generic.List[hashtable]]::new()
127 $changedPaths = [System.Collections.Generic.List[string]]::new()
128 foreach ($change in $changes) {
129 $record = Get-ChangedArtifactRecord -Change $change
130 if ($null -ne $record) {
131 $artifacts.Add($record)
132 }
133 if ($change.path) { $changedPaths.Add([string]$change.path) }
134 if ($change.previousPath) { $changedPaths.Add([string]$change.previousPath) }
135 }
136
137 $affectedAgents = [string[]]@()
138 if ($changedPaths.Count -gt 0) {
139 try {
140 $affectedAgents = Get-AffectedAgentSlugs -ChangedFiles $changedPaths.ToArray() -RepoRoot $RepoRoot
141 }
142 catch {
143 Write-Warning "Failed to resolve affected agents: $($_.Exception.Message)"
144 $affectedAgents = [string[]]@()
145 }
146 }
147
148 return @{
149 baseRef = $BaseRef
150 headRef = $HeadRef
151 artifacts = $artifacts.ToArray()
152 affectedAgents = [string[]]$affectedAgents
153 }
154}
155
156if ($MyInvocation.InvocationName -ne '.') {
157 $resolvedRepoRoot = Resolve-RepoRoot -Hint $RepoRoot
158
159 if ([string]::IsNullOrWhiteSpace($OutFile)) {
160 $OutFile = Join-Path -Path $resolvedRepoRoot -ChildPath 'logs/changed-ai-artifacts.json'
161 }
162 elseif (-not [System.IO.Path]::IsPathRooted($OutFile)) {
163 $OutFile = Join-Path -Path $resolvedRepoRoot -ChildPath $OutFile
164 }
165
166 try {
167 $manifest = Invoke-ChangedArtifactScan -BaseRef $BaseRef -HeadRef $HeadRef -RepoRoot $resolvedRepoRoot
168 }
169 catch {
170 Write-Error $_.Exception.Message
171 exit 2
172 }
173
174 $outDir = Split-Path -Path $OutFile -Parent
175 if (-not [string]::IsNullOrWhiteSpace($outDir) -and -not (Test-Path -LiteralPath $outDir -PathType Container)) {
176 New-Item -ItemType Directory -Path $outDir -Force | Out-Null
177 }
178
179 $manifest | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $OutFile -Encoding UTF8
180
181 Write-Host "Detected $($manifest.artifacts.Count) changed AI artifact(s) between $BaseRef and $HeadRef."
182 Write-Host "Affected agent slugs: $($manifest.affectedAgents.Count)"
183 Write-Host "Manifest: $OutFile"
184 exit 0
185}
186