Skip to content

feat(prepare): add human-readable stale reasons to prepare output#8408

Merged
jdx merged 2 commits into
mainfrom
feat/prepare-stale-reasons
Mar 2, 2026
Merged

feat(prepare): add human-readable stale reasons to prepare output#8408
jdx merged 2 commits into
mainfrom
feat/prepare-stale-reasons

Conversation

@jdx

@jdx jdx commented Mar 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace boolean fresh/stale check with FreshnessResult enum that carries human-readable reasons
  • Dry-run output now shows why a provider would run, e.g. [dry-run] Would prepare: npm (node_modules does not exist) or [dry-run] Would prepare: codegen (schema.graphql is newer than outputs)
  • Status bar stale notification includes reasons: prepare: npm (node_modules does not exist) — run 'mise prep'
  • Supports reasons: "does not exist", "is newer than outputs", "created this session", "no outputs defined", "forced"

Test plan

  • E2E test: dry-run shows "does not exist" when output is missing
  • E2E test: dry-run shows "is newer than outputs" when source is updated
  • All existing prepare e2e tests pass unchanged

🤖 Generated with Claude Code


Note

Medium Risk
Changes prepare freshness evaluation from a boolean to a reason-carrying enum and adjusts when steps are considered stale (e.g., missing outputs/session-created outputs), which could affect whether prepare runs or is skipped. Risk is limited to dependency-prep UX/logic and is covered by updated e2e assertions.

Overview
mise prepare --dry-run now prints why a provider would run by attaching a human-readable staleness reason to PrepareStepResult::WouldRun (e.g., output missing, sources newer, forced).

The prepare engine replaces the boolean freshness check with a FreshnessResult enum, adding explicit handling for missing outputs, outputs created in the current session, no outputs, no sources, and forced runs; the status-bar stale warning now includes these reasons.

E2E coverage is updated to assert the new reason strings for missing outputs and source-newer-than-output cases.

Written by Cursor Bugbot for commit 02a2faf. 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 significantly improves the user experience of the mise prepare command by providing clear, actionable feedback on why a preparation step is deemed necessary. Instead of a simple fresh/stale status, users will now see specific reasons in dry-run outputs and status bar notifications, enabling them to quickly understand and address the underlying issues. This change enhances transparency and debugging capabilities for mise users.

Highlights

  • Enhanced Staleness Reasons: Introduced a FreshnessResult enum to replace simple boolean freshness checks, providing detailed, human-readable reasons for why a mise prepare step might be considered stale.
  • Improved Dry-Run Output: Enhanced the mise prepare --dry-run command output to display these specific reasons, such as 'does not exist' or 'is newer than outputs', giving users more context.
  • Detailed Status Bar Notifications: Updated the status bar notification for stale prepare providers to include the human-readable reasons, improving user awareness and actionability.
  • Expanded E2E Testing: Expanded E2E tests to cover the new dry-run output and ensure correct reason reporting for different staleness scenarios.
Changelog
  • e2e/cli/test_prepare
    • Added assertions to verify that mise prepare --dry-run output includes specific stale reasons like "does not exist" and "is newer than outputs".
  • src/cli/prepare.rs
    • Modified the WouldRun variant of PrepareStepResult to include a reason string.
    • Updated the miseprintln! macro for dry-run output to display the new human-readable reason.
  • src/prepare/engine.rs
    • Defined a new FreshnessResult enum to encapsulate various freshness states and their corresponding human-readable reasons.
    • Updated the PrepareStepResult::WouldRun variant to carry both an ID and a reason.
    • Refactored the check_staleness function to return a vector of provider IDs and their String reasons.
    • Modified the check_freshness function to return FreshnessResult instead of a boolean, incorporating logic to determine and format specific reasons for staleness (e.g., outputs missing, sources newer, session stale, no outputs, forced).
    • Adjusted the PrepareEngine::execute method to use the new FreshnessResult and pass the reason to PrepareStepResult::WouldRun.
  • src/prepare/mod.rs
    • Updated the notify_if_stale function to format the warning message using the new human-readable reasons returned by check_staleness.
Activity
  • No human activity has been recorded on this pull request yet.
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.

@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 valuable enhancement by adding human-readable reasons for why a prepare step is considered stale. The core of the change is the refactoring from a boolean freshness check to a more descriptive FreshnessResult enum, which is a solid design choice. The implementation is well-executed across the affected files, and the e2e tests have been updated to cover the new output, ensuring the feature is verifiable. I've identified one minor issue where a fallback error message could be misleading, but overall, this is a great improvement to the user experience.

Comment thread src/prepare/engine.rs Outdated
Comment on lines +474 to +476
(_, None) => Ok(FreshnessResult::OutputsMissing(
"outputs do not exist".to_string(),
)),

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 message "outputs do not exist" is incorrect in this context. The loop at lines 440-447 has already verified that all output paths exist. If outputs_mtime is None at this point, it's likely due to an issue reading file metadata (e.g., permissions), not because the files are missing.

Using FreshnessResult::OutputsMissing is semantically incorrect. It would be more accurate to use FreshnessResult::Stale with a message that reflects the actual situation. This ensures the provider is correctly marked as stale while providing a non-misleading reason to the user.

Suggested change
(_, None) => Ok(FreshnessResult::OutputsMissing(
"outputs do not exist".to_string(),
)),
(_, None) => Ok(FreshnessResult::Stale(
"could not determine modification time of outputs".to_string(),
)),

@greptile-apps

greptile-apps Bot commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces boolean freshness checks with a FreshnessResult enum that provides human-readable reasons for why prepare providers need to run. The implementation is clean and well-structured:

  • Core change: Introduced FreshnessResult enum with variants for different staleness reasons (missing outputs, newer sources, forced, etc.)
  • Improved UX: Dry-run output now shows specific reasons like "node_modules does not exist" or "requirements.txt is newer than outputs"
  • Status notifications: Stale warnings include reasons, helping users understand what needs updating
  • Testing: E2E tests verify the new reason messages appear correctly

The refactoring maintains backward compatibility in behavior while adding valuable diagnostic information. The logic for determining freshness is sound, properly handling edge cases like empty directories and session-created outputs.

Confidence Score: 5/5

  • This PR is safe to merge with no identified issues
  • The implementation is well-designed with proper enum variants, comprehensive testing, and clean refactoring from boolean to structured results. All existing tests pass, new tests cover the added functionality, and the changes are purely additive to the user experience without altering core behavior.
  • No files require special attention

Important Files Changed

Filename Overview
src/prepare/engine.rs Introduced FreshnessResult enum to replace boolean checks; refactored check_freshness to return detailed reasons for staleness
src/cli/prepare.rs Updated dry-run output to include reason parameter from PrepareStepResult::WouldRun
src/prepare/mod.rs Enhanced notify_if_stale to format and display reasons alongside provider IDs in status warnings
e2e/cli/test_prepare Added test assertions to verify human-readable reasons appear in dry-run output for missing outputs and stale sources

Last reviewed commit: 4b78806

@github-actions

github-actions Bot commented Mar 2, 2026

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.24 x -- echo 28.3 ± 0.5 27.5 32.7 1.19 ± 0.06
mise x -- echo 23.8 ± 1.1 22.9 44.0 1.00
✅ Performance improvement for x -- echo is 19%

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.24 env 27.8 ± 0.6 27.1 32.6 1.20 ± 0.03
mise env 23.1 ± 0.4 22.4 25.2 1.00
✅ Performance improvement for env is 20%

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.24 hook-env 28.7 ± 0.5 27.9 33.4 1.20 ± 0.03
mise hook-env 23.9 ± 0.4 23.1 25.8 1.00
✅ Performance improvement for hook-env is 20%

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.24 ls 23.0 ± 0.4 22.4 24.9 1.06 ± 0.06
mise ls 21.7 ± 1.1 21.0 42.1 1.00

xtasks/test/perf

Command mise-2026.2.24 mise Variance
install (cached) 163ms 149ms +9%
ls (cached) 88ms 81ms +8%
bin-paths (cached) 96ms ✅ 85ms +12%
task-ls (cached) 867ms 848ms +2%

✅ Performance improvement: bin-paths cached is 12%

jdx and others added 2 commits March 2, 2026 02:42
Replace boolean fresh/stale check with FreshnessResult enum that
includes specific reasons like "package-lock.json is newer than
outputs" or "node_modules does not exist". Reasons are shown in
dry-run output and status bar notifications.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ures

The (_, None) match arm fires when output files exist but their mtime
couldn't be read (e.g., permissions). Using OutputsMissing was
semantically incorrect since outputs were already verified to exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the feat/prepare-stale-reasons branch from 77eb9d6 to 02a2faf Compare March 2, 2026 02:42
@jdx jdx merged commit ca0b1d0 into main Mar 2, 2026
35 checks passed
@jdx jdx deleted the feat/prepare-stale-reasons branch March 2, 2026 02:59
jdx pushed a commit that referenced this pull request Mar 2, 2026
### 🚀 Features

- **(hooks)** add task references to hooks and watch_files by @jdx in
[#8400](#8400)
- **(prepare)** add git-submodule built-in provider by @jdx in
[#8407](#8407)
- **(prepare)** add human-readable stale reasons to prepare output by
@jdx in [#8408](#8408)
- **(prepare)** add dependency ordering to prepare steps by @jdx in
[#8401](#8401)
- **(prepare)** add --explain flag for provider diagnostics by @jdx in
[#8409](#8409)
- **(prepare)** add per-provider timeout support by @jdx in
[#8405](#8405)
- **(prepare)** add blake3 content-hash freshness checking by @jdx in
[#8404](#8404)
- **(tasks)** monorepo vars and per-task vars by @halms in
[#8248](#8248)

### 🐛 Bug Fixes

- **(aqua)** restore bin_paths disk cache with fresh_file invalidation
by @jdx in [#8398](#8398)
- **(idiomatic)** use generic parser for idiomatic files by @risu729 in
[#8171](#8171)
- **(install)** apply precompiled options to all platforms in lockfile
by @jdx in [#8396](#8396)
- **(install)** normalize "v" prefix when matching lockfile versions by
@jdx in [#8413](#8413)
- **(prepare)** improve git submodule parser and fix check_staleness
error handling by @jdx in [#8412](#8412)
- **(python)** respect precompiled settings in lock file generation by
@jdx in [#8399](#8399)
- **(python)** clarify uv_venv_auto docs + prevent uv shim recursion in
venv creation by @halms in
[#8402](#8402)
- **(task)** remove deprecated `# mise` task header syntax by @jdx in
[#8403](#8403)
- **(vfox)** avoid eager metadata loading during config file detection
by @jdx in [#8397](#8397)
- clarify GitHub attestations to be artifact ones by @scop in
[#8394](#8394)
- ignore comments in idiomatic version files by @iloveitaly in
[#7682](#7682)

### 🚜 Refactor

- unify archive detection by @risu729 in
[#8137](#8137)

### 📚 Documentation

- remove duplicated docs for npm.package_manager by @risu729 in
[#8414](#8414)
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