Repository navigation
[WSLC] Stop state-aware exec failures from corrupting the output they report on - #1308
Merged
Merged
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2351959c-fa0c-4666-9f47-54023bc32f03
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2351959c-fa0c-4666-9f47-54023bc32f03
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2351959c-fa0c-4666-9f47-54023bc32f03
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2351959c-fa0c-4666-9f47-54023bc32f03
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Error-envelope routing remains inconsistent for parse failures, and raw stderr cannot safely distinguish workload output from typed errors.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Prevents WSLc state-aware exec failures from corrupting workload output while preserving truncation and terminal outcomes.
Changes:
- Routes live-exec error envelopes to stderr.
- Adds protocol-level truncation notices without replacing terminal outcomes.
- Updates regression tests and lifecycle documentation.
| File | Description |
|---|---|
tests/scripts/run_wslc_state_aware_tests.ps1 |
Tests stderr framing and output isolation. |
tests/scripts/run_isolation_session_state_aware_tests.ps1 |
Updates exec-error envelope parsing. |
src/core/wxc/src/main.rs |
Routes non-dry-run exec errors to stderr. |
src/backends/wslc/daemon/src/control_server.rs |
Emits truncation before terminal frames. |
src/backends/wslc/common/src/state_aware.rs |
Preserves outcomes and truncated exit codes. |
src/backends/wslc/common/src/daemon_protocol.rs |
Adds Truncated and bumps protocol version. |
src/backends/wslc/common/src/daemon_client.rs |
Tracks truncation independently of completion. |
docs/wsl/wslc-state-aware.md |
Documents revised WSLc behavior. |
docs/state-aware-lifecycle/mxc-state-aware-sandbox-api.md |
Updates executor stream semantics. |
docs/isolation-session/state-aware-rust.md |
Documents stderr error envelopes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+834
to
+836
| - Non-dry-run **exec**, `exitCode != 0` AND the final non-empty line of stderr | ||
| parses as a complete `{error: {...}}` envelope: dispatch failed; SDK surfaces | ||
| the typed error. |
Comment on lines
+743
to
+746
| if phase == "exec" && !dry_run { | ||
| StateAwareExit::ExecError(json) | ||
| } else { | ||
| StateAwareExit::Error(json) |
| } | ||
| }; | ||
| if let Some(notice) = notice { | ||
| write_frame(pipe, ¬ice).await?; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


📖 Description
Two ways a state-aware exec reported something untrue about a run it had already finished.
A failed exec corrupted its own output. The error envelope was appended to the stdout the script had already been streaming to, leaving neither valid JSON nor clean program output:
PRE_FAILURE_MARKER{"error":{"code":"backend_error",...}}. It now goes to stderr on its own line, so stdout belongs solely to the script and the envelope survives a script whose own stderr ends mid-line. Non-exec phases and exec dry-run stream nothing, so their envelope stays on stdout.A truncated exec overwrote the reason it ended. Dropping output replaced the terminal outcome: a clean run lost its exit code, and a timed-out or cancelled run lost the truncation notice entirely — callers were told the output was complete when it was not. Truncation now travels alongside the outcome, so a timeout still reports as a timeout and a truncated clean run carries its exit code in
details.exitCode.Also corrects two docs that described the old behaviour:
wslc-state-aware.mdpresented the overwriting as intentional, and the API doc's SDK-discrimination section still sent consumers to stdout for the error envelope.🔗 References
Addresses defect 3 of #843. The truncation defects were surfaced while analysing it; the second one became reachable on every terminal variant when #1252 added
TimedOutandCancelled.Of #843's four defects: 1 is closed (#1187, #954), 2's output half is closed (#1252) and its stdin half is blocked on the WSLc SDK surfacing
WSLCProcessFlagsStdin(#1258), 4 is closed (#1167 → #1240). This is 3.🔍 Validation
cargo fmt --all -- --checkandcargo clippy --all-targets --features wslc -- -D warningsclean acrosswslc_common,wxc_wslc_daemon,wxc, andmxc_engine.cargo test --workspace, plus new unit tests at each seam: the stream-selection branch in the executor, the daemon's frame sequence for every terminal variant, and the exit code surviving a truncation failure.run_wslc_state_aware_tests.ps1, 83/83.PROTOCOL_VERSIONgoes 5 → 6 for the new frame. The persistent per-user daemon is refused by a newer client until it restarts, which is the existing exact-equality check working as intended.✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (see docs/pull-requests.md)📋 Issue Type