Skip to content

Emit errors and warnings as structured ScriptResponse JSON - #1482

Merged
Elliot (theelliotm) merged 35 commits into
mainfrom
user/emichlin/cross-backend-error-contract
Oct 29, 2026
Merged

Elliot (theelliotm) merged 35 commits into
mainfrom
user/emichlin/cross-backend-error-contract

Conversation

@theelliotm

@theelliotm Elliot (theelliotm) commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

📖 Description

Executors now report failures and warnings as structured JSON instead of prose, so a caller can branch on a code rather than match backend-specific text.

  • Errors: each failure is one {"error":{"code","message"}} line on stderr. The exit code follows the code.
  • Warnings: ScriptResponse gains warnings (Option<Box<Vec<String>>>, which keeps the struct within the 128-byte result_large_err limit; a size test guards this). Executors write each warning as a {"warning":{"message"}} line on stderr.
  • Executor setup paths: wxc and lxc errors, including --setup-*, emit typed envelopes.
Code Who can fix it Exit
policy_validation the request 1
backend_unavailable the host -1
backend_error the runtime, during an accepted run -1
malformed_request, unsupported_containment, other phase codes the request 1

SDK compatibility: sites where a new code would break SDK v1 callers keep their v1 code. Each has a // SDK v2: comment naming its intended code. They are listed in docs/development/plans/sdk-v2-error-codes.md and tracked in #1595. The new codes apply everywhere else, for example Hyperlight, WSLC, Windows Sandbox and IsolationSession inherited stdio.

Out of scope:

  • warnings in the Rust, .NET and Node SDK result types.
  • Prose that backends still print alongside the envelope.
  • A result channel separate from the workload's stderr (Separate MXC diagnostics from the workload's stderr #1596). Envelopes on stderr are diagnostics; the exit code and a held ScriptResponse are the authoritative result.

🔗 References

Resolves #612

🔍 Validation

Local, Windows 11 ARM64, after merging main:

Command Result
cargo fmt --all -- --check passed
cargo clippy -p mxc-sdk -p wxc -p lxc --all-targets --features "mxc-sdk/wslc mxc-sdk/isolation_session" -- -D warnings passed
cargo clippy -p mxc-sdk --all-targets --target x86_64-unknown-linux-gnu -- -D warnings passed
cargo clippy -p mxc-sdk --all-targets --target aarch64-apple-darwin -- -D warnings passed
cargo test -p mxc-sdk --lib --features "wslc isolation_session" 2985 passed, 70 failed (local sandbox: registry, telemetry consent, sockets, PSEC; same set as main)
cargo test -p wxc 156 passed, 2 failed (local hard-link restriction; same as main)

Earlier scheduled validation run: 38377047465. It fixed the [P8d]/[P8e] hostLoopback failures. Its debian13-bubblewrap failure is pre-existing on main.

Not run locally: host suites under tests/scripts/ (Bubblewrap, LXC, Seatbelt, WSLC, IsolationSession). They need a new scheduled run on this revision.

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task
Microsoft Reviewers: Open in CodeFlow

Elliot (theelliotm) and others added 7 commits October 12, 2026 16:40
Entry-point failures printed a bare line and exited 1, which a caller could
not tell apart from a typed policy rejection, and warnings were written as
unstructured stderr text.

Classify every wxc-exec failure by whose problem it is, emit it as a typed
JSON envelope, and carry warnings on ScriptResponse.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Backends reported failures inconsistently: some flattened everything to a
generic backend error, the Bubblewrap and LXC runners set no failure phase at
all, and WSLC rejections exited -1 while ProcessContainer rejections exited 1.
A caller could not tell a refused request from an unavailable host, and the
PowerShell suites had to match on prose banners to find out.

Classify each failure by whose problem it is and derive both the wire code and
the exit code from that:

  the request is at fault      Rejected             policy_validation    exit 1
  the host is at fault         BackendUnavailable   backend_unavailable  exit -1
  the runtime faulted mid-run  other phases         backend_error        exit -1

Every backend now sets a phase, and `ScriptResponse::failure_exit_code` is the
single place the exit code comes from.

Two consequences are worth calling out. A capability the host's Windows build
cannot represent -- `enumeratePaths`, `hostLoopback='allow'` -- now reaches the
wire as `policy_validation`, because dropping the field runs; it used to be
reported as an unavailable backend, which told the caller to give up on the
host. Conversely, a backend this build did not compile in now reports
`backend_unavailable` from the one-shot path too, matching what the state-aware
path already returned, because only a rebuilt executor can serve it.

Add an optional `warnings` array to `ScriptResponse` so the executors stop
interleaving advisory diagnostics with the error channel. It is boxed to keep
the struct under clippy's `result_large_err` threshold, and omitted from the
wire when a run produced none.

Fixes #612

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The P14b and P14c behavioural assertions gate on the `nativeCaptureAvailable`
probe, which answers whether the Learning Mode API is present. That is not the
same question as whether it is implemented: on a host whose exports resolve but
return E_NOTIMPL, the probe says the provider is usable, both runs then fail
before an output path exists, and P14c reports three failures on empty strings.

The runtime already classifies that outcome correctly -- `is_api_unavailable()`
maps it to `BackendUnavailable`, which reaches stderr as a typed
`backend_unavailable` envelope. Gate on what the run reported rather than on
the probe alone, via a shared `Test-BackendUnavailable`. Keying on the typed
code covers every reason a host cannot provide capture, not just the ones a
probe knows to ask about.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dispatch runs after the policy is accepted, so a failure there is the host
failing to build the tier the policy asked for, not a verdict on the request.
Classifying fallback and capture-provider failures as policy_validation made
wxc-exec log them as unsupported_field_for_backend and exit 1, which the
process-container suites read as a validation rejection of a config they
require to be accepted. Only a SID that could not be derived or ACEs that
could not be applied keep their own codes.

Update the harnesses that encoded the previous exit codes: WSLC and isolation
session rejections now exit 1, and the two process-container dispatch refusals
now exit -1. Match the Bubblewrap cwd advisory piecewise, since the advisory is
carried in a JSON warning envelope that escapes the quotes around the path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tier

Two different failures share DispatchError. A field the selected tier cannot
represent names that field and is documented as a rejection, so collapsing it
into backend_unavailable made hostLoopback=allow and enumeratePaths exit -1,
which the suites read as 'accepted and silently dropped' -- the one outcome
P8d and P8e exist to rule out. A tier that could not be built at all, or a
missing denial-capture provider, stays backend_unavailable: no tier existed to
judge the policy against.

Restore the enumeratePaths harness to exit 1 to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Audit finalization raised its cleanup diagnostics as bare stderr prose, so a
caller had to scrape them while every other warning arrived as a JSON
envelope. They now travel on the response and are emitted with the rest.

The finalization failure arm hard-coded exit -1 regardless of how the backend
had already classified the run, which could pair a rejection envelope with an
exit status that contradicts it. Deriving the status from the failure phase
keeps the two in agreement, and the appended message reaches stderr through
the error envelope rather than a separate prose line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 18:45
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Failure classification remains inconsistent across validation and streaming paths, and the Seatbelt availability check can reject valid default executions.

5 open findings
What changed in this PR

Standardizes backend failures by responsible party and emits machine-readable error/warning envelopes.

Changes:

  • Maps policy, host availability, and runtime failures to consistent codes and exits.
  • Adds structured warning handling to ScriptResponse.
  • Updates backend implementations, tests, and documentation.
File Description
tests/​scripts/​run_wslc_all_tests.ps1 Updates rejection exit expectations.
tests/​scripts/​run_processcontainer_filesystem_enumerate_test.ps1 Clarifies enumeration rejection behavior.
tests/​scripts/​run_processcontainer_dacl_disabled_test.ps1 Expects unavailable-tier semantics.
tests/​scripts/​run_processcontainer_capture_denials_test.ps1 Skips assertions on unavailable hosts.
tests/​scripts/​run_isolation_session_tests.ps1 Updates policy rejection exits.
tests/​scripts/​run_bwrap_cwd_advisory_test.sh Validates structured warning output.
tests/​scripts/​lib/​WinProcessContainer.Common.ps1 Adds typed availability detection.
src/​tools/​wxc/​src/​main.rs Emits typed errors and warnings.
src/​tools/​mxc_darwin/​src/​main.rs Adds structured executor diagnostics.
src/​tools/​lxc/​src/​main.rs Adds structured executor diagnostics.
src/​mxc-sdk/​src/​core/​mxc_engine/​run.rs Classifies resolution failures.
src/​mxc-sdk/​src/​core/​mxc_engine/​error.rs Converts SDK errors back to wire errors.
src/​mxc-sdk/​src/​core/​mxc_engine/​dispatch.rs Preserves dispatcher classifications.
src/​mxc-sdk/​src/​core/​mxc_common/​script_runner.rs Adds shared envelope emitters.
src/​mxc-sdk/​src/​core/​mxc_common/​mxc_error.rs Centralizes error exits and serialization.
src/​mxc-sdk/​src/​core/​mxc_common/​models.rs Adds warnings and failure helpers.
src/​mxc-sdk/​src/​core/​mxc_common/​error.rs Classifies common errors.
src/​mxc-sdk/​src/​core/​mxc_common/​config_parser.rs Converts parse failures to typed errors.
src/​mxc-sdk/​src/​backends/​wslc/​common/​wsl_container_runner.rs Updates rejection assertions.
src/​mxc-sdk/​src/​backends/​wslc/​common/​error.rs Derives exits from failure phase.
src/​mxc-sdk/​src/​backends/​windows_sandbox/​lifecycle/​state_aware.rs Classifies unavailable sandbox hosts.
src/​mxc-sdk/​src/​backends/​windows_sandbox/​lifecycle/​error.rs Separates host and policy failures.
src/​mxc-sdk/​src/​backends/​seatbelt/​common/​seatbelt_runner.rs Classifies Seatbelt failures.
src/​mxc-sdk/​src/​backends/​process_container/​common/​dispatcher.rs Classifies dispatch failures.
src/​mxc-sdk/​src/​backends/​process_container/​common/​base_container_runner.rs Distinguishes unsupported host baselines.
src/​mxc-sdk/​src/​backends/​process_container/​common/​appcontainer_runner.rs Classifies BFS and launch failures.
src/​mxc-sdk/​src/​backends/​nanvix/​runner/​mod.rs Splits policy, availability, and runtime errors.
src/​mxc-sdk/​src/​backends/​lxc/​common/​lxc_runner.rs Adds detailed LXC failure phases.
src/​mxc-sdk/​src/​backends/​lxc/​common/​availability.rs Adds uncached execution-time probing.
src/​mxc-sdk/​src/​backends/​isolation_session/​common/​sandbox.rs Preserves typed launch classifications.
src/​mxc-sdk/​src/​backends/​isolation_session/​common/​one_shot.rs Classifies lifecycle and process exits.
src/​mxc-sdk/​src/​backends/​isolation_session/​common/​error.rs Maps backend errors to response phases.
src/​mxc-sdk/​src/​backends/​hyperlight/​common/​mod.rs Splits Hyperlight failure categories.
src/​mxc-sdk/​src/​backends/​bubblewrap/​common/​bwrap_runner.rs Classifies Bubblewrap failures.
docs/​development/​architecture/​versioning.md Documents error and warning contracts.
docs/​development/​architecture/​container-lifecycle.md Documents exit-code behavior.
docs/​development/​architecture/​backends/​isolation-session/​state-aware-rust.md Updates IsolationSession semantics.
docs/​backends/​seatbelt/​seatbelt-backend.md Documents Seatbelt failures.
docs/​backends/​lxc/​lxc-backend.md Adds LXC troubleshooting guidance.
docs/​backends/​hyperlight/​hyperlight-backend.md Adds Hyperlight failure guidance.
docs/​backends/​bwrap/​bubblewrap-backend.md Adds Bubblewrap failure guidance.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/mxc-sdk/src/core/mxc_engine/run.rs Resolved
@theelliotm Elliot (theelliotm) changed the title Classify every backend failure by who can act on it Emit errors and warnings as structured ScriptResponse JSON Oct 13, 2026
@theelliotm Elliot (theelliotm) self-assigned this Oct 13, 2026
Three surfaces reached the same condition by a different route and reported
it differently.

Shared request validation returned a runtime error, so an empty script was a
rejection through `validate` but a `backend_error` through `spawn`, which is
the path callers actually take. Both shared checks judge the request, so they
are rejections. `enumeratePaths` on a backend that cannot represent it now
also matches how the process-container dispatcher classifies the same field.

The streaming and PTY arms for a backend this build omits returned
`unsupported_containment`, while run-to-completion resolution called the same
build and host `backend_unavailable`. The code no longer depends on which
operation the caller chose. Arms for a backend belonging to another operating
system are untouched.

Seatbelt probed for Apple's sandbox CLI on every launch, but only the `Open`
method shells out to it; `Exec`, the default, applies the profile through
`sandbox_init`. A host without the CLI no longer loses the launch method that
does not need it.

Documents the stderr warning envelope alongside the response array, since the
two shapes differ and only the array was described, and records why a missing
experimental opt-in is a host-side code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 19:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Several post-telemetry early exits still discard retained warnings instead of emitting structured warning envelopes.

2 open findings
3 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Drain retained telemetry warnings before early exits

src/​tools/​wxc/​src/​main.rs:1424

This early exit occurs after telemetry::init may have retained a warning (for example, ETW registration failure), but it bypasses the only one-shot warning drain at line 1660. The error envelope is emitted while that warning is silently lost from stderr, despite warnings being documented as emitted on failures too. Drain structured warnings before exiting; the same is needed at the other post-telemetry early exits.

This issue also appears in the following locations of the same file:

  • line 1436
  • line 1465
  • line 1591

🧠 Review effort: Balanced

@theelliotm
Elliot (theelliotm) marked this pull request as ready for review October 13, 2026 19:17
@theelliotm
Elliot (theelliotm) requested a review from a team as a code owner October 13, 2026 19:17
Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/tools/wxc/src/main.rs Resolved

@MGudgin Gudge (MGudgin) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified adversarial review of #1482

I reviewed the 43-file diff from base 8188df6 to head 9b7a541 and confirmed that its normalized contents match gh pr diff 1482. The inline comments below are anchored only on added lines; unchanged supporting files were byte-compared with the base. The strongest gap is that Unix executable tests do not assert the new JSON-code/exit contract. This is a COMMENT review, not a request for changes based on claim-only findings. No local build, platform-dependent integration suite, or end-to-end test was run as part of filing this review.

Findings on existing open threads

  • #3, live Bubblewrap DNS failures mislabeled as policy refusal: continued in discussion_r4277475899.
  • #6, state-aware error/status mismatch with the PR's blanket claim: continued in discussion_r4277476083 as claim_mismatch, not an introduced runtime regression.
  • #13, warning JSON test can miss a malformed line: continued in discussion_r4277475994.
  • #20, ProcessContainer DACL warnings plus other unstructured wxc-exec advisories despite “Resolves #612”: continued in discussion_r4277476034 as claim_mismatch.

Claim-only and unchanged supporting locations

  • #15 (claim_mismatch, Medium): new docs/development/architecture/versioning.md:718-719 promises wrong-OS unsupported_containment, but the byte-identical state-aware WSLC/IsolationSession gates still return backend_unavailable. The inline comment targets the new claim, not the old gates.
  • #16-19 (newly_exposed_by_change, Medium): the changed IsolationSession policy mapping, one-shot parser, Hyperlight policy phase, and Windows WSLC feature-off arm leave docs/development/architecture/backends/isolation-session/oneshot.md, the one-shot paragraph of docs/development/architecture/container-lifecycle.md, the earlier Hyperlight exit row, and docs/backends/wslc/wsl-container-getting-started.md stale. Each comment is anchored to the changed behavior rather than forcing an anchor into an unchanged paragraph.
  • #22 (claim_mismatch, Low): the PR's all-failures envelope wording includes dry-run failures, but the unchanged handle_dry_run_exit path in wxc, lxc, and mxc_darwin exits before emit_backend_error_envelope; dry-run callers still get a human summary rather than an error JSON line. Either emit the envelope on a failing dry run or limit the claim explicitly. This pre-existing early-exit path is not asserted as a new regression.

Verified pre-existing behavior, not attributed as a new regression

  • mxc_engine/state_aware.rs is byte-identical between base and head; it already returned backend_unavailable for certain missing-feature paths. The state-aware terminal branches already hard-coded exit 1. Finding #6 addresses only the PR's new universal promise.
  • The host DNS lookup in bubblewrap/common/proxy_network.rs is byte-identical. Finding #3 concerns the new rejected conversion of its errors at bwrap_runner.rs:472, not the resolver itself.
  • The older Seatbelt Exec-versus-Open rejection and the streaming feature-off classification have resolved review threads. New comments #11, #15, #19, and #24 address separate residual test, state-aware, and documentation gaps; they are not requests to reopen the fixed behavior.

pub fn error_code(&self) -> MxcErrorCode {
match self {
FailurePhase::Rejected => MxcErrorCode::PolicyValidation,
FailurePhase::BackendUnavailable => MxcErrorCode::BackendUnavailable,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium (security) - workload stderr can impersonate MXC's JSON error.

Attribution: newly_exposed_by_change - the new backend_unavailable code is presented as a machine-readable host-failure signal on the same stderr channel the sandboxed program can write.

wxc-exec relays workload stderr before calling emit_backend_error_envelope; that emitter writes nothing for an ordinary nonzero workload exit because error_message is empty (script_runner.rs:104-120). A workload can print a plausible {"error":{"code":"backend_unavailable",...}} and exit nonzero. A CLI consumer parsing these lines cannot establish whether this diagnostic came from MXC or from contained code. This is conditional on a consumer trusting stderr; I did not find an in-repo SDK making fallback decisions from it.

Fix: Put executor-originated results on a host-owned channel the workload cannot write to. Until then, document these shared-stream lines as untrusted and do not recommend switching containment based solely on them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pre-existing. I think another PR could add a host-owned channel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium, conditional CLI-consumer risk (still open). Attribution: newly_exposed_by_change for the newly meaningful backend_unavailable stderr signal. The new documentation correctly warns that workload stderr may contain forged envelope-shaped lines; that mitigates the claim but does not give a CLI consumer a way to authenticate MXC's JSON diagnostics. For a normal nonzero workload exit with empty error_message, emit_backend_error_envelope writes no authoritative result. I have not found an in-repo SDK making an unsafe backend selection from stderr, so this is not a demonstrated sandbox escape or a blocker on its own. If machine-readable CLI error codes are intended for decisions, provide a host-owned result channel; otherwise please track the channel work separately and keep the untrusted-stream limitation explicit.

/// A refused request and an unusable host have their own constructors on
/// [`ScriptResponse`]; this covers the faults that stay `backend_error` and
/// only say *where* the run came apart.
fn response_with_phase(phase: FailurePhase, message: &str) -> ScriptResponse {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium (maintainability) - centralize phase-aware ScriptResponse construction.

Attribution: introduced_by_change - this PR adds the same response/phase assembly here and in lxc_runner.rs:47, appcontainer_runner.rs:95, seatbelt_runner.rs:1104, and isolation_session/common/sandbox.rs:91.

The implementations already differ in whether they copy the diagnostic into standard_err, which affects bare-prose duplication alongside the new JSON envelope. Maintaining one error contract through five near-identical constructors invites drift.

Fix: Put the phase-aware response construction in a small shared ScriptResponse constructor and use it at the backend call sites; preserve intentionally different stderr behavior explicitly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread src/tools/wxc/src/main.rs Resolved

@MGudgin Gudge (MGudgin) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested

This follow-up changes my verdict from the COMMENT review 5534936733 on the same PR head (9b7a541). The 17 inline comments in that review and four subsequent replies already contain the detailed evidence; I am not opening duplicate threads.

Please address these change-attributable issues before merge:

  • High - Unix executor contract coverage (discussion_r4284388975, introduced_by_change): no Unix executor suite asserts both the structured error code and its exact process exit status for the new failure contract. Add a real refusal and unavailable-backend subprocess case, plus an envelope-serialization assertion.
  • Medium - Bubblewrap host DNS misclassified as request refusal (discussion_r4277475899, introduced_by_change): SandboxProxy::resolve can fail on host DNS timeout/thread failure, but the new rejected mapping emits policy_validation/exit 1. Keep static invalid-input errors as policy refusals and classify host lookup failures separately.
  • Medium - response warnings are missing for in-process callers (discussion_r4284389019, introduced_by_change): the new ScriptResponse.warnings field is not populated by mxc_engine::run even when the logger records advisories. Populate it at the shared run boundary or narrow the published response-level contract.

The state-aware exit mismatch in discussion_r4277476083 predates this PR and is a claim_mismatch, not a merge condition by itself. Other Medium/Low comments remain actionable but are not the basis for this verdict. The PR base and head are unchanged since the earlier review; no local build or host-dependent test suite was run for this follow-up.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Needs-Author-Feedback Waiting for additional information or action from the issue or pull-request author. label Oct 15, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot removed the Needs-Author-Feedback Waiting for additional information or action from the issue or pull-request author. label Oct 15, 2026
Elliot (theelliotm) and others added 3 commits October 23, 2026 15:31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1c677fc2-77c3-43b0-a06f-da11d11447c8
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1c677fc2-77c3-43b0-a06f-da11d11447c8
Seatbelt profile preparation moved to profile_preparation.rs on main; its path and working-directory errors now classify request faults as policy_validation and host faults as backend_error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1c677fc2-77c3-43b0-a06f-da11d11447c8
Copilot AI balanced review requested due to automatic review settings October 23, 2026 23:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Share the path-vs-host I/O classification between bwrap and Seatbelt, and gate the Windows-only hyperlight Ambiguous variant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1c677fc2-77c3-43b0-a06f-da11d11447c8
Copilot AI balanced review requested due to automatic review settings October 23, 2026 23:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-platform error and timeout changes need human sign-off on host validation, including the failures in the linked scheduled run.

4 open issues
2 resolved since last review

Review effort: Balanced

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d3b6643f-9e96-44f0-9860-8c7a1796421a
Restore SDK v1 codes at sites where the new classification would change
published SDK behavior, with a `// SDK v2:` comment naming the intended
code. Document the deferred work in
docs/development/plans/sdk-v2-error-codes.md (tracked in #1595).

Also address review feedback: Hyperlight permission-denied is a policy
refusal, wxc/lxc --setup-* errors emit typed envelopes, and a Bubblewrap
spawn failure is covered by a test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d3b6643f-9e96-44f0-9860-8c7a1796421a
Copilot AI balanced review requested due to automatic review settings October 27, 2026 21:34
# Conflicts:
#	src/mxc-sdk/src/core/mxc_engine/run.rs
#	src/tools/wxc/src/main.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot AI balanced review requested due to automatic review settings October 27, 2026 21:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The IsolationSession host timeout regression still accepts the old ambiguous result without verifying the structured timeout diagnostic.

5 open issues
1 resolved since last review

Review effort: Balanced

The timeout scenario now requires exit -1 and a backend_error envelope
reporting the timeout. The not-compiled-backend test uses Hyperlight,
since MicroVM reports backend_unavailable on Windows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d3b6643f-9e96-44f0-9860-8c7a1796421a
Copilot AI balanced review requested due to automatic review settings October 27, 2026 22:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-platform diagnostic and timeout changes still need current-revision host-suite validation and final maintainer review.

1 open issue
4 resolved since last review

Review effort: Balanced

@MGudgin Gudge (MGudgin) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving the current revision, c7bfbe5. I rechecked the previously requested Rust V1 error-code mappings, Hyperlight permission classification, structured setup errors, the Bubblewrap spawn-failure test, and the IsolationSession timeout assertion. All 29 PR checks pass. Focused local Windows tests passed for the ProcessContainer V1 mapping, the default-feature missing-backend mapping, and the Hyperlight permission classifier (3 tests); I did not run Linux/macOS paths locally.

This approval does not claim a clean scheduled host run: run 40594896918 on this head failed seven jobs (five WSLC image-pull failures, one WSLC stdin-output-loss test, and one MicroVM guest-startup failure). A later mainline run failed in the same WSLC/MicroVM categories, but those failures are not proven unrelated to this PR. The separate host-owned diagnostic channel is tracked in #1596; the remaining Bubblewrap launch/PTY coverage discussion is recorded on the PR.

@theelliotm
Elliot (theelliotm) merged commit ed8639d into main Oct 29, 2026
65 of 72 checks passed
@theelliotm
Elliot (theelliotm) deleted the user/emichlin/cross-backend-error-contract branch October 29, 2026 01:35
@microsoft-github-policy-service microsoft-github-policy-service Bot removed the Needs-Attention Requires attention or a decision from the MXC maintainers. label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emit wxc executor errors and warnings as structured ScriptResponse JSON

3 participants