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
39 changes: 28 additions & 11 deletions .agents/skills/build-openshell-mxc-windows/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: build-openshell-mxc-windows
description: Maintain and validate OpenShell's build-only Windows MSVC lane for x64 and ARM64. Use when working on Windows compilation, `windows:*` mise tasks, unsupported Windows compute-driver contracts, or Windows build reports. This skill does not implement Docker, Kubernetes, Podman, VM, MXC driver, policy translation, MSI, service, or supervisor runtime support on Windows.
description: Maintain and validate OpenShell's Windows MSVC lane for x64 and ARM64. Use when working on Windows compilation, `windows:*` mise tasks, unsupported Windows compute-driver contracts, MXC example wiring checks, or Windows build reports. This skill does not implement Docker, Kubernetes, Podman, VM, MXC driver, policy translation, MSI, service, or supervisor runtime support on Windows.
metadata:
internal: true
---
Expand All @@ -12,8 +12,8 @@ OpenShell repository. The Windows lane is already present in `main`; do not
treat this skill as a first-time porting recipe unless the user explicitly asks
for a new fork or a from-scratch bring-up.

The lane is build-only. It validates that OpenShell can compile and test on
Windows MSVC for the supported deliverables:
The lane validates that OpenShell can compile and test on Windows MSVC for the
supported deliverables:

- `openshell-gateway.exe`
- `openshell.exe`
Expand Down Expand Up @@ -51,6 +51,8 @@ In scope:
`openshell`.
- Running workspace tests on a native x64 or ARM64 host.
- Running focused unsupported-driver contract tests.
- Running the shipped Ollama and cloud-inference MXC examples against the
in-process `wxc` mock and a local API stub.
- Reporting test counts, skipped/gated areas, warnings, artifacts, and logs.
- Keeping Linux and macOS build paths unchanged.
- Keeping unsupported Windows compute drivers explicit and testable.
Expand Down Expand Up @@ -158,8 +160,15 @@ mise run --skip-tools windows:build:x64
mise run --skip-tools windows:build:arm64
mise run --skip-tools windows:test:x64
mise run --skip-tools windows:test:unsupported:x64
mise run --skip-tools windows:e2e:mxc:inference-mock:x64
```

Use the `arm64` form of the inference task on a native ARM64 host. It exercises
the real gateway, CLI, and shipped PowerShell runners with an in-process `wxc`
mock and local HTTP responses. It proves example wiring, request execution, and
sandbox-scoped credential propagation; it does not prove MXC, AppContainer,
filesystem, or network enforcement.

The two `windows:test:mxc-real:*` tasks are host-specific and mutually
exclusive on a single host (each rejects the other architecture -- see the
table below): run `windows:test:mxc-real:x64` on an x64 host, or
Expand Down Expand Up @@ -220,14 +229,17 @@ order:
The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache`
entries for Cargo registry and dependency target artifacts with sccache's GHA
backend for cacheable Rust compiler outputs. Failed runs also save their usable
dependency artifacts. Pull-request mirrors labeled `test:windows` run Clippy for the
Windows-supported workspace and e2e crates plus Rust tests. Pushes to `main` and
manual dispatches run the same lint and test commands in a cache-seed job,
followed by a dependent release-binary build job. The seed and PR jobs use the
same cache namespaces. Merge queues do not run this workflow. Main/manual seed
and build jobs use job-level `continue-on-error: true`; opt-in PR jobs report
failures normally. Applying the label alone does not start a run: re-run all
jobs in the current mirror push run, or push a new mirrored commit. The binaries are not uploaded or published.
dependency artifacts. Pull-request mirrors labeled `test:windows` run Clippy
for the Windows-supported workspace and e2e crates plus Rust tests, build
release binaries, and run both shipped MXC inference examples through the mock
task. Pushes to `main` and manual dispatches run the same lint and test commands
in a cache-seed job, followed by a dependent release-binary build and
mock-example job. The seed and PR jobs use the same cache namespaces. Merge
queues do not run this workflow. Main/manual seed and build jobs use job-level
`continue-on-error: true`; opt-in PR jobs report failures normally. Applying
the label alone does not start a run: re-run all jobs in the current mirror
push run, or push a new mirrored commit. The binaries are not uploaded or
published.

The ARM64 check/build steps in this x64-host contract are cross-builds. The
wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the
Expand Down Expand Up @@ -272,6 +284,8 @@ crypto dependency builds.
| `windows:test:mxc-real:x64` | Runs the serial, ignored real-`wxc-exec` integration suite natively on x64 through the MSVC wrapper. Rejects non-x64 hosts. |
| `windows:test:mxc-real:arm64` | Runs the same real-`wxc-exec` suite natively on ARM64. Rejects non-ARM64 hosts. |
| `windows:test:mxc-gb300:arm64` | Runs the required native ARM64 ProcessContainer subset and fails when a test skips. |
| `windows:e2e:mxc:inference-mock:x64` | Runs the shipped Ollama and cloud-inference demos on native x64 through the real gateway and CLI, in-process `wxc` mock, and local API stub. This is wiring evidence, not MXC enforcement evidence. |
| `windows:e2e:mxc:inference-mock:arm64` | Runs the same mock-wiring checks on native ARM64 with ARM64 release binaries. |
| `windows:qualify:mxc:gb300:contract` | Validates the required/optional/unsupported/architecture-constrained GB300 matrix. |
| `windows:qualify:mxc:gb300` | Runs the fail-closed GB300 ARM64 gate and validates hash-bound evidence. |
| `windows:artifacts` | Reports size and SHA256 for release artifacts that exist. |
Expand Down Expand Up @@ -324,6 +338,8 @@ When reporting `windows:ci`, distinguish these categories:
- Passed tests from the full ARM64 workspace test log when run on a native
ARM64 host.
- The focused unsupported-contract re-run.
- The architecture-matched MXC inference-example mock task and its explicit
wiring-only limitation.
- Explicit Cargo ignored tests, usually ignored doc examples.
- Tests hidden by `#[cfg(not(target_os = "windows"))]`; these often appear as
`running 0 tests`, not as ignored tests.
Expand Down Expand Up @@ -385,6 +401,7 @@ Every substantial Windows build run should report:
| ARM64 check/build | Pass/fail/skipped and log path. |
| Native tests | Passed/failed/ignored/filtered counts and log path for the host architecture. |
| Unsupported contracts | Which focused tests ran and their result. |
| MXC example mock E2E | Architecture, result, artifact directory on failure, and the wiring-only limitation. |
| Artifacts | Binary paths, size, and SHA256 when available. |
| Skips | Explicitly explain tests not run for a non-native architecture, unsupported driver package exclusions, and Windows cfg-gated tests. |
| Follow-ups | Only concrete follow-ups tied to failures or requested scope. |
6 changes: 6 additions & 0 deletions .github/workflows/windows-msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ jobs:
run: mise run --skip-tools windows:lint:${{ matrix.arch }}
- name: Test
run: mise run --skip-tools windows:test:${{ matrix.arch }}
- name: Build MXC example E2E binaries
run: mise run --skip-tools windows:build:${{ matrix.arch }}
- name: Run shipped MXC inference examples with mock API
run: mise run --skip-tools windows:e2e:mxc:inference-mock:${{ matrix.arch }}
- name: sccache stats
if: always()
run: sccache --show-stats
Expand Down Expand Up @@ -211,6 +215,8 @@ jobs:
cache-bin: "false"
- name: Build release binaries
run: mise run --skip-tools windows:build:${{ matrix.arch }}
- name: Run shipped MXC inference examples with mock API
run: mise run --skip-tools windows:e2e:mxc:inference-mock:${{ matrix.arch }}
- name: sccache stats
if: always()
run: sccache --show-stats
5 changes: 5 additions & 0 deletions architecture/windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ Windows validation separates source correctness from host capability:
workspace and unsupported-driver contract tests for x64 and ARM64.
- Mock MXC E2E validates gateway, CLI, driver, lifecycle, and policy wiring but
is not evidence of OS enforcement.
- Hosted Windows CI runs the shipped Ollama and cloud-inference demos against
that mock and a local compatible API. This proves both complete demo scripts,
sandbox-scoped credential propagation, and response paths without a model or
external credential, but it does not prove MXC isolation, proxy substitution,
or network enforcement.
- Real-`wxc-exec` tests validate the installed schema and selected filesystem,
UI, network, and lifecycle behavior. A probe-gated skip is useful
diagnostic output, not qualification evidence.
Expand Down
12 changes: 6 additions & 6 deletions crates/openshell-driver-mxc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pc_relay_spawner_path = ""
pc_relay_target_port = 0
# processContainer only: env-inheritance tier for the launched process
# (safest first): default is a minimal Windows CreateProcessW bootstrap set
# (SYSTEMROOT/WINDIR/PATH/COMSPEC/LOCALAPPDATA); pc_minimal_env starts from an
# (SYSTEMROOT/WINDIR/PATH/PATHEXT/COMSPEC/LOCALAPPDATA); pc_minimal_env starts from an
# EMPTY env for runtimes that need a fully curated per-sandbox environment.
pc_minimal_env = false
# processContainer only: compatibility fallback for unrestricted outbound TCP.
Expand Down Expand Up @@ -203,11 +203,11 @@ environment variable, so workloads using it must pass
`--cacert %CURL_CA_BUNDLE%` explicitly. Clients that honor the injected trust
variables consume the same per-sandbox bundle directly.

The driver seeds only `SYSTEMROOT`, `WINDIR`, `PATH`, `COMSPEC`, and
`LOCALAPPDATA` from the gateway host before applying sandbox and TLS overrides,
so required Windows bootstrap values remain available without exposing the
gateway's full environment unless the gateway explicitly opts into another
environment mode.
The driver seeds only `SYSTEMROOT`, `WINDIR`, `PATH`, `PATHEXT`, `COMSPEC`, and
`LOCALAPPDATA` from the gateway host before applying sandbox and TLS overrides.
These values provide Windows process startup and command-resolution behavior
without exposing the gateway's full environment unless the gateway explicitly
opts into another environment mode.

When governed egress is disabled, any network rule fails closed during sandbox creation.

Expand Down
4 changes: 2 additions & 2 deletions crates/openshell-driver-mxc/examples/inference.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ network_policies:
nvidia_inference:
name: nvidia-inference
endpoints:
- host: integrate.api.nvidia.com
port: 443
- host: "__INFERENCE_HOST__"
port: __INFERENCE_PORT__
protocol: rest
# Chat completions use POST.
access: read-write
Expand Down
57 changes: 51 additions & 6 deletions crates/openshell-driver-mxc/examples/run-inference-test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: Apache-2.0

# Cloud inference (T1) demo for OpenShell on MXC. PowerShell 5.1 compatible.
# -Mock runs the workload on the host through the in-process wxc shim. It is for
# CI wiring coverage only and does not provide MXC or AppContainer isolation.

[CmdletBinding()]
param(
Expand All @@ -11,8 +13,10 @@ param(
[string] $ShareDir,
[string] $Model = "nvidia/nemotron-3.5-lightning-30b-a3b",
[string] $Prompt = "Say hello in exactly five words.",
[string] $ApiUrl = "https://integrate.api.nvidia.com/v1/chat/completions",
[ValidateRange(0, 65535)] [int] $Port = 0,
[string] $SandboxName,
[switch] $Mock,
[switch] $KeepArtifacts
)

Expand Down Expand Up @@ -133,6 +137,7 @@ $success = $false
$failure = $null
$oldGatewayConfig = $env:OPENSHELL_GATEWAY_CONFIG
$oldComputeDriver = $env:OPENSHELL_COMPUTE_DRIVER
$oldMockWxc = $env:OPENSHELL_MXC_MOCK_WXC
$oldApiKey = $env:NV_API_KEY
$apiKey = $env:NV_API_KEY

Expand All @@ -142,12 +147,29 @@ try {
}
$gateway = Resolve-Executable $GatewayPath "openshell-gateway.exe" ""
$cli = Resolve-Executable $CliPath "openshell.exe" ""
$wxc = Resolve-Executable $WxcExecPath "wxc-exec.exe" "OPENSHELL_WXC_EXEC_PATH"
if ($Mock) {
# The gateway still validates that wxc_exec_path is absolute. The
# in-process mock never launches this placeholder.
$wxc = Join-Path $here "mock-wxc-exec.exe"
} else {
$wxc = Resolve-Executable $WxcExecPath "wxc-exec.exe" "OPENSHELL_WXC_EXEC_PATH"
}
foreach ($fixture in @("mxc-inference.toml", "inference.yaml")) {
if (-not (Test-Path -LiteralPath (Join-Path $here $fixture) -PathType Leaf)) {
throw "required demo fixture '$fixture' is missing beside the runner"
}
}
if ($ApiUrl.IndexOfAny([char[]]@('"', '%', '!', '&', '|', '<', '>', '^', [char] 13, [char] 10)) -ge 0) {
throw "ApiUrl contains a character that cannot be rendered safely into the sandbox command"
}
try {
$apiUri = [System.Uri] $ApiUrl
} catch {
throw "ApiUrl is not a valid absolute URI: $ApiUrl"
}
if (-not $apiUri.IsAbsoluteUri -or $apiUri.Scheme -notin @("http", "https")) {
throw "ApiUrl must be an absolute HTTP or HTTPS URI"
}
if ($Port -eq 0) { $Port = Get-AvailablePort }
$endpoint = "http://127.0.0.1:$Port"
if ([string]::IsNullOrWhiteSpace($SandboxName)) { $SandboxName = "inference-$PID" }
Expand All @@ -163,8 +185,9 @@ try {

Info "gateway: $gateway"
Info "CLI: $cli"
Info "wxc-exec: $wxc"
Info "wxc-exec: $(if ($Mock) { 'in-process mock (no MXC isolation)' } else { $wxc })"
Info "share: $ShareDir"
Info "inference API: $ApiUrl"
Info "NV_API_KEY: present (value redacted)"

$cmdExe = Join-Path $env:SystemRoot "System32\cmd.exe"
Expand All @@ -187,6 +210,8 @@ try {
$policyText = [System.IO.File]::ReadAllText((Join-Path $here "inference.yaml"))
$policyText = $policyText.Replace("__OPENSHELL_DEMO_SHARE__", $sharePolicy)
$policyText = $policyText.Replace("__CMD_EXE__", $cmdExe)
$policyText = $policyText.Replace("__INFERENCE_HOST__", $apiUri.DnsSafeHost)
$policyText = $policyText.Replace("__INFERENCE_PORT__", [string] $apiUri.Port)
Write-Utf8 $policyUsed $policyText

$requestPath = Join-Path $ShareDir "inference-request.json"
Expand All @@ -198,11 +223,21 @@ try {
Write-Utf8 $requestPath $requestJson

$probePath = Join-Path $ShareDir "inference-probe.cmd"
$probeLines = @(
"@echo off",
$tlsArgs = if ($apiUri.Scheme -eq "https") {
# Inbox curl uses Schannel and does not honor CURL_CA_BUNDLE by itself.
# Point --cacert at the public bundle staged by the governed proxy.
"`"$curlExe`" --silent --show-error --fail-with-body --ssl-no-revoke --cacert `"%CURL_CA_BUNDLE%`" --max-time 120 -D `"$headersPath`" -H `"Authorization: Bearer %NV_API_KEY%`" -H `"Content-Type: application/json`" --data-binary `"@$requestPath`" -o `"$responsePath`" `"https://integrate.api.nvidia.com/v1/chat/completions`" 2> `"$errorPath`" || exit /b 31",
'--ssl-no-revoke --cacert "%CURL_CA_BUNDLE%"'
} else {
""
}
$proxyBypassArgs = if ($apiUri.IsLoopback) {
"--noproxy `"$($apiUri.DnsSafeHost)`""
} else {
""
}
$probeLines = @(
"@echo off",
"`"$curlExe`" $proxyBypassArgs --silent --show-error --fail-with-body $tlsArgs --max-time 120 -D `"$headersPath`" -H `"Authorization: Bearer %NV_API_KEY%`" -H `"Content-Type: application/json`" --data-binary `"@$requestPath`" -o `"$responsePath`" `"$ApiUrl`" 2> `"$errorPath`" || exit /b 31",
"`"$findStrExe`" /C:`"choices`" `"$responsePath`" >nul || exit /b 32",
"echo PASS> `"$donePath`""
)
Expand All @@ -214,6 +249,11 @@ try {
$gwErrLog = Join-Path $resultDir "gateway.err.log"
$env:OPENSHELL_GATEWAY_CONFIG = $tomlUsed
$env:OPENSHELL_COMPUTE_DRIVER = "mxc"
if ($Mock) {
$env:OPENSHELL_MXC_MOCK_WXC = "1"
} else {
Remove-Item Env:OPENSHELL_MXC_MOCK_WXC -ErrorAction SilentlyContinue
}
# The credential belongs to sandbox creation, not gateway configuration.
Remove-Item Env:NV_API_KEY -ErrorAction SilentlyContinue
try {
Expand Down Expand Up @@ -280,14 +320,19 @@ try {
}
$env:OPENSHELL_GATEWAY_CONFIG = $oldGatewayConfig
$env:OPENSHELL_COMPUTE_DRIVER = $oldComputeDriver
if ([string]::IsNullOrWhiteSpace($oldMockWxc)) {
Remove-Item Env:OPENSHELL_MXC_MOCK_WXC -ErrorAction SilentlyContinue
} else {
$env:OPENSHELL_MXC_MOCK_WXC = $oldMockWxc
}
if ([string]::IsNullOrWhiteSpace($oldApiKey)) { Remove-Item Env:NV_API_KEY -ErrorAction SilentlyContinue } else { $env:NV_API_KEY = $oldApiKey }
if (-not $KeepArtifacts -and $createdShare -and $ShareDir -and (Test-Path -LiteralPath $ShareDir)) {
Remove-Item -LiteralPath $ShareDir -Recurse -Force -ErrorAction SilentlyContinue
}
}

$verdict = if ($success) { "PASS" } else { "FAIL" }
$summary = "verdict=$verdict`r`nbase=cloud-inference`r`nsandbox=$SandboxName`r`ngateway=$endpoint`r`nbackend=process_container`r`nresult=$failure`r`n"
$summary = "verdict=$verdict`r`nbase=cloud-inference`r`nmode=$(if ($Mock) { 'mock-wiring' } else { 'real-mxc' })`r`nsandbox=$SandboxName`r`ngateway=$endpoint`r`nbackend=process_container`r`nresult=$failure`r`n"
Write-Utf8 (Join-Path $resultDir "summary.txt") $summary
Write-Host "`n$summary"
Write-Host "Results: $resultDir"
Expand Down
Loading
Loading