Skip to content

Conversation

@NikkeTryHard
Copy link
Owner

@NikkeTryHard NikkeTryHard commented Feb 7, 2026

Summary

  • Redirect all diagnostic [tach:*] and [worker:*] stderr logs to /tmp/tach.log using fd-level redirection (fcntl(F_DUPFD_CLOEXEC) / dup2)
  • Stream file results in real-time via bar.println() as each test file completes — files scroll up above a sticky spinner
  • Spinner shows live stats: Running N tests · X passed · Y failed
  • Vitest-style summary block with aligned labels: Test Files, Tests, Duration, Log file
  • Crash resilience: unstreamed files from worker crashes are printed in final output

Changes

  • New: src/reporting/logredirect.rs — stderr-to-file redirect with RAII restore
  • Modified: src/reporting/reporter.rs — TachReporter gains real-time streaming, per-file tracking, improved spinner, aligned summary
  • Modified: src/main.rs — wire log redirect and per-file test counts
  • Modified: src/reporting/mod.rs, src/lib.rs — module exports

Test plan

  • 844 unit tests passing (cargo nextest run --lib)
  • Clippy clean, fmt clean
  • LogRedirect: 5 tests (creation, path, capture, restore, drop)
  • TachReporter streaming: 8 tests (completion, crash, skip, ordering)
  • End-of-worktree audit: all high/medium issues resolved

Summary by CodeRabbit

  • New Features

    • Real-time per-file test result streaming as files complete.
    • Automatic diagnostic log capture to file during interactive mode.
    • Improved terminal color support and output formatting.
    • Enhanced output readability with per-file summary information and failure details.
  • Bug Fixes

    • Better handling of terminal color detection and output routing.

… stdout

Separates diagnostic output from test results for a cleaner terminal:

- LogRedirect: redirects stderr (fd 2) to /tmp/tach_<uuid>.log so
  [tach:*] and [worker:*] diagnostic messages are captured to file
- TachReporter: all render methods (file list, summary, failures)
  now output to stdout via println!() instead of eprintln!()
- Spinner draw target set to stdout so progress is visible
- Color detection uses stdout (supports_colors_stdout) since stderr
  may be redirected to a log file
- ProgressReporter::should_use_progress_bar checks stdout terminal
- Log file path printed after test run completes

Only TachReporter is changed; other reporters (Dots, Progress, Human,
Json) remain on stderr for backward compatibility.
- LogRedirect now uses /tmp/tach.log instead of /tmp/tach_<uuid>.log,
  preventing stale log file accumulation across runs
- Document in main.rs that child processes (Zygote/workers) inherit the
  stderr redirect intentionally; parent handles fatal errors via reporter
- Document in TachReporter::on_error that println! is safe because
  TachReporter and JsonReporter are mutually exclusive
Files scroll up above the spinner as each file's tests complete,
instead of buffering everything until the end (vitest-style UX).

- Add on_session_setup() to Reporter trait with per-file test counts
- Extract format_file_line() from render_file_list() for reuse
- Stream completed files via bar.println() in on_test_finished()
- Skip already-streamed files in on_run_finished() (crash edge case)
- Wire file count computation in main.rs before run_tests()
- Add test verifying unstreamed files (from worker crashes) are printed
  in on_run_finished via render_file_list
- Change spinner format from "Running tests... 42/1996 (2%)" to
  "Running 1996 tests · 42 passed · 0 failed"
- Add log_path field to TachReporter with set_log_path() setter,
  displayed as 4th line in summary block
- Remove duplicate log path printing from execute_session in main.rs
- H1: Move set_log_path() after LogRedirect::new() succeeds so summary
  only shows log path when redirect actually works. Add set_log_path to
  Reporter trait (default no-op) and MultiReporter (forwards to children).
- H3: Check dup(2) return value in test_stderr_captured_to_log_file
  before passing to File::from_raw_fd.
- M6: Use fcntl(F_DUPFD_CLOEXEC) instead of dup(2) to prevent saved
  stderr fd from leaking into child processes (Zygote, workers).
…rence

- Fix extra blank line when all files were already streamed in real-time
  by only printing the newline if there are unstreamed files to display
- Align summary labels to consistent 13-char column width (Tests,
  Duration, Log file were 1 char short vs Test Files)
- Change Reporter::on_session_setup to take &HashMap instead of owned
  HashMap, eliminating unnecessary clones in MultiReporter
- Change Reporter::set_log_path to take &str instead of String,
  only TachReporter calls .to_owned()
- Update stale doc comment in logredirect.rs to reflect
  fcntl(F_DUPFD_CLOEXEC) usage instead of dup
@NikkeTryHard NikkeTryHard merged commit 70e3ea9 into master Feb 7, 2026
1 of 2 checks passed
@github-actions github-actions bot added documentation Improvements or additions to documentation rust reporting labels Feb 7, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This pull request implements the first phase of a TUI-like reporting system by adding stderr log redirection, per-file test count tracking, and real-time streaming of file results to stdout. New LogRedirect module handles fd-level redirection; Reporter trait expanded with session setup and log path methods; TachReporter refactored to stream results incrementally during test execution.

Changes

Cohort / File(s) Summary
Planning Documentation
docs/plans/2026-02-07-tui-reporter.md
Comprehensive three-phase implementation plan for TUI-like reporting and log suppression, including stderr redirection, real-time streaming, and polish/integration tasks with commit steps and test scaffolding.
Module Exports
src/lib.rs, src/reporting/mod.rs
Exposed new logredirect module as part of the public API via re-exports.
Log Redirection Implementation
src/reporting/logredirect.rs
New LogRedirect utility struct using fd-level operations (fcntl, dup2) to redirect stderr to a log file for the duration of its lifetime, with manual restore() method and Drop implementation ensuring cleanup.
Reporter Trait & Implementations
src/reporting/reporter.rs
Added on_session_setup and set_log_path trait methods; TachReporter enhanced with per-file test count tracking (file_expected, files_streamed, files_printed), real-time streaming logic, color handling via supports_colors_stdout, and reorganized output from stderr to stdout for file-list and summary sections.
Session Execution Wiring
src/main.rs
Integrated LogRedirect initialization in interactive mode, wired per-file counts to reporter.on_session_setup, set log paths on reporters, and ensured log redirect cleanup via drop() after test execution.

Sequence Diagram(s)

sequenceDiagram
    participant Main as Main<br/>Session
    participant LogRedir as LogRedirect<br/>(fd 2)
    participant Reporter as TachReporter<br/>Reporter
    participant TestRunner as Test<br/>Scheduler
    participant Stdout as Stdout

    Main->>LogRedir: new() create log redirect
    LogRedir->>LogRedir: dup2(fd 2 → log file)
    LogRedir-->>Main: return LogRedirect

    Main->>Reporter: on_session_setup(file_counts)
    Reporter->>Reporter: store file_expected map
    Main->>Reporter: set_log_path(path)
    Reporter->>Reporter: store log_path

    TestRunner->>TestRunner: run tests per file
    TestRunner->>Stdout: (diagnostics via fd 2<br/>redirected to log)

    rect rgba(100, 200, 100, 0.5)
    TestRunner->>Reporter: on_test_finished(file_result)
    Reporter->>Reporter: check files_streamed
    Reporter->>Stdout: format_file_line(per-file<br/>summary)
    Reporter->>Stdout: render failures<br/>with icons
    Reporter->>Reporter: mark file as streamed
    end

    Main->>LogRedir: drop()
    LogRedir->>LogRedir: dup2(fd 2 → original)
    LogRedir->>Stdout: restore stderr

    Main->>Stdout: final summary<br/>(with log path)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Whiskers twitch with delight—stderr now flows to files so neat,
Per-file streams dance on stdout, real-time progress is sweet!
LogRedirect hops and captures, fd operations with care,
TachReporter now spreads its wings through the terminal air!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tui-reporter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NikkeTryHard NikkeTryHard deleted the feat/tui-reporter branch February 9, 2026 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation reporting rust

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant