Skip to content

Commit 9ed2e49

Browse files
kylehgcclaude
andcommitted
fix(runner): drop the failure-only stderr forward superseded by rtk-ai#3772
The fork adopted upstream rtk-ai#3029 (georgyia, c27bbd0) to surface a failing tool's stderr under stdout-only filtering, scoped to non-zero exits. rtk-ai#3772 forwards stderr on every exit and counts it, so the earlier block now prints the same diagnostics twice on failure. Remove it; its test file keeps the failure case and its success case now pins the new contract: a success exit with stderr-only output is no longer collapsed to silence. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 4d3b417 commit 9ed2e49

2 files changed

Lines changed: 17 additions & 18 deletions

File tree

‎src/core/runner.rs‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,6 @@ where
126126
return Ok(exit_code);
127127
}
128128

129-
// `filter_stdout_only` keeps stderr out of the filter input, so nothing
130-
// downstream can surface it — a failing child's diagnostics would be dropped
131-
// and the exit code left as the only signal (#3026). Emit them here. Only on
132-
// failure: on a successful run stderr is the incidental noise RTK exists to
133-
// suppress, and the filtered stdout already carries the result.
134-
if opts.filter_stdout_only && exit_code != 0 && !result.raw_stderr.trim().is_empty() {
135-
eprint!("{}", result.raw_stderr);
136-
}
137-
138129
let text_to_filter = if opts.filter_stdout_only {
139130
raw_stdout
140131
} else {

‎tests/stderr_passthrough_test.rs‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![cfg(unix)]
2-
//! A failing tool's stderr must reach the user (#3026). Filters that compress
3-
//! stdout run with `RunOptions::stdout_only`, which keeps stderr out of the filter
4-
//! input — so unless the runner emits it, the diagnostics are dropped and the exit
5-
//! code becomes the only surviving signal.
2+
//! A tool's stderr must reach the user whatever the exit code. Filters that
3+
//! compress stdout run with `RunOptions::stdout_only`, which keeps stderr out of
4+
//! the filter input — so unless the runner emits it, the diagnostics are dropped
5+
//! and the exit code becomes the only surviving signal (upstream #3029), or, on
6+
//! a success exit with empty stdout, nothing at all survives (upstream #3772).
67
78
use std::fs;
89
use std::os::unix::fs::PermissionsExt;
@@ -55,15 +56,22 @@ fn failing_tool_stderr_reaches_the_user() {
5556
}
5657

5758
#[test]
58-
fn successful_tool_stderr_stays_suppressed() {
59-
// On success stderr is the incidental noise RTK exists to compress away, and
60-
// the filtered stdout already carries the result.
59+
fn successful_tool_stderr_reaches_the_user() {
60+
// A success exit carries diagnostics too — a deprecation notice, a missing
61+
// config, prettier's whole report — and with stdout empty the never-worse
62+
// guard used to collapse the run to silence on both streams.
6163
let db = tempfile::tempdir().expect("create db tempdir");
6264
let out = rtk_ruff(&shim(0), &db);
6365

6466
assert_eq!(out.status.code(), Some(0));
6567
assert!(
66-
!String::from_utf8_lossy(&out.stderr).contains(DIAGNOSTIC),
67-
"successful run must not leak tool stderr"
68+
String::from_utf8_lossy(&out.stderr).contains(DIAGNOSTIC),
69+
"diagnostic swallowed on a success exit — stderr was {:?}, stdout was {:?}",
70+
String::from_utf8_lossy(&out.stderr),
71+
String::from_utf8_lossy(&out.stdout)
72+
);
73+
assert!(
74+
String::from_utf8_lossy(&out.stdout).trim().is_empty(),
75+
"the tool said nothing on stdout, so neither may rtk"
6876
);
6977
}

0 commit comments

Comments
 (0)