Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,53 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
ai-static:
name: AI plans and unit tests
runs-on: windows-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Parse PowerShell and run hardware-independent tests
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
Get-ChildItem ./src/Workloads, ./src/tests, ./src/tools -Recurse -Filter *.ps1 |
ForEach-Object {
$tokens = $null
$errors = $null
[void][System.Management.Automation.Language.Parser]::ParseFile(
$_.FullName, [ref]$tokens, [ref]$errors)
if ($errors) { throw "$($_.FullName): $($errors -join '; ')" }
}
foreach ($id in 'ai-common','cuda','rocm','intel-ai','foundry','pytorch','llama.cpp','ollama') {
& "./src/tests/$id/unit.ps1"
}

- name: Validate report schema and manifest
shell: pwsh
run: |
python -m pip install --disable-pip-version-check --quiet pyyaml jsonschema
python -c "import json,yaml; json.load(open('src/docs/ai-workload-report.schema.json', encoding='utf-8')); yaml.safe_load(open('src/manifest.yml', encoding='utf-8-sig')); print('AI data files valid')"

- name: Exercise non-mutating AI plans and validate reports
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
New-Item -ItemType Directory -Path ai-reports -Force | Out-Null
foreach ($id in 'cuda','rocm','intel-ai','foundry','pytorch','llama.cpp','ollama') {
& "./src/Workloads/$id/install.ps1" -PlanOnly -ReportPath "./ai-reports/$id.json"
}
@'
import glob, json, jsonschema
schema = json.load(open("src/docs/ai-workload-report.schema.json", encoding="utf-8"))
for path in glob.glob("ai-reports/*.json"):
with open(path, encoding="utf-8-sig") as handle:
jsonschema.validate(json.load(handle), schema)
print("OK:", path)
'@ | python -

# ---------------------------------------------------------------------------
# Job A: parse manifest.yml → matrices for per-OS flow jobs.
# ---------------------------------------------------------------------------
Expand Down
355 changes: 350 additions & 5 deletions README.md

Large diffs are not rendered by default.

675 changes: 675 additions & 0 deletions src/Workloads/_common/ai-catalog.psd1

Large diffs are not rendered by default.

141 changes: 141 additions & 0 deletions src/Workloads/_common/ai-report.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

function Get-AiGpuInventory {
$controllers = @(Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue |
Where-Object { $_.PNPDeviceID -match '^PCI\\' -and $_.Name -notmatch '(?i)\bNPU\b' })
return @($controllers | ForEach-Object {
$vendor = if ($_.PNPDeviceID -match 'VEN_10DE' -or $_.Name -match 'NVIDIA') {
'NVIDIA'
} elseif ($_.PNPDeviceID -match 'VEN_1002' -or $_.Name -match 'AMD|Radeon') {
'AMD'
} elseif ($_.PNPDeviceID -match 'VEN_8086' -or $_.Name -match 'Intel') {
'Intel'
} elseif ($_.PNPDeviceID -match 'VEN_17CB' -or $_.Name -match 'Qualcomm|Adreno') {
'Qualcomm'
} else {
'Unknown'
}
[ordered]@{
vendor = $vendor
name = $_.Name
pnpDeviceId = $_.PNPDeviceID
driverVersion = $_.DriverVersion
}
})
}

function Get-AiNpuInventory {
return @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue |
Where-Object { $_.FriendlyName -match '(?i)(\bNPU\b|AI Boost|Neural Processing)' } |
ForEach-Object {
[ordered]@{
name = $_.FriendlyName
instanceId = $_.InstanceId
status = $_.Status
}
})
}

function New-AiWorkloadReport {
param(
[Parameter(Mandatory)] [string] $Id,
[hashtable] $Request = @{}
)
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
return [ordered]@{
schemaVersion = 1
workload = $Id
startedAtUtc = (Get-Date).ToUniversalTime().ToString('o')
completedAtUtc = $null
host = [ordered]@{
os = $os.Caption
osVersion = $os.Version
osBuild = $os.BuildNumber
architecture = (Get-DevConfigArchitecture)
powershell = $PSVersionTable.PSVersion.ToString()
gpus = @(Get-AiGpuInventory)
npus = @(Get-AiNpuInventory)
}
request = $Request
acquisitions = [System.Collections.ArrayList]::new()
phases = [System.Collections.ArrayList]::new()
acceptance = [ordered]@{}
result = [ordered]@{
ready = $false
planOnly = [bool]$(if ($Request.ContainsKey('PlanOnly')) { $Request.PlanOnly } else { $false })
fallbackUsed = $false
warnings = [System.Collections.ArrayList]::new()
blockers = [System.Collections.ArrayList]::new()
}
}
}

function Add-AiReportAcquisition {
param(
[Parameter(Mandatory)] [hashtable] $Report,
[Parameter(Mandatory)] $Entry
)
[void]$Report.acquisitions.Add($Entry)
}

function Add-AiReportPhase {
param(
[Parameter(Mandatory)] [hashtable] $Report,
[Parameter(Mandatory)] [string] $Name,
[Parameter(Mandatory)] [string] $Status,
$Evidence = $null
)
[void]$Report.phases.Add([ordered]@{ name = $Name; status = $Status; evidence = $Evidence })
}

function Complete-AiWorkloadReport {
param(
[Parameter(Mandatory)] [hashtable] $Report,
[Parameter(Mandatory)] [bool] $Ready,
[Parameter(Mandatory)] [string] $Path
)
$Report.completedAtUtc = (Get-Date).ToUniversalTime().ToString('o')
$Report.result.ready = $Ready
Write-DevConfigTextFile -Path $Path -Content ($Report | ConvertTo-Json -Depth 20)
Write-Host "AI_REPORT: $Path"
}

function Write-AiFailureReport {
param(
[Parameter(Mandatory)] [hashtable] $Report,
[Parameter(Mandatory)] [string] $Path,
[Parameter(Mandatory)] $ErrorRecord
)
[void]$Report.result.blockers.Add($ErrorRecord.Exception.Message)
Complete-AiWorkloadReport -Report $Report -Ready $false -Path $Path
}

function Get-AiDefaultReportPath {
param([Parameter(Mandatory)] [string] $Id)
return Join-Path $env:LOCALAPPDATA "DevConfig\reports\$Id-latest.json"
}

function Get-AiCatalog {
return Get-AiCatalogData
}

function Get-AiCatalogValue {
param(
[Parameter(Mandatory)] [hashtable] $Entry,
[Parameter(Mandatory)] [string] $Name
)
if ($Entry.ContainsKey($Name)) {
return $Entry[$Name]
}
return $null
}

function Set-AiAcquisitionAction {
param(
[Parameter(Mandatory)] [hashtable] $Report,
[Parameter(Mandatory)] [int] $Index,
[Parameter(Mandatory)] [string] $Action
)
$Report.acquisitions[$Index].action = $Action
}
Loading