Skip to content

bug(dotnet): build/test summary line at top of output is cut off by | tail -N #1574

Closed

Description

@F0rty-Tw0

TL;DR

rtk dotnet build (also test, restore) puts the success/failure status line at the top of the output. Native dotnet puts it at the bottom. Anything that reads the end of the stream loses the verdict: | tail -N, watch/monitor mode in agents, IDE log tails, chunked-output readers.

Repro

rtk dotnet build 2>&1 | tail -5

Expected: the last 5 lines include ok dotnet build: 0 errors, 0 warnings (…).
Actual: the last 5 lines are warnings or empty; the status line is gone.

Why agents in particular get hurt

Agents (Claude Code, Codex, Copilot CLI, etc.) commonly read build output through:

  • | tail -N to keep token usage low
  • streaming / watch consumers (/watch, /monitor, tail -f, log followers)
  • a bounded recent-output context window

In all three cases the agent only sees the last N lines or the tail of the stream. Native dotnet writes Build succeeded. or Build FAILED. last, so the agent gets a clear verdict. RTK writes the verdict first, then errors and warnings, so the agent sees error noise followed by EOF, with no ok or fail line anywhere near the end.

Result: the agent cannot tell whether the build passed, even though the information was technically there 200 lines ago. This silently breaks any agent loop that gates the next step on build success.

Why this happens (code)

src/cmds/dotnet/dotnet_cmd.rs::format_build_output (and the test/restore equivalents) emit the status line first, then errors, then warnings.

Two things compound the problem:

  1. The hook rewrites the left side of pipes. dotnet build 2>&1 | tail -5 becomes rtk dotnet build … | tail -5, so tail operates on the filtered stream, not raw dotnet output. Tracked in bug(rewrite): hook rewrites left-hand side of piped commands, breaking downstream filters #1560.
  2. On failure, raw stdout/stderr is prepended before the filtered summary (dotnet_cmd.rs lines 216–228), pushing the verdict even further from the tail. PR fix(dotnet): stop prepending raw stdout on build failure (#914) #1115 (issue dotnet build can be more noisy with rtk #914) drops the prepend on failure but does not move the summary line.

Suggested fixes

Two options, not mutually exclusive:

  1. Hook side (root fix, bug(rewrite): hook rewrites left-hand side of piped commands, breaking downstream filters #1560): stop rewriting the left side when piping into tail, head, wc, grep, or any explicit "read-the-end" consumer. A pipe into | tail -N is an explicit user signal for raw, unreordered output.
  2. Filter side (defensive): move the status line to the bottom of format_{build,test,restore}_output, matching native dotnet. Cheap, unblocks streaming consumers and tail/head pipes today, even before bug(rewrite): hook rewrites left-hand side of piped commands, breaking downstream filters #1560 lands.

Option 2 alone fixes the agent watch/monitor case described above. Option 1 alone fixes the explicit-pipe case but not streaming consumers that read RTK's stdout directly.

Related

Environment

  • Code reference: src/cmds/dotnet/dotnet_cmd.rs:986 (format_build_output builds the header first)
  • Reproduces on master (commit 4113696)

Activity

  1. pszymkowiak commented on Apr 28, 2026

    @pszymkowiak
    Collaborator

    [w] wshm · Automated triage by AI

    🔍 Automated Triage

    🐛 Category bug
    🟡 Priority medium
    🎯 Confidence 95%

    Summary

    The dotnet build/test/restore filter emits the status line at the top instead of the bottom, causing | tail -N and streaming consumers to miss the pass/fail verdict. Two PRs already in progress.

    This looks like a simple fix. Only repo maintainers can trigger auto-fix.

    📁 Relevant files
    • src/cmds/dotnet/dotnet_cmd.rs

    Triaged automatically by wshm · This is an automated analysis, not a human review.

  2. added a commit that references this issue on May 7, 2026
    ed161b0
  3. YOMXXX commented on May 21, 2026

    @YOMXXX
    Contributor

    Heads-up: while triaging this for a possible PR I traced the current `develop` state and the issue body's main scope — `format_build_output`, `format_test_output`, `format_restore_output` — already emits the status line last on `develop`:

    • `ed161b0 fix(dotnet): move build/test/restore status line to the bottom`
    • `271bc53 fix(dotnet): 🐛 format build/test/restore output summaries`

    Confirmed by reading `src/cmds/dotnet/dotnet_cmd.rs` — all three functions end with the `[…sections, verdict]` shape, and each has an inline comment referencing this issue. The behaviour change described in the report should already be in the next release.

    One adjacent surface that still has the same shape and isn't covered by those commits: `format_dotnet_format_output` (`dotnet format --check` path) starts with `Format: N files need formatting` and ends with `ok M files already formatted` — `| tail -N` on this one can give an agent the misleading `ok` line as last visible content. If you'd like that tightened in the same spirit (verdict at the bottom), happy to open a small follow-up PR scoped purely to that function — otherwise this issue itself looks ready to close once `develop` ships.

  4. F0rty-Tw0 commented on May 21, 2026

    @F0rty-Tw0
    ContributorAuthor

    @YOMXXX That's true, nice find, i think we can close this one since the release of 0.40 has fixes for this specific issue. You can open a new issue related to the dotnet format, tag me in it, and im happy to jump into it.

  5. added a commit that references this issue on May 30, 2026
    152f4e3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeffort-smallQuelques heures, 1 fichierfilter-qualityFilter produces incorrect/truncated signalgood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions