refactor: Route `run`/`watch` output through unified `TerminalSink` (#12315)
## Summary
- Convert all direct `stdout`/`stderr` writes in the `turbo run` hot
path to `turborepo_log` so the TUI doesn't get corrupted by rogue output
- Merge `StdoutSink` and `TerminalSink` into a single sink with three
modes: **Active** (Info→stdout, Warn/Error→stderr), **StderrOnly** (for
`--graph`/`--dry=json`), and **Disabled** (TUI mode)
- Move GitHub Actions `::error::` annotation handling into the sink so
application code just calls `turborepo_log::error()`
- Restore detailed remote cache status messages in the run prelude (e.g.
"disabled (in configuration)" rather than just "disabled")
- Delete `StdoutSink` (139 lines) and simplify `LogSinks` facade
## What changed
| Before | After |
|---|---|
| 3 sinks with 2 independent `AtomicBool` toggles | 2 sinks
(`TerminalSink` + `TuiSink`), 1 tri-state `AtomicU8` |
| `LogSinks` coordinates lockstep enable/disable of 2 sinks | `LogSinks`
delegates to 1 sink |
| GH Actions `::error::` is a direct `writeln!` bypass in `run/mod.rs` |
Annotation lives inside `TerminalSink` |
| `should_print_prelude` field + `hide_prelude()` builder method |
Removed — prelude always emits through `turborepo_log`, sinks control
visibility |
| `print_run_prelude()` (~95 lines of `cprint!` macros) | Deleted —
`emit_run_prelude_logs()` handles everything |
## Testing
8 new integration tests in `run_logging.rs`:
- `test_prelude_appears_in_stream_mode` — packages, tasks, cache status
on stdout
- `test_prelude_absent_from_graph_stdout` — stdout is clean DOT output
- `test_prelude_absent_from_dry_json_stdout` — stdout parses as valid
JSON
- `test_prelude_appears_in_dry_text_mode` — prelude visible in `--dry`
text
- `test_prelude_single_package_format` — `"Running build"` without
`"Packages in scope"`
- `test_github_actions_error_annotation_on_stderr` — `::error::` on
stderr with `GITHUB_ACTIONS=1`
- `test_remote_caching_enable` assertion restored to check `"(in
configuration)"` detail
6 unit tests in `TerminalSink` covering Active/StderrOnly/Disabled
modes.
To manually verify: rebuild with `cargo build -p turborepo` and check
`turbo run build` in stream mode shows the prelude, `--graph` keeps
stdout clean, and the TUI log panel gets the prelude events.
Fixes #8383