Skip to content

fix: prioritize raw task output over task_output setting#7286

Merged
jdx merged 11 commits intojdx:mainfrom
skorfmann:fix/raw-task-output-priority
Dec 14, 2025
Merged

fix: prioritize raw task output over task_output setting#7286
jdx merged 11 commits intojdx:mainfrom
skorfmann:fix/raw-task-output-priority

Conversation

@skorfmann
Copy link
Copy Markdown
Contributor

@skorfmann skorfmann commented Dec 14, 2025

Summary

When a task has raw = true, it needs stdin/stdout to be connected directly for interactive/streaming commands to work properly. The task_output setting (e.g., task_output = "prefix") was being checked before the raw property, causing raw tasks to not receive proper stdin/stdout when a global task_output was configured.

Problem

With a config like:

[settings]
task_output = "prefix"

[tasks.stream]
raw = true
run = "some-streaming-command"

The raw = true task would not work correctly because task_output = "prefix" takes precedence in the output mode selection logic.

Solution

Reorder the output mode selection to check raw before the task_output setting, ensuring raw tasks always get interleave mode regardless of global configuration.

Test plan

  • Unit tests pass (mise run test:unit)
  • Verified manually that raw tasks now work with task_output = "prefix" configured

🤖 Generated with Claude Code


Note

Ensure raw tasks use interleave output regardless of task_output (except silent/quiet), and add an e2e test to verify behavior.

  • Task output selection (src/task/task_output_handler.rs):
    • Make CLI flags (--prefix, --interleave) override config.
    • Prioritize raw tasks to use TaskOutput::Interleave even when Settings::task_output is set (unless silent/quiet).
    • Preserve silent/quiet suppression precedence over raw.
  • Tests:
    • Add e2e test e2e/tasks/test_task_raw_output verifying raw task stdout is not prefixed when task_output = "prefix".

Written by Cursor Bugbot for commit 8a69478. This will update automatically on new commits. Configure here.

When a task has `raw = true`, it needs stdin/stdout to be connected
directly for interactive/streaming commands to work properly. The
`task_output` setting (e.g., `task_output = "prefix"`) was being
checked before the raw property, causing raw tasks to not receive
proper stdin/stdout when a global task_output was configured.

This fix reorders the output mode selection to check `raw` before
the `task_output` setting, ensuring raw tasks always get interleave
mode regardless of global configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 14, 2025 14:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a priority issue where the global task_output configuration setting was preventing raw tasks from receiving proper stdin/stdout connections. By reordering the conditional checks in the output mode selection logic, raw tasks now correctly receive interleave mode regardless of the configured task_output setting, while still respecting explicit CLI flag overrides.

Key Changes

  • Moved the raw property check before the task_output setting check in the output mode selection logic
  • Raw tasks now always receive Interleave mode (needed for stdin/stdout) unless overridden by explicit CLI flags

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

skorfmann and others added 3 commits December 14, 2025 17:29
Add tests to verify that raw tasks get Interleave output mode:
- test_raw_task_gets_interleave_output: task with raw=true gets Interleave
- test_raw_handler_gets_interleave_output: handler with raw=true gets Interleave
- test_prefix_flag_overrides_raw: explicit --prefix flag still works
- test_interleave_flag_with_raw: --interleave with raw task works

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds an integration test that verifies raw tasks get interleave output
mode even when task_output = "prefix" is configured globally.

The test confirms:
- Normal tasks respect the task_output setting
- Raw tasks bypass task_output and use interleave mode
- Raw task stdout doesn't have prefix applied

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner

jdx commented Dec 14, 2025

bugbot run

Add tests that verify raw=true tasks get Interleave output mode
even when task_output=prefix is set in settings. Uses the established
Settings::reset() pattern from http.rs for test isolation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread src/task/task_output_handler.rs Outdated
let task = raw_task();

assert_eq!(handler.output(Some(&task)), TaskOutput::Interleave);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Unit tests depend on global Settings

The new unit tests call handler.output(...), which consults Settings::get() (including env/config). If a developer or CI environment sets values like MISE_TASK_OUTPUT/raw/silent, these tests can fail or pass for the wrong reasons, making them flaky and environment-dependent.

Fix in Cursor Fix in Web

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Raw tasks bypass global silent output

OutputHandler::output() now checks self.raw(task) before Settings::get().task_output, so a config like task_output = "silent" or task_output = "quiet" no longer applies to raw = true tasks. This can unexpectedly emit output even when the user configured global output suppression.

src/task/task_output_handler.rs#L119-L133

if self.prefix {
TaskOutput::Prefix
} else if self.interleave {
TaskOutput::Interleave
} else if self.raw(task) {
// raw tasks need interleave for stdin/stdout to work properly
TaskOutput::Interleave
} else if let Some(output) = Settings::get().task_output {
output
} else if self.jobs() == 1 || self.is_linear {
TaskOutput::Interleave
} else {
TaskOutput::Prefix
}

Fix in Cursor Fix in Web


skorfmann and others added 3 commits December 14, 2025 18:00
Raw tasks should still respect explicit output suppression settings
(task_output = "silent" or "quiet") while only overriding output
format settings like "prefix". This addresses the bugbot review
comment about raw tasks bypassing global output suppression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner

jdx commented Dec 14, 2025

bugbot run

Comment thread src/task/task_output_handler.rs Outdated
Restructure the output mode selection to maintain correct priority:
1. CLI flags (--prefix, --interleave) override all config settings
2. task_output silent/quiet from config overrides raw tasks
3. raw tasks get Interleave for other task_output modes (prefix, etc.)

This ensures `mise run --prefix task` works even with `task_output = "silent"`
in config, while still allowing silent/quiet config to suppress raw task output.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner

jdx commented Dec 14, 2025

bugbot run

Comment thread src/task/task_output_handler.rs Outdated
let handler = OutputHandler::new(default_config());
let task = raw_task();
assert_eq!(handler.output(Some(&task)), TaskOutput::Interleave);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Test race condition due to missing lock acquisition

The test_raw_task_gets_interleave_output test does not acquire TEST_SETTINGS_LOCK before calling handler.output(), which reads from global Settings. Other tests (like test_task_output_silent_applies_to_raw_task) do acquire the lock and modify global settings via Settings::reset(). Since Rust runs tests in parallel by default, if both tests run concurrently, the first test may read task_output = Silent set by the other test. In that case, output.is_silent() returns true at line 128, causing the function to return TaskOutput::Silent instead of the expected TaskOutput::Interleave, leading to intermittent test failures.

Fix in Cursor Fix in Web

Add with_default_settings helper that acquires TEST_SETTINGS_LOCK
and resets settings to prevent race conditions when tests run in
parallel. Updated test_raw_task_gets_interleave_output and
test_prefix_flag_overrides_raw to use this helper.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread src/task/task_output_handler.rs Outdated
}

#[cfg(test)]
mod tests {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just remove this and rely on the e2e test unless you think it's adding value

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me 👍

Remove unit tests that were causing issues with global Settings
dependencies. The e2e test provides sufficient coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner

jdx commented Dec 14, 2025

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no bugs!


@jdx jdx merged commit 21ec807 into jdx:main Dec 14, 2025
28 checks passed
jdx pushed a commit that referenced this pull request Dec 14, 2025
### 🚀 Features

- **(java)** add created_at support to ls-remote --json by @jdx in
[#7297](#7297)
- **(ls-remote)** add created_at timestamps to ls-remote --json for more
backends by @jdx in [#7295](#7295)
- **(ls-remote)** add created_at timestamps to ls-remote --json for core
plugins by @jdx in [#7294](#7294)
- **(registry)** add --json flag to registry command by @jdx in
[#7290](#7290)
- **(ruby)** add created_at timestamps to ls-remote --json by @jdx in
[#7296](#7296)

### 🐛 Bug Fixes

- **(spm)** recursively update submodules after checkout by @JFej in
[#7292](#7292)
- prioritize raw task output over task_output setting by @skorfmann in
[#7286](#7286)

### New Contributors

- @skorfmann made their first contribution in
[#7286](#7286)
- @JFej made their first contribution in
[#7292](#7292)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants