fix(pi-shell): strip golangci info/warn logs but keep level=error

is_golangci_noise drops 'level=info'/'level=warn' runner chatter while
preserving 'level=error' lines, which carry config and typecheck
failures that must reach the agent.

Op: correct
Restores: spec:snip/filters/golangci-lint.yaml
This commit is contained in:
metaphorics
2026-06-12 02:34:04 +09:00
parent b83ad73dde
commit b11f5f8d2c
+44 -1
View File
@@ -373,7 +373,19 @@ fn is_go_noise(line: &str) -> bool {
fn is_golangci_noise(line: &str) -> bool {
let lower = line.to_ascii_lowercase();
lower.starts_with("level=") && lower.contains("msg=\"[linters_context]")
// Strip runner-log info/warn chatter (snip strips `^level=` wholesale), but
// DELIBERATELY KEEP `level=error` — those lines carry config/typecheck failures
// that would otherwise vanish silently.
// `level=error` carries config/typecheck failures (incl. the canonical
// `level=error msg="[linters_context]…"` typecheck headline) — never strip it,
// even when it routes through the linters_context component.
if lower.starts_with("level=error") {
return false;
}
lower.starts_with("level=info")
|| lower.starts_with("level=warning")
|| lower.starts_with("level=warn")
|| lower.starts_with("level=") && lower.contains("msg=\"[linters_context]")
|| lower.starts_with("golangci-lint has version")
|| lower.starts_with("running ") && lower.contains("linters")
}
@@ -551,6 +563,37 @@ mod tests {
);
}
#[test]
fn golangci_strips_info_warn_but_keeps_level_error() {
let cfg = MinimizerConfig { enabled: true, ..Default::default() };
let ctx = MinimizerCtx {
program: "golangci-lint",
subcommand: Some("run"),
command: "golangci-lint run ./...",
config: &cfg,
};
// Real default (non-json) golangci run: the typecheck headline is emitted by
// the logrus logger in its canonical `level=error msg="[linters_context]…"`
// shape — the exact format that must survive. Surrounding runner chatter
// (incl. a warn-level linters_context line) is stripped.
let input = "level=info Active 5 linters\nlevel=warning The linter 'deadcode' is \
deprecated\nlevel=warning msg=\"[linters_context] stale cache\"\nlevel=error \
msg=\"[linters_context] typechecking error: cannot find package\"\nmain.go:10:2: \
undefined: Foo (typecheck)\n";
let out = filter(&ctx, input, 1);
assert!(out.text.contains("level=error"));
assert!(out.text.contains("typechecking error"));
// `group_by_file` regroups the per-issue line under a `main.go:` header,
// so assert on the surviving location + linter, not the joined string.
assert!(out.text.contains("main.go"));
assert!(out.text.contains("undefined: Foo (typecheck)"));
assert!(!out.text.contains("level=info"));
assert!(!out.text.contains("level=warning"));
// The warn-level linters_context chatter is still dropped — the keep is
// scoped to error level, not to every linters_context line.
assert!(!out.text.contains("stale cache"));
}
#[test]
fn unknown_go_tool_is_passthrough() {
let cfg = MinimizerConfig { enabled: true, ..Default::default() };