This note records the supported steps for exercising the Compare-VIHistory
tooling against an external repository. The canonical local-first downstream
adoption proof uses LabVIEW-Community-CI-CD/labview-icon-editor-demo on
develop, while the legacy one-off module sample below still uses
svelderrainruiz/labview-icon-editor, which is the active downstream icon
editor repository.
- Git history with the target VI available locally.
- LVCompare/LabVIEW installed (the same requirements as the action repo).
- Access to the Compare-VI tooling (
Compare-VIHistory.ps1,Compare-RefsToTemp.ps1, and supporting modules). - Hosted GitHub runner flows that use the bundle-backed NI Linux adapter also
rely on
Run-NILinuxContainerCompare.ps1plus its adjacent runtime support scripts from the same bundle.
The release pipeline publishes an immutable CompareVI.Tools zip bundle on
each tagged release. For cross-repo usage, prefer downloading that asset
instead of checking out this repository.
Treat the backend release tag as the authoritative pin. The bundle's embedded PowerShell manifest version is informative, but the supported consumer contract is the reviewed release tag plus its published checksum/provenance.
-
Download the pinned release asset
$tag = 'v1.0.0' $asset = 'CompareVI.Tools-v<release-version>.zip' $uri = "https://github.com/LabVIEW-Community-CI-CD/compare-vi-cli-action/releases/download/$tag/$asset" Invoke-WebRequest -Uri $uri -OutFile $asset
-
Verify the archive
Download the matching
SHA256SUMS.txtfrom the same release and confirm the hash for the zip before extracting it. -
Extract and inspect metadata
Expand-Archive -Path .\CompareVI.Tools-v<release-version>.zip -DestinationPath .\comparevi-tools Get-Content .\comparevi-tools\CompareVI.Tools-v<release-version>\comparevi-tools-release.json
The embedded metadata records the module version, repository source, source ref/tag, source SHA, the file closure for the bundle, and the supported downstream consumer contracts under
consumerContract.historyFacadeandconsumerContract.hostedNiLinuxRunner.versionContractis the authoritative interpretation layer for release identity. TreatversionContract.authoritativeConsumerPinas the immutable consumer pin for the bundle. WhenversionContract.toolsIterationis present,versionContract.baseSemverandversionContract.stableFamilyTagonly describe the compatibility family; they do not supersede the immutablevX.Y.Z-tools.Nrelease identity. -
Import the module from the extracted bundle
Import-Module .\comparevi-tools\CompareVI.Tools-v<release-version>\tools\CompareVI.Tools\CompareVI.Tools.psd1 -Force
-
Run the facade helper
Set-Location labview-icon-editor $history = Invoke-CompareVIHistoryFacade ` -TargetPath "resource/plugins/NIIconEditor/Miscellaneous/Settings Init.vi" ` -Mode attributes,front-panel,block-diagram ` -RenderReport ` -FailOnDiff:$false ` -InvokeScriptPath ..\comparevi-tools\CompareVI.Tools-v<release-version>\tools\Invoke-LVCompare.ps1 $history.observedInterpretation.coverageClass $history.execution.requestedModes $history.execution.executedModes $history.reports.markdownPath
This path replaces whole-repository acquisition for module consumers while keeping the integration pinned to a reviewed release tag. The returned facade object is the supported downstream summary surface: requested/executed modes, coverage and outcome interpretation, report paths, and per-mode tallies without the raw backend comparison payloads.
comparevi-tools-release.json now also exposes a first-class capability record
at consumerContract.capabilities.viHistory.
Use that capability record when a downstream distributor such as
LabviewGitHubCiTemplate needs to stamp vi-history support into generated
repositories without copying compare's internal control plane.
The capability contract tells downstream distributors:
- this repository is the upstream producer for
vi-history - the distribution model is the immutable release bundle
- the authoritative downstream pin lives at
versionContract.authoritativeConsumerPin - the template should resolve the capability's consumer surfaces from the
referenced contract paths inside the same
comparevi-tools-release.jsonpayload:consumerContract.historyFacadeconsumerContract.localRuntimeProfilesconsumerContract.localOperatorSessionconsumerContract.diagnosticsCommentRendererconsumerContract.hostedNiLinuxRunner
- the template Docker profile should resolve the Producer-published Docker
image contract from
consumerContract.capabilities.dockerProfile.authoritativeImageContractSource, which currently points atconsumerContract.dockerImageContractinside the same immutablecomparevi-tools-release.jsonpayload
That keeps the producer/distributor boundary clean:
compare-vi-cli-actionpublishes and versions the capabilityLabviewGitHubCiTemplatedistributes the capability- generated repositories consume the pinned release surface instead of vendoring compare internals
The autonomous governor portfolio also treats that producer/distributor link as
an explicit dependency. Compare remains the current owner until the signed
producer-native CompareVI.Tools release is ready, and only then does the
portfolio hand off the next-owner route to LabviewGitHubCiTemplate.
For hosted GitHub runner diagnostics, use the same extracted bundle root as
COMPAREVI_SCRIPTS_ROOT and resolve the NI Linux runner from
tools/Run-NILinuxContainerCompare.ps1. Keep its adjacent support scripts
(Assert-DockerRuntimeDeterminism.ps1 and
Compare-ExitCodeClassifier.ps1) in the extracted bundle; do not copy the
runner by itself.
When a hosted or local smoke lane needs extra dependencies or config inside the
NI Linux image, prefer runtime injection over starting multiple short-lived
containers. Run-NILinuxContainerCompare.ps1 now accepts either the low-level
runtime injection switches or an explicit bootstrap contract
(-RuntimeBootstrapContractPath):
-RuntimeInjectionScriptPathfor a bash fragment that is sourced inside the running container before LabVIEW CLI/Xvfb discovery.-RuntimeInjectionEnvfor additionalKEY=VALUEpairs passed into that same container execution.-RuntimeInjectionMountfor extrahostPath::/container/pathmounts that carry config or dependency payloads.branchRefandmaxCommitCountinside the bootstrap contract so consumers can bind the VI-history smoke run to a specific source branch and fail early when that branch drifts past the agreed history window.viHistoryinside the bootstrap contract when the container should derive the compare pair from a mounted git repo instead of relying on host-supplied-BaseVi/-HeadVi. The explicit block accepts:repoPathtargetPathresultsPath- optional
baselineRef - optional
maxPairs
Because the injection script is sourced in the same bash session that later
invokes the LabVIEW CLI, sequential bootstrap steps such as exporting config,
amending PATH, unpacking sidecar tools, or verifying mounted payloads all run
inside one container start before the compare operation executes.
When the explicit viHistory block is present, the bootstrap script now:
- resolves the requested branch inside the mounted repo
- enforces the branch budget against divergence from
develop(when present) - materializes a bounded first-parent pair plan inside the container work root
- emits
suite-manifest.json,history-context.json, andvi-history-bootstrap-receipt.jsonunder the mounted results directory - hands that plan to the same in-container compare command, so one container session can walk multiple sequential VI-history pairs and still emit a single bounded suite bundle
For VI-history consumers, the host-side fast loop enforces the commit cap before
starting Docker, using divergence from develop as the budget when that
baseline exists. The bootstrap script enforces the same cap again inside the
container when COMPAREVI_VI_HISTORY_BRANCH_COMMIT_COUNT is provided. That
keeps oversized feature branches from silently turning the smoke lane into a
full-history replay while leaving the baseline develop lane usable.
pwsh -NoLogo -NoProfile -File tools/Run-NILinuxContainerCompare.ps1 `
-RuntimeBootstrapContractPath .\runtime-bootstrap.json{
"schema": "ni-linux-runtime-bootstrap/v1",
"mode": "vi-history-suite-smoke",
"branchRef": "consumer/feature-history",
"maxCommitCount": 64,
"scriptPath": "tools/NILinux-VIHistorySuiteBootstrap.sh",
"viHistory": {
"repoPath": ".",
"targetPath": "fixtures/vi-attr/Head.vi",
"resultsPath": "tests/results/local-parity/linux-smoke/vi-history-suite/results",
"baselineRef": "develop",
"maxPairs": 2
}
}Treat LabVIEW-Community-CI-CD/labview-icon-editor-demo as the first
documented downstream consumer for the local-first VI history loop.
- Backend pin: reviewed
compare-vi-cli-actionrelease tag pluscomparevi-tools-release.json - Facade pin: immutable
comparevi-historyrelease used by the consumer workflows and local-review scripts - Downstream repo:
LabVIEW-Community-CI-CD/labview-icon-editor-demo - PR workflow target branch:
develop - Downstream maintainer doc:
docs/comparevi-history-diagnostics.md - Representative VI:
Tooling/deployment/VIP_Post-Install Custom Action.vi
For that repo, the supported local maintainer loop is:
- refine locally with
dev-fast - repeat locally with
warm-devwhen iteration is high-frequency - run
proofbefore opening the PR - use GitHub CI only for publication and trust-boundary proof
Example local review from a comparevi-history checkout:
pwsh -NoLogo -NoProfile -File <comparevi-history-root>\scripts\Invoke-CompareVIHistoryLocalReview.ps1 `
-ConsumerRepositoryRoot <labview-icon-editor-demo-root> `
-ViPath 'Tooling/deployment/VIP_Post-Install Custom Action.vi'Example repeated-turn warm runtime:
pwsh -NoLogo -NoProfile -File <comparevi-history-root>\scripts\Invoke-CompareVIHistoryLocalReview.ps1 `
-ConsumerRepositoryRoot <labview-icon-editor-demo-root> `
-ViPath 'Tooling/deployment/VIP_Post-Install Custom Action.vi' `
-Profile warm-dev `
-WarmRuntimeDir tests/results/local-review/runtime `
-BaseRef develop `
-HeadRef HEADExample local proof before opening the PR:
pwsh -NoLogo -NoProfile -File <comparevi-history-root>\scripts\Invoke-CompareVIHistoryLocalReview.ps1 `
-ConsumerRepositoryRoot <labview-icon-editor-demo-root> `
-ViPath 'Tooling/deployment/VIP_Post-Install Custom Action.vi' `
-Profile proof `
-BaseRef develop `
-HeadRef HEADKeep the checked-in GitHub workflows in the downstream repo as the publication surface. The local-first loop is for reviewer/runtime refinement before the PR exists, not a replacement for the published PR diagnostics.
Use this exact sample when you need a documented cross-repo consumer reference:
- Backend pin: reviewed
compare-vi-cli-actionrelease tag pluscomparevi-tools-release.json - Downstream repo:
svelderrainruiz/labview-icon-editor - Target VI:
resource/plugins/NIIconEditor/Miscellaneous/Settings Init.vi - Recommended modes:
attributes,front-panel,block-diagram - Supported module entry point:
Invoke-CompareVIHistoryFacade - Runtime summary artifact:
history-summary.json
For reviewer-facing diagnostics surfaces, prefer explicit scoped modes instead
of aggregate lanes such as default or full. The embedded bundle metadata
also advertises
consumerContract.diagnosticsCommentRenderer.entryScriptPath = tools/New-CompareVIHistoryDiagnosticsBody.ps1,
which comparevi-history consumers can resolve from the extracted tooling root
or workflow tooling-path output instead of copying inline PowerShell comment
renderers.
Cross-repo maintainers should now separate local refinement speed from canonical proof:
proof- image:
nationalinstruments/labview:2026q1-linux - purpose: release parity and CI truth
- image:
windows-mirror-proof- image:
nationalinstruments/labview:2026q1-windows - purpose: repeatable headless Windows mirror proof on a Windows host before any host-native LabVIEW 2026 32-bit promotion
- image:
dev-fast- image:
comparevi-vi-history-dev:local - purpose: faster cold local refinement with a mounted working tree and prewarmed dependencies
- image:
warm-dev- same local dev image
- purpose: repeated local turns against one long-lived Docker runtime
This split is deliberate:
comparevi-toolsstays the non-LV/tools image only- the local dev image is not published in the first slice
- CI and release workflows keep advertising only the canonical NI image
windows-mirror-proofis proof-only in this first slice and stays pinned tonationalinstruments/labview:2026q1-windows
Use the backend runtime substrate from this repo:
node tools/npm/run-script.mjs history:local:build-dev-image
node tools/npm/run-script.mjs history:local:refine -- `
-BaseVi fixtures/vi-attr/Base.vi `
-HeadVi fixtures/vi-attr/Head.vi `
-HistoryTargetPath fixtures/vi-attr/Head.vi
node tools/npm/run-script.mjs history:local:proof -- `
-BaseVi fixtures/vi-attr/Base.vi `
-HeadVi fixtures/vi-attr/Head.vi `
-HistoryTargetPath fixtures/vi-attr/Head.vi
node tools/npm/run-script.mjs history:local:windows-mirror:proof -- `
-BaseVi fixtures/vi-attr/Base.vi `
-HeadVi fixtures/vi-attr/Head.vi `
-HistoryTargetPath fixtures/vi-attr/Head.vi
node tools/npm/run-script.mjs history:local:warm-runtime -- `
-RepoRoot . `
-ResultsRoot tests/results/local-vi-history/warm-dev `
-RuntimeDir tests/results/local-vi-history/runtime/warm-devDirect PowerShell entrypoints are:
tools/Build-VIHistoryDevImage.ps1tools/Invoke-VIHistoryLocalRefinement.ps1tools/Invoke-VIHistoryLocalOperatorSession.ps1tools/Manage-VIHistoryRuntimeInDocker.ps1tools/Test-WindowsNI2026q1HostPreflight.ps1tools/Run-NIWindowsContainerCompare.ps1
The local receipts are:
comparevi/local-refinement@v1comparevi/local-runtime-state@v1comparevi/local-runtime-health@v1comparevi/local-refinement-benchmark@v1comparevi/local-operator-session@v1
The cross-plane budget receipt layers on top of those timing artifacts:
vi-history/cross-plane-performance-budget@v1- default JSON path:
tests/results/_agent/vi-history/cross-plane-performance-budget.json - companion Markdown summary:
tests/results/_agent/vi-history/cross-plane-performance-budget.md
Run the budget after Linux proof and Windows mirror proof receipts exist:
node tools/npm/run-script.mjs env:labview:2026:host-planes
node tools/npm/run-script.mjs priority:vi-history:budget -- `
--linux-receipt tests/results/local-vi-history/proof/local-refinement.json `
--windows-receipt tests/results/local-vi-history/windows-mirror-proof/local-refinement.json `
--host-plane-report tests/results/_agent/host-planes/labview-2026-host-plane-report.jsonAdd --shadow-receipt <path> when a host-native 32-bit VI History lane emits a
timing receipt for the same workload. The budget report:
- enforces the Windows budget at
<= 1.2xLinux wall-clock time - records when a justification was supplied for an over-budget Windows result
- warns when shadow 32-bit timing is missing or when it is not acting as a throughput accelerator against the measured container planes
- writes a PR-comment-ready Markdown summary next to the JSON report
Treat that shadow receipt as acceleration evidence only:
- the authoritative proof planes remain the Linux and Windows image-backed lanes
- host-native 32-bit stays manual and opt-in
- hosted CI must not promote host-native 32-bit into a required proof surface
Windows mirror proof also records host/image evidence under the local refinement and operator-session receipts:
runtimePlane = windows-mirrorwindowsMirror.hostPreflight.pathwindowsMirror.compare.reportPathwindowsMirror.compare.capturePathwindowsMirror.compare.runtimeSnapshotPath
Those receipts are the contract comparevi-history should consume when it adds
profile-aware local-review and local-proof surfaces on top of the backend
runtime planes.
Use the operator-session contract when one local command needs to compose the runtime plane with a downstream review hook. The session manifest records:
- the underlying local-refinement receipt
- benchmark selection and warm-runtime artifacts
- optional downstream review output paths such as a review bundle, workspace, preview manifest, or review receipt
- the final composed session status
The session wrapper sets stable environment variables for downstream review hooks, including:
COMPAREVI_LOCAL_REFINEMENT_RECEIPT_PATHCOMPAREVI_LOCAL_REFINEMENT_BENCHMARK_PATHCOMPAREVI_LOCAL_REFINEMENT_RESULTS_ROOTCOMPAREVI_LOCAL_OPERATOR_SESSION_PATHCOMPAREVI_REVIEW_RECEIPT_PATHCOMPAREVI_REVIEW_BUNDLE_PATHCOMPAREVI_REVIEW_WORKSPACE_HTML_PATHCOMPAREVI_REVIEW_WORKSPACE_MARKDOWN_PATHCOMPAREVI_REVIEW_PREVIEW_MANIFEST_PATHCOMPAREVI_REVIEW_RUN_PATH
For extracted tooling bundles, prefer the module-level stable surface instead of hard-coding backend script paths:
Invoke-CompareVIHistoryLocalRefinementFacadeInvoke-CompareVIHistoryLocalOperatorSessionFacade- consumer contract:
comparevi-tools/local-refinement-facade@v1andcomparevi-tools/local-operator-session-facade@v1
For a downstream maintainer, the intended loop is now:
- refine a VI-history change locally with
dev-fast - repeat locally with
warm-devwhen the turn frequency is high - run
proofbefore opening the PR - use GitHub CI only for publication and trust-boundary proof
That keeps sticky comment, preview publication, and trust-split validation in GitHub while moving parser/renderer/runtime iteration off the PR churn path.
-
Clone the target repo
git clone https://github.com/svelderrainruiz/labview-icon-editor.git
-
Import the module
From the cloned
compare-vi-cli-actionrepository run:Import-Module (Join-Path $PWD 'tools/CompareVI.Tools/CompareVI.Tools.psd1') -Force
The module exposes both
Invoke-CompareVIHistoryandInvoke-CompareVIHistoryFacade, and redirects all helper lookups back to this repository. -
Run the history helper
Set-Location labview-icon-editor
Invoke-CompareVIHistory -TargetPath "resource/plugins/NIIconEditor/Miscellaneous/Settings Init.vi"
-SourceBranchRef "feature/history-source" -MaxBranchCommits 64
-RenderReport -FailOnDiff:$false
-InvokeScriptPath ..\compare-vi-cli-action\tools\Invoke-LVCompare.ps1
Add `-MaxPairs <n>` when you need to cap the number of commit pairs in the cross-repo run.
Add `-SourceBranchRef` plus `-MaxBranchCommits` when the consumer needs an
explicit budget against branch sprawl before the history suite runs.
- Outputs land in `tests/results/ref-compare/history/` inside the cloned
repo (`history-report.md`, `history-report.html`, manifest JSON, etc.).
- Works for any VI path with commit history; use `-StartRef` if you need to
anchor to an older commit.
- When LabVIEW is not available locally, point `-InvokeScriptPath` at a
testing stub so the pipeline still emits manifests and reports.
### Reference fixtures
The repository ships a synthetic snapshot under
`fixtures/cross-repo/labview-icon-editor/settings-init/` (Markdown, HTML, and
JSON manifests). `tests/CompareVI.CrossRepo.Fixtures.Tests.ps1` validates that
the recorded metadata bucket counts (2 entries in the `metadata` bucket) stay
in sync with the documentation. Use the fixture as a template when capturing
new cross-repo runs.
## Offline corpus harness
For the seeded offline real-history corpus path added under issue `#894`, use
[`Offline-RealHistory-Corpus.md`](./Offline-RealHistory-Corpus.md). That flow
wraps `Compare-VIHistory` with the NI Windows container bridge and writes
generated evidence under `tests/results/offline-real-history/` instead of
committing bulky raw reports. Issue `#895` adds the deterministic committed
subset at `fixtures/real-history/offline-corpus.normalized.json`, which is
rebuilt from the checked-in seed fixture and tiny capture summaries instead of
from local run artifacts.
## Observations / gaps
- With `CompareVI.Tools` we can reuse `Compare-VIHistory` and
`Compare-RefsToTemp` without copying scripts into the target repository.
- The published `CompareVI.Tools` zip bundle now covers the module acquisition
path without cloning this repository.
- The bundle now also carries the hosted NI Linux runner surface needed by
comparevi-history consumers that stage `nationalinstruments/labview:2026q1-linux`
on hosted runners.
- A reusable workflow/facade is still useful for the cleanest `uses:` UX.
## Packaging decision (2025-10-31)
For issue #527 we will proceed with the **PowerShell module** approach:
- Create a module (working name `CompareVI.Tools`) that exports
`Compare-VIHistory`, `Compare-RefsToTemp`, bucket metadata helpers, and the
vendor resolver.
- Publish the module as part of the compare-vi-cli-action release process as a
pinned zip bundle.
- Provide a simple wrapper script so GitHub workflows can import the module and
invoke `Compare-VIHistory` without copying files.
- Generate a zip bundle from the release pipeline for consumers that prefer
fixed artifacts.
## Next steps (tracked by issue #527)
- **Packaging options**
- *PowerShell module bundle*: publish `Compare-VIHistory`,
`Compare-RefsToTemp`, bucket metadata, vendor resolvers, and compare
engine dependencies as a self-contained `CompareVI.Tools` zip asset on each
release. External repos download/unpack the bundle and import the module
directly.
- *Reusable workflow/composite action*: wrap the helper in a GitHub Action
that accepts repo+VI inputs and runs the history capture on a trusted
runner.
- **Automation gaps to close**
- Keep the release bundle metadata and verification guidance aligned with the
published asset names.
- Provide a sample workflow (e.g., `vi-history-cross-repo.yml`) that
downloads the helper and runs it against a supplied repo/ref.
- Clarify access requirements (SAML, LFS, large history impacts) in the docs.
- Add validation that warns when the target VI has no history (e.g., history
report shows only `_missing-base_` rows).