Skip to content

fix(task): only include args in task prefix when disambiguating duplicates#8536

Merged
jdx merged 1 commit into
mainfrom
fix/task-prefix-smart-args
Mar 9, 2026
Merged

fix(task): only include args in task prefix when disambiguating duplicates#8536
jdx merged 1 commit into
mainfrom
fix/task-prefix-smart-args

Conversation

@jdx

@jdx jdx commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

When the same task runs multiple times with different arguments (e.g. mise run greet alice ::: greet bob), all output was prefixed with just the task name ([greet]), making it impossible to distinguish which run produced which output.

Now args are included in the prefix only when needed:

  • Multiple instances of same task: [greet alice] and [greet bob]
  • Single instance: [greet] (no args, clean prefix)
  • Different tasks: [greet] and [build] (no disambiguation needed)

Long prefixes are truncated to 40 characters.

How it works: After building the dependency graph, mark_ambiguous_prefixes() counts tasks by display_name. Tasks that share a name get show_args_in_prefix = true, which prefix() checks before formatting.

Closes #8531

Test plan

  • E2E test: test_task_prefix_args_disambiguation validates all three scenarios (duplicate task with args, single task, different tasks)
  • Existing test_task_help_with_cd passes (no regression on -- arg passthrough)
  • Existing test_task_delegation_dedup passes (no regression on shared deps)

🤖 Generated with Claude Code


Note

Low Risk
Behavior change is limited to task output prefix formatting and is guarded by targeted E2E coverage; minimal risk outside of tooling/log-parsing expectations.

Overview
Improves task output labeling by including args in the prefix only when needed to disambiguate multiple executions of the same display_name (e.g. parallel greet alice vs greet bob), while keeping single-run prefixes clean.

This introduces a per-task show_args_in_prefix flag set during dependency graph preparation (Deps::mark_ambiguous_prefixes, invoked after Deps::new and Deps::new_pruned), and updates Task::prefix() to conditionally append args and still truncate to 40 chars.

Adds an E2E test for prefix disambiguation and updates an existing double-dash/usage-spec test expectation to match the new prefix behavior.

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

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the mise task runner by improving the clarity of task output. It addresses a limitation where identical task names running with varying arguments resulted in ambiguous output prefixes. The changes introduce a mechanism to dynamically include task arguments in the output prefix only when necessary for disambiguation, thereby providing clearer context for concurrent or repeated task executions.

Highlights

  • Task Output Disambiguation: Task output prefixes now conditionally include arguments to disambiguate between multiple runs of the same task with different arguments. For single task runs or different tasks, the prefix remains concise. Long prefixes are truncated to 40 characters.
Changelog
  • e2e/tasks/test_task_prefix_args_disambiguation
    • Added a new E2E test to verify the behavior of task output prefixes with and without arguments for disambiguation.
  • src/cli/run.rs
    • Integrated the mark_ambiguous_prefixes call into the prepare_tasks function to enable prefix disambiguation logic.
  • src/task/deps.rs
    • Implemented mark_ambiguous_prefixes to identify tasks that share a display_name and appear multiple times, setting a flag to include arguments in their prefixes.
  • src/task/mod.rs
    • Introduced show_args_in_prefix boolean field to the Task struct to control argument inclusion in prefixes.
    • Modified the prefix method to format the task prefix, conditionally including arguments and truncating long prefixes.
    • Updated the Default implementation for Task to initialize show_args_in_prefix to false.
Activity
  • An E2E test, test_task_prefix_args_disambiguation, was added and validated to cover the new disambiguation logic.
  • Existing tests, test_task_help_with_cd and test_task_delegation_dedup, were confirmed to pass, ensuring no regressions.
  • This pull request addresses and closes the discussion found at Distinguish tasks by arguments? (test matrix) #8531.
  • The changes were generated with the assistance of Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@jdx jdx force-pushed the fix/task-prefix-smart-args branch 2 times, most recently from c001344 to 6dd4eef Compare March 9, 2026 14:58
@greptile-apps

greptile-apps Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves mise run output readability by including task arguments in output prefixes only when needed for disambiguation — specifically when the same task runs concurrently with different arguments (e.g. mise run greet alice ::: greet bob). Previously, every task prefix unconditionally included all args, making output noisy for single-instance runs.

Key changes:

  • Adds show_args_in_prefix: bool to Task (serde-skipped, defaults to false). Task::prefix() conditionally appends args and truncates to 40 characters.
  • Adds Deps::mark_ambiguous_prefixes(), which groups graph nodes by display_name and sets show_args_in_prefix = true on all members of any group with >1 node.
  • prepare_tasks() in run.rs calls mark_ambiguous_prefixes() after building the dependency graph. Deps::new_pruned() also calls it after pruning, so sub-graphs used by task_executor behave consistently.
  • Existing test test_task_double_dash_behavior is correctly updated to expect [with_usage] (no args) for a single-instance task run.
  • New e2e test test_task_prefix_args_disambiguation validates all three scenarios: duplicate task (args shown), single task (no args), and different tasks (no args).

Correctness notes:

  • Task::PartialEq and Hash are already implemented manually (using only name, args, and env) and do not include show_args_in_prefix, so deduplication logic is unaffected.
  • The flag is set at graph-construction time and carried in task clones emitted via the channel, ensuring downstream code (output handlers, etc.) always sees the correctly-marked task.
  • Minor: mark_ambiguous_prefixes is called inside new_pruned but not inside Deps::new, requiring callers of new (currently just prepare_tasks) to invoke it explicitly. This asymmetry is not a current bug but may be a future footgun.

Confidence Score: 4/5

  • Safe to merge; a small, well-targeted behavioural change with good test coverage and no impact on task execution logic.
  • The change is well-scoped and logically correct. Task::PartialEq/Hash correctly exclude the new field, so deduplication is unaffected. Both code paths (prepare_tasks and new_pruned) call mark_ambiguous_prefixes exactly once on a fresh graph. The only deductions are: (1) minor asymmetry between Deps::new and Deps::new_prunednew does not self-call mark_ambiguous_prefixes, requiring explicit caller responsibility; (2) mark_ambiguous_prefixes visibility is pub when pub(crate) is sufficient.
  • No files require special attention; src/task/deps.rs has the minor asymmetry noted above but it is not a current bug.

Important Files Changed

Filename Overview
src/task/mod.rs Adds show_args_in_prefix: bool field (serde-skipped, defaulting to false) to Task; updates prefix() to conditionally format with args only when flagged, with 40-char truncation. PartialEq/Hash correctly exclude the new field so task deduplication is unaffected.
src/task/deps.rs Adds mark_ambiguous_prefixes() which groups graph nodes by display_name and sets show_args_in_prefix = true on any group with >1 member. Called at the end of new_pruned(). Note: the method only ever sets the flag to true, never resets to false, so in sub-graphs created via new_pruned the flag could persist from the parent's task clones if they were already marked, but since task_executor constructs fresh task clones this is not a practical issue.
src/cli/run.rs Small change in prepare_tasks: makes the Deps binding mutable and calls mark_ambiguous_prefixes() before returning. Clean integration with no side effects.
e2e/tasks/test_task_prefix_args_disambiguation New e2e test covering three scenarios: same task twice with different args (expects args in prefix), single task run (expects no args), and two different tasks (expects no args in either prefix). Well-structured coverage of the new behaviour.
e2e/tasks/test_task_double_dash_behavior Updates existing test to reflect the new prefix behaviour: [with_usage] instead of [with_usage -x myfile] since the task runs as a single instance. Correct regression update.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["mise run greet alice ::: greet bob"] --> B["prepare_tasks()"]
    B --> C["Deps::new(config, tasks)"]
    C --> D["Build DiGraph<Task>"]
    D --> E["mark_ambiguous_prefixes()"]
    E --> F{{"Group nodes by display_name"}}
    F --> G["greet alice\ngreet bob → count = 2"]
    G --> H["Set show_args_in_prefix = true\nfor both nodes"]
    H --> I["is_linear()"]
    I --> J["subscribe() → emit leaves"]
    J --> K["Task cloned from graph\n(carries show_args_in_prefix)"]
    K --> L["task.prefix()"]
    L --> M{{"show_args_in_prefix\n&& args not empty?"}}
    M -- Yes --> N["[greet alice]\n[greet bob]"]
    M -- No --> O["[greet]\n(single run or different tasks)"]

    style N fill:#d4edda,stroke:#28a745
    style O fill:#cce5ff,stroke:#007bff
Loading

Comments Outside Diff (2)

  1. src/task/deps.rs, line 234 (link)

    Consider pub(crate) visibility

    mark_ambiguous_prefixes is only used within the crate (src/cli/run.rs and internally in new_pruned), so pub(crate) would be a tighter, more idiomatic fit here than pub.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  2. src/task/deps.rs, line 106-127 (link)

    mark_ambiguous_prefixes called in new_pruned but not in new

    mark_ambiguous_prefixes is called at the end of new_pruned but not inside Deps::new itself, so callers of new must remember to call it manually (as prepare_tasks does). If a future caller invokes Deps::new without the follow-up call, prefix disambiguation silently fails.

    Consider either calling mark_ambiguous_prefixes at the end of Deps::new, or adding a prominent doc comment on new that explicitly states the caller is responsible for it. This makes the contract clear and reduces the risk of accidentally omitting it.

Fix All in Claude Code

Last reviewed commit: 38889a9

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a useful feature for disambiguating task output prefixes when the same task is run multiple times with different arguments. The implementation is logical and the addition of an E2E test is great for ensuring correctness. I have a couple of suggestions to improve the implementation slightly.

Note: Security Review is unavailable for this PR.

Comment thread src/task/deps.rs Outdated
Comment on lines +234 to +252
let mut name_counts: HashMap<String, usize> = HashMap::new();
for idx in self.graph.node_indices() {
*name_counts
.entry(self.graph[idx].display_name.clone())
.or_default() += 1;
}
let ambiguous: HashSet<String> = name_counts
.into_iter()
.filter(|(_, count)| *count > 1)
.map(|(name, _)| name)
.collect();
if ambiguous.is_empty() {
return;
}
for idx in self.graph.node_indices() {
if ambiguous.contains(&self.graph[idx].display_name) {
self.graph[idx].show_args_in_prefix = true;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This implementation iterates over the graph nodes twice. You can make this more efficient and arguably clearer by iterating once to group task indices by name, and then iterating over the groups to mark the ambiguous ones.

        let mut name_to_indices: HashMap<String, Vec<petgraph::graph::NodeIndex>> = HashMap::new();
        for idx in self.graph.node_indices() {
            name_to_indices
                .entry(self.graph[idx].display_name.clone())
                .or_default()
                .push(idx);
        }

        for indices in name_to_indices.values() {
            if indices.len() > 1 {
                for &idx in indices {
                    self.graph[idx].show_args_in_prefix = true;
                }
            }
        }

Comment thread src/task/mod.rs
let inner = format!("{} {}", self.display_name, self.args.join(" "));
let inner = inner.trim();
format!("[{}]", console::truncate_str(inner, max_width, "…"))
let inner = if self.show_args_in_prefix && !self.args.is_empty() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The maximum width for the prefix is hardcoded as 40. It would be better to define this as a constant to improve readability and maintainability, for example const MAX_PREFIX_WIDTH: usize = 40; at a module or impl level.

@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 x -- echo 23.1 ± 0.4 22.3 28.3 1.00
mise x -- echo 23.2 ± 0.4 22.6 27.2 1.01 ± 0.02

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 env 23.7 ± 1.6 21.9 43.5 1.00
mise env 24.0 ± 0.6 22.7 26.5 1.01 ± 0.07

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 hook-env 24.7 ± 0.7 23.4 31.1 1.00
mise hook-env 24.9 ± 0.5 23.7 26.7 1.00 ± 0.03

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 ls 23.6 ± 0.4 22.6 24.9 1.00
mise ls 24.2 ± 0.4 23.0 25.9 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.3.5 mise Variance
install (cached) 157ms 158ms +0%
ls (cached) 86ms 87ms -1%
bin-paths (cached) 89ms 89ms +0%
task-ls (cached) 865ms 851ms +1%

…cates

When the same task runs multiple times with different arguments (e.g. as
dependencies in a test matrix), all output was prefixed with just the task
name, making it impossible to distinguish runs. Now args are included in
the prefix (e.g. `[test-docker 4.1]`) only when multiple instances of the
same task are in the execution graph. Single-instance tasks keep the clean
`[task]` prefix without args.

Closes #8531

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the fix/task-prefix-smart-args branch from 6dd4eef to 38889a9 Compare March 9, 2026 15:45
@jdx jdx merged commit 09b3da0 into main Mar 9, 2026
36 checks passed
@jdx jdx deleted the fix/task-prefix-smart-args branch March 9, 2026 16:07
jdx pushed a commit that referenced this pull request Mar 9, 2026
### 🐛 Bug Fixes

- **(activate)** reorder shims to front of PATH on re-source in fish by
@jdx in [#8534](#8534)
- **(backend)** strip mise shims from dependency_env PATH to prevent
fork bomb by @pose in [#8475](#8475)
- **(github)** resolve "latest" version correctly via GitHub API by @jdx
in [#8532](#8532)
- **(lock)** set env tags and clarify lockfile docs by @jdx in
[#8519](#8519)
- **(lock)** use separate mise.<env>.lock files instead of env tags by
@jdx in [#8523](#8523)
- **(task)** include args in task output prefix and truncate long
prefixes by @jdx in [#8533](#8533)
- **(task)** only include args in task prefix when disambiguating
duplicates by @jdx in [#8536](#8536)
- **(test)** pin goreleaser version in attestation e2e test by @jdx in
[#8518](#8518)
- **(windows)** env._.source needs to run bash.exe on Windows (fix
#6513) by @pjeby in [#8520](#8520)
- handle locked .exe shims on Windows during reshim by @davireis in
[#8517](#8517)

### 🚜 Refactor

- **(prepare)** remove touch_outputs and update docs to reflect blake3
hashing by @jdx in [#8535](#8535)

### 📚 Documentation

- **(docker)** replace jdxcode/mise image with curl install, update to
debian:13-slim by @jdx in [#8526](#8526)
- fix "gzip: stdin is encrypted" error in shell tricks cookbook by
@pjeby in [#8512](#8512)

### 📦 Registry

- add tigerbeetle
([github:tigerbeetle/tigerbeetle](https://github.com/tigerbeetle/tigerbeetle))
by @risu729 in [#8514](#8514)

### New Contributors

- @pjeby made their first contribution in
[#8520](#8520)
- @davireis made their first contribution in
[#8517](#8517)
- @Aurorxa made their first contribution in
[#8511](#8511)

## 📦 Aqua Registry Updates

#### New Packages (6)

-
[`betterleaks/betterleaks`](https://github.com/betterleaks/betterleaks)
- [`majorcontext/moat`](https://github.com/majorcontext/moat)
- [`princjef/gomarkdoc`](https://github.com/princjef/gomarkdoc)
- [`remko/age-plugin-se`](https://github.com/remko/age-plugin-se)
- [`sudorandom/fauxrpc`](https://github.com/sudorandom/fauxrpc)
- [`swanysimon/mdlint`](https://github.com/swanysimon/mdlint)

#### Updated Packages (1)

- [`moonrepo/moon`](https://github.com/moonrepo/moon)
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.

1 participant