Skip to content

fix(setup): preserve trailing command output while bounding inherited-pipe waits - #1207

Draft
karkarl wants to merge 1 commit into
mainfrom
karkarl-fix-1194-pipe-drain
Draft

fix(setup): preserve trailing command output while bounding inherited-pipe waits#1207
karkarl wants to merge 1 commit into
mainfrom
karkarl-fix-1194-pipe-drain

Conversation

@karkarl

@karkarl karkarl commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

CommandRunner.RunAsync always applied a short bounded grace (s_outputDrainGrace) to the stdout/stderr drain after the child process exited. On high-volume commands whose output was still draining when that grace elapsed, trailing output could be truncated even though the process exited cleanly.

This change preserves complete output on the normal path and keeps the bounded wait only where it is actually needed:

  • On the normal exit path, RunAsync now awaits full stdout/stderr close so all trailing output is captured.
  • The bounded grace is applied only on timeout cleanup, or when a caller opts in via the new allowInheritedPipeHandleEscape parameter for WSL inspection commands whose descendants can keep inherited pipe handles open after the direct child exits.
  • The wsl.exe --list / --verbose / --version / --status inspection callers (CleanupStaleDistroStep, CreateWslInstanceStep, ExistingConfigDetector, StartGatewayStep, PreflightWslStep) opt into the bounded escape, since those are the calls that can leave a descendant holding inherited handles.

Timeout and cancellation behavior are unchanged.

Fixes #1194

Validation

  • dotnet test tests/OpenClaw.SetupEngine.Tests (subsystem touched by this change): full suite 949/949 passed after restoring against a local NuGet feed.
  • Focused CommandRunnerTests: 7/7 passed, including the new high-volume drain and bounded-timeout tests.
  • Required ./build.ps1 and the Shared/Tray closeout suites are Not verified / blocked: NuGet cannot reach https://api.nuget.org/v3/index.json on this host (NU1900 "Unable to load the service index"; underlying TLS/service-index handshake failure), and the global cache lacks Microsoft.ML.OnnxRuntime 1.29.0. A maintainer on a network-enabled host should run ./build.ps1, dotnet test tests/OpenClaw.Shared.Tests, and dotnet test tests/OpenClaw.Tray.Tests to complete closeout before merge.

Real behavior proof

  • New regression test RunAsync_DrainsHighVolumeStdoutAndStderrThroughTrailingMarkers runs a command emitting 8,000 lines on each of stdout and stderr followed by STDOUT_MARKER / STDERR_MARKER, on the default (non-opt-in) path. It asserts all 8,000 lines on each stream are present and that the output ends with the trailing marker, directly proving trailing output is no longer truncated.
  • RunAsync_ProcessTimeoutRemainsBounded proves the timeout path still returns bounded (TimedOut, exit -1) within the grace window.
  • RunAsync_ExitsLeavingPipeHolder... now passes allowInheritedPipeHandleEscape: true, proving the opt-in path stays bounded when a descendant holds an inherited pipe handle open.

This PR is intentionally left as a draft for a human to complete full-repo ./build.ps1 + Shared/Tray validation on a network-enabled host before merge.

…-pipe waits

CommandRunner previously always applied a short bounded grace to the
stdout/stderr drain after the child exited, which could truncate trailing
output on high-volume commands. Await full output-close on the normal path
so complete output is preserved, and apply the bounded grace only on timeout
cleanup or when a caller opts in via allowInheritedPipeHandleEscape for WSL
inspection commands whose descendants can hold inherited pipe handles open.

Opt the wsl.exe --list/--verbose inspection callers into the bounded escape
(CleanupStaleDistroStep, CreateWslInstanceStep, ExistingConfigDetector,
StartGatewayStep). Add regression tests: high-volume stdout/stderr drain with
trailing markers on the default path, a bounded-timeout test, and update the
pipe-holder test to use the opt-in.

Fixes #1194

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

clawsweeper Bot commented Aug 22, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 22, 2026
@clawsweeper

clawsweeper Bot commented Aug 22, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 22, 2026, 11:19 AM ET / 15:19 UTC.

ClawSweeper review

What this changes

The branch waits for complete stdout and stderr draining after ordinary setup commands, while retaining a short bounded wait for timeouts and selected WSL inspection commands.

Regression provenance

Possible regression — suspected (reviewed change). No predecessor PR is attributed.

Merge readiness

⚠️ Ready for maintainer review - 2 items remain

Keep open. This focused collaborator-authored draft addresses a real current-main truncation path and is not already implemented; it needs the repository-required Windows setup validation before merge.

Priority: P2
Reviewed head: 9c48c15cd84a9b3881fbddd3d4d474b34906516a

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) The implementation is focused and regression-covered; remaining confidence work is repository-required validation rather than a demonstrated patch defect.
Proof confidence 🌊 off-meta tidepool Not applicable: The external-contributor proof gate does not apply to this collaborator-authored PR; its focused regression-test claims are supplemental, while product WSL validation remains a merge-risk reducer.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: The external-contributor proof gate does not apply to this collaborator-authored PR; its focused regression-test claims are supplemental, while product WSL validation remains a merge-risk reducer.
Evidence reviewed 7 items Current-main behavior: Current main unconditionally races both output-close tasks against the 250 ms grace, so a cleanly exited high-output command can return before its trailing callbacks complete.
Proposed repair: The branch waits for both stream-close signals on the normal path and retains the bounded grace for timeouts or explicit inherited-pipe callers.
Regression coverage: The added test emits 8,000 stdout and stderr lines followed by separate trailing markers, then asserts the count and final markers on the default path.
Findings None None.
Security None None.

Live Verification

Command: dotnet test tests/OpenClaw.SetupEngine.Tests/OpenClaw.SetupEngine.Tests.csproj --no-restore --filter FullyQualifiedName~CommandRunnerTests

Result: FAIL (failed) — execution before step 1 run: sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

Assertions:

  • FAIL expect_output: Passed!

How this fits together

The setup engine runs Windows and WSL commands and captures their output for provisioning decisions. Its results feed WSL installation, preflight diagnostics, gateway startup, and setup completion checks.

flowchart LR
A[Setup steps] --> B[Command runner]
B --> C[Windows or WSL command]
C --> D[Standard output and error drains]
D --> E{Timeout or known inherited handle?}
E -->|No| F[Wait for stream close]
E -->|Yes| G[Use bounded grace]
F --> H[Captured setup result]
G --> H
Loading

Before merge

  • Resolve merge risk (P1) - The focused tests demonstrate the generic drain policy, but no current-head product WSL setup transcript proves that the selected WSL inspection calls remain bounded in the real setup path.
  • Complete next step (P2) - This collaborator-authored draft needs required validation and ordinary maintainer review, not an automated replacement patch.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch scope 9 files affected, 134 added, 23 removed The change stays concentrated in command execution, the explicit WSL callers, and their tests.
Production versus test growth production +66/-20, tests +68/-3 Test growth slightly exceeds implementation growth and directly covers normal drain, timeout, and inherited-pipe behavior.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #1194
Summary: This PR is the concrete candidate fix for the linked trailing-command-output issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge-risk options

Maintainer options:

  1. Add product WSL setup proof (recommended)
    Run the required WSL gateway validation and retain its current-head result to show selected inspection calls remain bounded while ordinary commands keep trailing output.
  2. Accept the focused-test boundary
    Maintainers may accept the remaining real-WSL coverage gap if CI and local required suites pass and the caller classification is considered sufficient.

Technical review

Best possible solution:

Preserve the scoped normal-drain behavior, then complete the repository build, Shared and Tray suites, plus the product WSL gateway validation before landing.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main has an unconditional 250 ms output-drain race, and the branch adds a focused high-volume marker test for the resulting truncation path; this read-only review did not execute it.

Is this the best way to solve the issue?

Yes, with the remaining WSL validation. Restricting the bounded escape to timeout cleanup and known inherited-handle callers is a narrower maintainable fix than retaining truncation for every command.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against ccd64bbb7d68.

Labels

Label changes:

  • add P2: A setup-output regression can cause provisioning or diagnostic failures, but the available evidence limits the blast radius to command execution paths.
  • add merge-risk: 🚨 availability: A command whose descendant retains inherited output handles could stall setup if it is not deliberately routed through the bounded escape.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply to this collaborator-authored PR; its focused regression-test claims are supplemental, while product WSL validation remains a merge-risk reducer.

Label justifications:

  • P2: A setup-output regression can cause provisioning or diagnostic failures, but the available evidence limits the blast radius to command execution paths.
  • merge-risk: 🚨 availability: A command whose descendant retains inherited output handles could stall setup if it is not deliberately routed through the bounded escape.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply to this collaborator-authored PR; its focused regression-test claims are supplemental, while product WSL validation remains a merge-risk reducer.

Evidence

What I checked:

Likely related people:

  • Joel: The current-main commit that introduced the bounded drain behavior is attributed to Joel and touched the command runner. (role: feature introducer and recent area contributor; confidence: high; commits: ccd64bbb7d68; files: src/OpenClaw.SetupEngine/CommandRunner.cs)
  • Scott Hanselman: Feature-history output associates Scott with earlier CommandRunner test coverage, making this a secondary routing contact. (role: prior test-area contributor; confidence: medium; commits: 4206611f2b2e; files: tests/OpenClaw.SetupEngine.Tests/CommandRunnerTests.cs)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Run ./build.ps1 and the required Shared and Tray suites on a Windows host with dependency access.
  • Run scripts/validate-wsl-gateway.ps1 and retain a redacted current-head transcript.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve trailing command output while bounding inherited-pipe waits

2 participants