fix(islo): propagate streamed output delivery failures - #1969
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs changes before merge. Reviewed September 7, 2026, 4:16 PM ET / 20:16 UTC. ClawSweeper reviewWhat this changesThe Islo adapter now propagates stdout/stderr delivery errors, with regression tests and documentation explaining when remote exit codes remain authoritative. Merge readiness⛔ Needs changes before merge - 1 item remains This remains a useful fix: current main and v0.52.0 still discard output-writer errors. The new real-provider evidence resolves the previous proof request, and no blocking correctness defect was found. Priority: P2 Review scores
Verification
How this fits togetherCrabbox’s Islo adapter sends commands directly to remote sandboxes and decodes their streamed output into local stdout and stderr. Its result feeds the CLI’s exit status and existing session retention or cleanup handling. flowchart TD
A[CLI command] --> B[Islo HTTP execution]
B --> C[Stream decoder]
C --> D[Local stdout and stderr]
D --> E{Delivery succeeded?}
E -->|Yes| F[Preserve remote exit]
E -->|No| G[Return delivery failure]
F --> H[Finalize session and cleanup]
G --> H
Before merge
Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Keep output-delivery failures in the existing Islo stream-error path while preserving successful remote exits and established session cleanup semantics. Do we have a high-confidence way to reproduce the issue? Yes. Current-main source discards writer errors, and the supplied real-provider comparison demonstrates false success with read-only stdout/stderr descriptors; this review did not execute the reproduction. Is this the best way to solve the issue? Yes. Returning the original writer error through the existing flush failure path is the narrowest repair, and the supplied live controls demonstrate that healthy output and remote exit codes remain intact. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 4f6a77b16199. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
History |
|
Observed live comparison for head Both actual Darwin/arm64 CLIs were built with Go 1.26.5 using One real Islo sandbox per version, one active at a time: Ubuntu 26.04, 1 vCPU, 1024 MB memory, 10 GB disk. Fresh
The failed sinks were real Each failing-output workload wrote a case-specific witness before emitting its output. An unconditional later healthy-FD command verified that witness. This establishes workload entry without assuming stdout/stderr event ordering or claiming that closing the stream stopped the remote command. All 16 run session files identified the correct kept lease and correct fresh/reused state. All 18 CLI processes completed and were reaped; no capture overflow or guard deadline fired. Baseline cleanup completed before candidate allocation. Both normal Stops returned success; separate read-only API observations returned the original immutable sandbox IDs with status This is real CLI → Islo HTTP/SSE → Run finalization → retained-session → explicit Stop proof. It does not test automatic deletion failure, remote process cancellation, or crafted post-exit SSE ordering; source regression tests cover late decoder/writer precedence. Driver SHA-256: The executed-source head Independent inspection verified the raw command results, session files, provider readbacks and cleanup, including the late credential-helper correction. The 4,636-entry evidence seal was independently produced and rechecked; audit SHA-256: Current integration |
|
Merged as The fix stops silently discarding Islo stdout/stderr writer errors. Successful stream delivery still preserves output and remote exit codes; failed delivery uses the existing stream-error path, with provider-owned retention and guarded cleanup unchanged. The documentation and Unreleased changelog entry are on main. Verification included eight pre-fix regression failures, focused/full Islo race tests, shared races, Islo vet, internal-link checks across 246 Markdown files, independent scoped P0 review, and exact-head CI with all 11 main jobs passing: https://github.com/openclaw/crabbox/actions/runs/34158254464. Connector and release checks passed without reruns. The actual two-sandbox, 18-command Islo comparison and its precise limits are recorded at #1969 (comment). Both failed-output cases changed from baseline success to candidate exit1; ordinary exits0/7 and quiet controls stayed correct. Both exact resources were deleted and local claims removed. Independent audit and parent recheck passed after correcting a task-bound credential daemon's late temporary-directory recreation; that history was preserved. The integrated CLI binaries are byte-identical to those actually executed, rather than an assertion that the historical hosted run was replayed on a new tree. The separate run-admission change #1970 landed immediately afterward. Current main GOTOOLCHAIN=go1.26.5 go test -race -count=1 -timeout=180s ./internal/providers/islo ./internal/providers/sharedThat final source test is distinct from the earlier hosted binary proof; no claim is made that the newer main CLI was live-replayed. Adjacent lifecycle/heartbeat proof holds remain untouched. |
Summary
Islo's SSE decoder ignored errors returned while writing command stdout and stderr. A run could therefore report success after its output destination rejected the bytes. Return the original writer error through the decoder's existing failure path so the run reports a delivery failure instead of a successful remote exit.
This stays inside Islo's transport adapter. SSE framing, multiline data, comments, final EOF flushing, repeated exit events, stream limits, and successful output bytes are unchanged. Existing read/decode failures already take precedence over a previously observed exit; output delivery now follows that same rule. The provider's existing run finalizer still owns retention and guarded cleanup. Closing a stream is not evidence that its remote workload stopped.
The provider documentation clarifies the completion rule, and Unreleased records the user-visible fix. No configuration, credentials, dependency, pricing, idle/reclaim, heartbeat, or other provider policy changes are included.
Verification
Candidate head:
79ff10914e08cef124d90d562af5160480ae4261, tree:0b4771dbf1cc204de0e439eeda90df599866f162, based on4f6a77b16199fb4a31c28a164ede394b9d07e6bd.Real-provider verification and integration
The actual before/after comparison passed all 18 CLI commands using two real Islo sandboxes: normal output/exit7 preserved, both quiet-descriptor controls passed, and rejected stdout/stderr changed from silent baseline0 to candidate1. Entry-witness reads avoid cross-channel ordering assumptions. Both owned sandboxes were explicitly stopped, with original-ID deleted tombstones, exact-name HTTP404 and no local claims. All run session handles were retained correctly. This is retained-run plus explicit Stop proof, not automatic deletion-failure or remote-cancellation testing.
Full observed output and scope: #1969 (comment). Independent audit and parent recheck verified the 4,636-entry evidence seal. The audit also caught a task-bound credential daemon recreating an empty temporary directory after initial cleanup; that specific daemon and directory were cleaned, and the original observation remains preserved.
The real execution stays bound to the original ad2/7f7 sources. Current integration includes the separately landed AWS Worker diagnostics change and resolves only the changelog conflict. Both newly built CLIs are byte-identical to those actually executed, and the full 1,497-file Go source scope is unchanged. No hosted replay or incoming AWS feature proof is claimed. Fresh Islo/shared races, docs and independent P0-scoped review passed on this integrated tree.
Current-head CI passed all 11 main jobs: https://github.com/openclaw/crabbox/actions/runs/34158254464. All five code-validation workflows succeeded, including connector smokes and the release check; no reruns were needed. The current-head review accepts the real-provider proof and reports no actionable code findings. The final merge target against main
4f6a77b16199fb4a31c28a164ede394b9d07e6bdis exactly the reviewed/tested integrated tree0b4771dbf1cc204de0e439eeda90df599866f162. Related lifecycle/heartbeat holds remain separate: #1706 and #1707.