Skip to content
Open
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
135 changes: 112 additions & 23 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,9 @@ jobs:
execution_model: ${{ steps.plan.outputs.execution_model }}
runner_image: ${{ steps.plan.outputs.runner_image }}
expected_context: ${{ steps.plan.outputs.expected_context }}
expected_os: ${{ steps.plan.outputs.expected_os }}
required_labels: ${{ steps.plan.outputs.required_labels }}
matching_runner_count: ${{ steps.plan.outputs.matching_runner_count }}
steps:
- uses: actions/checkout@v5
with:
Expand All @@ -1513,36 +1516,61 @@ jobs:
with:
phase: J2
results-dir: tests/results
- name: Resolve portable hosted Windows lane
- name: Resolve self-hosted Windows Docker lane
id: plan
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
run: |
$resultsRoot = 'tests/results/_agent/vi-history-dispatch'
New-Item -ItemType Directory -Path $resultsRoot -Force | Out-Null
$planPath = Join-Path $resultsRoot 'validate-vi-history-windows-hosted-plan.json'
pwsh -NoLogo -NoProfile -File tools/Resolve-HostedWindowsLanePlan.ps1 `
-RunnerImage 'windows-2022' `
-ContainerImage 'nationalinstruments/labview:2026q1-windows' `
-ExpectedContext 'default' `
-ExpectedOs 'windows' `
-OutputJsonPath $planPath `
-GitHubOutputPath $env:GITHUB_OUTPUT `
-StepSummaryPath $env:GITHUB_STEP_SUMMARY
$planPath = Join-Path $resultsRoot 'validate-vi-history-windows-docker-plan.json'
$requiredLabels = @(
'self-hosted',
'Windows',
'X64',
'comparevi',
'capability-ingress',
'docker-lane'
)
$requiredHealthReceipts = @()
$plannerArgs = @{
Repository = '${{ github.repository }}'
RequiredLabels = $requiredLabels
ExecutionModel = 'self-hosted-windows-docker-lane'
RunnerImage = 'self-hosted-windows-docker-lane'
ExpectedContext = 'desktop-windows'
ExpectedOs = 'windows'
Notes = @(
'Availability means an online, idle repository runner advertises the ingress plus docker-lane labels.',
'The lane may mutate Docker Desktop into the Windows engine and then restores the starting context after proof capture.'
)
Token = $env:GITHUB_TOKEN
OutputJsonPath = $planPath
GitHubOutputPath = $env:GITHUB_OUTPUT
StepSummaryPath = $env:GITHUB_STEP_SUMMARY
}
if ($requiredHealthReceipts.Count -gt 0) {
$plannerArgs.RequiredHealthReceipts = $requiredHealthReceipts
}
& tools/Resolve-SelfHostedWindowsLanePlan.ps1 @plannerArgs

- name: Append VI history Windows runner plan
shell: pwsh
run: |
if ($env:GITHUB_STEP_SUMMARY) {
$lines = @(
'### VI History Scenarios (Windows hosted plan)',
'### VI History Scenarios (Windows self-hosted Docker plan)',
'',
('- execute_lanes: `{0}`' -f '${{ needs.vi-history-scenarios-plan.outputs.execute_lanes }}'),
('- lane_available: `{0}`' -f '${{ steps.plan.outputs.available }}'),
('- lane_status: `{0}`' -f '${{ steps.plan.outputs.status }}'),
('- skip_reason: `{0}`' -f '${{ steps.plan.outputs.skip_reason }}'),
('- hosted_model: `{0}`' -f '${{ steps.plan.outputs.execution_model }}'),
('- execution_model: `{0}`' -f '${{ steps.plan.outputs.execution_model }}'),
('- runner_image: `{0}`' -f '${{ steps.plan.outputs.runner_image }}'),
'- hosted model: agents can dispatch this portable hosted Windows lane while continuing on local Linux or Windows Docker Desktop lanes.'
('- required_labels: `{0}`' -f '${{ steps.plan.outputs.required_labels }}'),
'- self-hosted docker model: validate 64-bit LabVIEW in the Windows container while the LV32 lane runs in parallel as the native host-plane reference.'
)
$lines -join "`n" | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
}
Expand All @@ -1551,20 +1579,24 @@ jobs:
if: always()
uses: actions/upload-artifact@v7
with:
name: validate-vi-history-windows-hosted-plan
path: tests/results/_agent/vi-history-dispatch/validate-vi-history-windows-hosted-plan.json
name: validate-vi-history-windows-docker-plan
path: tests/results/_agent/vi-history-dispatch/validate-vi-history-windows-docker-plan.json
if-no-files-found: error

vi-history-scenarios-windows:
needs: [smoke-gate, lint, session-index, session-index-v2-contract, vi-history-scenarios-plan, vi-history-scenarios-windows-plan]
if: needs.smoke-gate.outputs.skip != 'true' && needs.vi-history-scenarios-plan.outputs.execute_lanes == 'true' && needs.vi-history-scenarios-windows-plan.outputs.available == 'true'
runs-on: windows-2022
runs-on: [self-hosted, Windows, X64, comparevi, capability-ingress, docker-lane]
continue-on-error: true
timeout-minutes: 50
permissions:
actions: read
contents: read
env:
NI_WINDOWS_IMAGE: nationalinstruments/labview:2026q1-windows
NI_WINDOWS_LABVIEW_PATH: C:\Program Files\National Instruments\LabVIEW 2026\LabVIEW.exe
GITHUB_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
defaults:
run:
shell: pwsh
Expand All @@ -1573,13 +1605,14 @@ jobs:
run: |
if ($env:GITHUB_STEP_SUMMARY) {
$lines = @(
'### VI History Scenarios (Windows lane)',
'### VI History Scenarios (Windows self-hosted Docker lane)',
'',
('- execute_lanes: `{0}`' -f '${{ needs.vi-history-scenarios-plan.outputs.execute_lanes }}'),
('- hosted_status: `{0}`' -f '${{ needs.vi-history-scenarios-windows-plan.outputs.status }}'),
('- plan_status: `{0}`' -f '${{ needs.vi-history-scenarios-windows-plan.outputs.status }}'),
('- runner_image: `{0}`' -f '${{ needs.vi-history-scenarios-windows-plan.outputs.runner_image }}'),
('- expected_context: `{0}`' -f '${{ needs.vi-history-scenarios-windows-plan.outputs.expected_context }}'),
'- image pull budget: Windows image hydration is materially slower than the Linux lane, so keep local lanes active while hosted proof runs.'
('- required_labels: `{0}`' -f '${{ needs.vi-history-scenarios-windows-plan.outputs.required_labels }}'),
'- self-hosted 64-bit proof runs on the ingress host and pairs with the parallel LV32 lane so 32-bit host-plane drift has an immediate native reference.'
)
$lines -join "`n" | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
}
Expand All @@ -1601,7 +1634,31 @@ jobs:
with:
phase: J2
results-dir: tests/results
- name: Collect hosted Windows runner health
- name: Validate self-hosted runner label contract
shell: pwsh
run: |
$resultsRoot = Join-Path $env:GITHUB_WORKSPACE 'tests/results/local-parity/windows'
New-Item -ItemType Directory -Path $resultsRoot -Force | Out-Null
$requiredLabels = @(
'self-hosted',
'Windows',
'X64',
'comparevi',
'capability-ingress',
'docker-lane'
)
foreach ($label in $requiredLabels) {
$contractPath = Join-Path $resultsRoot ("runner-label-contract-{0}.json" -f $label)
pwsh -NoLogo -NoProfile -File tools/Assert-RunnerLabelContract.ps1 `
-Repository '${{ github.repository }}' `
-RunnerName $env:RUNNER_NAME `
-RequiredLabel $label `
-Token $env:GITHUB_TOKEN `
-OutputJsonPath $contractPath `
-GitHubOutputPath $env:GITHUB_OUTPUT `
-StepSummaryPath $env:GITHUB_STEP_SUMMARY
}
- name: Collect self-hosted Windows runner health
shell: pwsh
run: |
pwsh -NoLogo -NoProfile -File tools/Collect-RunnerHealth.ps1 `
Expand All @@ -1618,8 +1675,9 @@ jobs:
pwsh -NoLogo -NoProfile -File tools/Test-WindowsNI2026q1HostPreflight.ps1 `
-Image $env:NI_WINDOWS_IMAGE `
-ResultsDir $resultsRoot `
-ExecutionSurface 'github-hosted-windows' `
-AllowUnavailable `
-ExecutionSurface 'desktop-local' `
-ManageDockerEngine:$true `
-AllowHostEngineMutation:$true `
-OutputJsonPath $summaryPath `
-GitHubOutputPath $env:GITHUB_OUTPUT `
-StepSummaryPath $env:GITHUB_STEP_SUMMARY
Expand Down Expand Up @@ -1650,6 +1708,8 @@ jobs:
-LabVIEWPath $env:NI_WINDOWS_LABVIEW_PATH `
-ReportPath $reportPath `
-TimeoutSeconds 600 `
-ManageDockerEngine:$false `
-AllowHostEngineMutation:$false `
-RuntimeEngineReadyTimeoutSeconds 180 `
-RuntimeEngineReadyPollSeconds 5 `
-RuntimeSnapshotPath $runtimeSnapshot
Expand Down Expand Up @@ -1743,7 +1803,33 @@ jobs:
if: always() && steps.windows-preflight.outputs.windows_host_preflight_status != 'ready'
shell: pwsh
run: |
Write-Host ("::notice::Skipping hosted Windows compare because preflight status was {0} ({1})." -f '${{ steps.windows-preflight.outputs.windows_host_preflight_status }}', '${{ steps.windows-preflight.outputs.windows_host_preflight_failure_class }}')
Write-Host ("::notice::Skipping self-hosted Windows Docker compare because preflight status was {0} ({1})." -f '${{ steps.windows-preflight.outputs.windows_host_preflight_status }}', '${{ steps.windows-preflight.outputs.windows_host_preflight_failure_class }}')

- name: Restore Docker Desktop context after Windows proof
if: always()
shell: pwsh
run: |
$resultsRoot = 'tests/results/local-parity/windows'
$preflightPath = Join-Path $resultsRoot 'windows-ni-2026q1-host-preflight.json'
if (-not (Test-Path -LiteralPath $preflightPath -PathType Leaf)) {
Write-Host ("::notice::Skipping Docker Desktop restore because preflight artifact was not found at {0}" -f $preflightPath)
exit 0
}
$preflight = Get-Content -LiteralPath $preflightPath -Raw | ConvertFrom-Json -Depth 20
$restoreContext = if ($preflight.contexts.PSObject.Properties['start'] -and -not [string]::IsNullOrWhiteSpace([string]$preflight.contexts.start)) {
[string]$preflight.contexts.start
} else {
'desktop-windows'
}
$restorePath = Join-Path $resultsRoot 'runtime-manager-restore-windows.json'
pwsh -NoLogo -NoProfile -File tools/Invoke-DockerRuntimeManager.ps1 `
-ProbeScope 'windows' `
-BootstrapWindowsImage:$false `
-BootstrapLinuxImage:$false `
-RestoreContext $restoreContext `
-OutputJsonPath $restorePath `
-GitHubOutputPath '' `
-StepSummaryPath $env:GITHUB_STEP_SUMMARY | Out-Null

- name: Upload VI history scenario artifacts (Windows lane)
if: always()
Expand All @@ -1759,6 +1845,8 @@ jobs:
tests/results/local-parity/windows/container-export/**
tests/results/local-parity/windows/windows-ni-2026q1-host-preflight.json
tests/results/local-parity/windows/runtime-manager-compare-windows.json
tests/results/local-parity/windows/runtime-manager-restore-windows.json
tests/results/local-parity/windows/runner-label-contract-*.json
tests/results/local-parity/windows/_agent/runner-health.json
if-no-files-found: warn

Expand Down Expand Up @@ -1825,6 +1913,7 @@ jobs:
needs: [smoke-gate, lint, session-index, session-index-v2-contract, vi-history-scenarios-plan, vi-history-scenarios-windows-lv32-plan]
if: needs.smoke-gate.outputs.skip != 'true' && needs.vi-history-scenarios-plan.outputs.execute_lanes == 'true' && needs.vi-history-scenarios-windows-lv32-plan.outputs.available == 'true'
runs-on: [self-hosted, Windows, X64, comparevi, capability-ingress, labview-2026, lv32]
continue-on-error: true
timeout-minutes: 60
permissions:
actions: read
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve

## [Unreleased]

## [v0.6.10] - 2026-03-30

### Changed

- `Compare-VIHistory.ps1`, `Render-VIHistoryReport.ps1`, and the supporting
category helpers now preserve touch-history chronology, keep collapsed noise
pairs visible, canonicalize history labels, and emit review-order guidance so
the canonical VI-history proof answers which pair to inspect first instead of
flattening the newest meaningful change into report noise.
- `validate.yml` now treats Windows VI-history proofing as a self-hosted split:
`vi-history-scenarios-windows` runs the 64-bit Windows Docker proof on the
ingress host, while `vi-history-scenarios-windows-lv32` runs in parallel as
the native 32-bit reference lane.
- The NI Linux proof tooling and local `comparevi-history` fast loop now honor
`DOCKER_COMMAND_OVERRIDE`, making WSL-hosted `docker.exe` and wrapper-based
runtimes behave consistently during canonical proof replay.

### Added

- Chronology-aware decision guidance in the VI-history report facade,
including newest-pair status, explicit review sequence, and focus/context
bucket summaries for the canonical proof target.
- Workflow-planner coverage for the self-hosted Windows Docker split,
including regression checks for the empty health-receipt binding path.
- Local fast-loop regression coverage proving the released facade can pre-pull
the proof image through a docker override path before the hosted proof runs.

### Documentation

- Updated the release helper packet for the `v0.6.10` maintenance cut and
shifted the canonical product proof references from `DrawIcon.vi` to
`Tooling/deployment/VIP_Pre-Install Custom Action.vi`.

## [v0.6.9] - 2026-03-30

### Fixed
Expand Down
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<Deterministic>true</Deterministic>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<Version>0.6.9</Version>
<AssemblyVersion>0.6.9.0</AssemblyVersion>
<FileVersion>0.6.9.0</FileVersion>
<Version>0.6.10</Version>
<AssemblyVersion>0.6.10.0</AssemblyVersion>
<FileVersion>0.6.10.0</FileVersion>
<InformationalVersion>$(Version)+local</InformationalVersion>
<CompareViSharedSource Condition="'$(CompareViSharedSource)' == ''">package-first</CompareViSharedSource>
<CompareViSharedFallbackSource Condition="'$(CompareViSharedFallbackSource)' == ''">project</CompareViSharedFallbackSource>
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ renders, `history-report-html`). Downstream workflows and reusable snippets can
consume those keys to surface the Markdown/HTML report or to dispatch follow-up
automation without spelunking the artifacts. When the renderer is unavailable,
`Compare-VIHistory.ps1` writes a lightweight fallback report so the Markdown
output key always resolves to a readable summary.
output key always resolves to a readable summary. The stable
`history-summary-json` facade and rendered history report now also surface the
decision statement, the newest meaningful pair, and pair chronology (refs,
subjects, and commit dates) so reviewers can answer what changed, when it
changed, and whether it matters without opening raw manifests first.

Provide the optional `notify_issue` input when dispatching the workflow to post
the same summary table to a GitHub issue for stakeholders.
Expand Down
20 changes: 11 additions & 9 deletions docs/DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,8 @@ For each cut:
- Branch protection requires a linear history: use the **Squash and merge** button (or rebase-and-merge) so no merge
commits land on `develop`/`main`.
- Keep PRs focused and include the standing issue reference (`#<number>`) in the commit subject and PR description.
- Ensure required checks (`validate`, `fixtures`, `session-index`) are green before merging; rerun as needed.
- Ensure required checks (`lint`, `fixtures`, `Policy Guard (Upstream) / policy-guard`,
`vi-history-scenarios-linux`, `commit-integrity`) are green before merging; rerun as needed.
- `Validate` now computes a `validate-scope-plan` artifact before the heavy lanes fan out.
Standard `pull_request` and `merge_group` runs classify changed paths with an allow-list into:
`docs-metadata-only`, `tests-only`, `tools-policy-only`, `ci-control-plane`, `mixed-lightweight`, `compare-engine-history`,
Expand All @@ -477,14 +478,12 @@ For each cut:
`comparevi-history-bundle-certification` follows the same routing.
`vi-history-scenarios-*` runs for `compare-engine-history`, `docker-vi-history`, `mixed-runtime`, `unclassified`, and
explicit manual dispatches; the final VI-history plan still honors `history_scenario_set`.
- Hosted Windows mirror proof now lives in `Validate` as the non-required `vi-history-scenarios-windows` lane.
That lane runs on GitHub-hosted `windows-2022`, hydrates
`nationalinstruments/labview:2026q1-windows` with no repository runner dependency, and is expected to
take materially longer to pull than the Linux lane.
- If the hosted Windows runner cannot expose a Docker Windows daemon, the lane records
`windows_host_preflight_status = unavailable` and skips the heavy compare instead of poisoning
the current queue item with a non-required proof failure.
Agents can dispatch the hosted lane while continuing with the manual Linux or Windows Docker Desktop/WSL2 lanes locally.
- Windows mirror proof now lives in `Validate` as the non-required
`vi-history-scenarios-windows` lane on the self-hosted compare ingress host.
That lane validates the 64-bit Windows Docker image locally instead of burning
GitHub-hosted Windows image-pull time.
- `vi-history-scenarios-windows-lv32` runs in parallel and acts as the native 32-bit
reference for that Windows Docker proof, so 32-bit and 64-bit feedback arrive together.
- `node tools/npm/run-script.mjs priority:lane:concurrency:plan` now reads the host-plane report, host RAM budget,
and optional Docker runtime snapshot to recommend a safe concurrent hosted/manual bundle before those lanes are
dispatched.
Expand All @@ -495,6 +494,9 @@ For each cut:
the local CLI/orchestrator path, and `ready_for_review` is reserved for final hosted validation on the current head.
- `agent-review-policy` is the hosted concentrator for local review evidence and promotion validation. It should not be
used to acquire a second GitHub-side Copilot review after `ready_for_review`.
- `session-index`, `issue-snapshot`, `semver`, `agent-review-policy`, and `hook-parity`
remain valuable supporting lanes, but they are not part of the minimal merge-queue
required-check surface for `develop`.
- Run `node tools/npm/run-script.mjs priority:policy` (or `node tools/npm/run-script.mjs priority:policy:sync`) if you
need to audit merge settings locally; the command also runs during `priority:handoff-tests` and fails when
repo/branch policy drifts.
Expand Down
Loading
Loading