Skip to content

refactor(prepare): remove touch_outputs and update docs to reflect blake3 hashing#8535

Merged
jdx merged 2 commits into
mainfrom
remove-touch-outputs
Mar 9, 2026
Merged

refactor(prepare): remove touch_outputs and update docs to reflect blake3 hashing#8535
jdx merged 2 commits into
mainfrom
remove-touch-outputs

Conversation

@jdx

@jdx jdx commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Remove touch_outputs config option from prepare providers — freshness checking now uses blake3 content hashes exclusively, so touching output mtimes is dead code
  • Update prepare docs to describe the blake3 hash-based freshness system instead of the old mtime comparison

Test plan

  • cargo check passes
  • All lints pass (pre-commit hook)
  • Existing e2e prepare tests pass (no tests referenced touch_outputs)

🤖 Generated with Claude Code


Note

Low Risk
Mostly removal of a dead configuration path plus documentation/schema updates; runtime behavior should be unchanged since freshness no longer relies on output mtimes.

Overview
Prepare providers no longer support touch_outputs. The config field is removed from PrepareProviderConfig, the provider base/trait APIs, and the execution engine (including dropping the output-mtime touching helper and filetime usage).

Docs and schema are updated to match hash-based freshness. docs/dev-tools/prepare.md now describes blake3 source hashing with state persisted in .mise/prepare-state.toml, and schema/mise.json drops the touch_outputs property from prepare_provider.

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

…ake3 hashing

Prepare freshness checking now uses blake3 content hashes exclusively,
making touch_outputs (which touched output mtimes) dead code. Remove
the feature entirely and update docs to describe the hash-based system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@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 refactors the prepare system by transitioning its freshness checking from modification times (mtime) to blake3 content hashing. This fundamental change eliminates the need for the touch_outputs configuration, streamlining the system and ensuring more accurate detection of actual content changes. The associated documentation has been updated to reflect this new, more robust approach.

Highlights

  • Removed touch_outputs Configuration: The touch_outputs configuration option has been removed from prepare providers. This change reflects the shift to an exclusive blake3 content hash-based freshness checking system, making mtime-based output touching obsolete and simplifying the configuration.
  • Updated Documentation for Freshness Checking: The prepare documentation has been thoroughly updated to describe the new blake3 hash-based freshness checking mechanism. This replaces the previous explanation that relied on modification time (mtime) comparisons, providing accurate and current information for users.
Changelog
  • docs/dev-tools/prepare.md
    • Removed the touch_outputs option from the provider options table.
    • Updated the 'Freshness Checking' section to detail blake3 content hashing instead of mtime comparison.
    • Removed the explanatory paragraph about touch_outputs behavior.
  • schema/mise.json
    • Removed the touch_outputs property definition from the PrepareProviderConfig schema.
  • src/prepare/engine.rs
    • Removed the filetime::FileTime import.
    • Removed the touch: bool field from the PrepareJob struct.
    • Eliminated the assignment and usage of the touch variable when creating PrepareJob instances.
    • Removed conditional blocks that previously called Self::touch_outputs(&job.outputs).
    • Deleted the touch_outputs function entirely.
  • src/prepare/mod.rs
    • Removed the touch_outputs trait method from PrepareProvider.
  • src/prepare/providers/mod.rs
    • Updated the documentation comment for ProviderBase to remove the mention of touch_outputs.
    • Removed the touch_outputs method from the ProviderBase implementation.
  • src/prepare/rule.rs
    • Removed the touch_outputs field and its associated documentation from the PrepareProviderConfig struct.
Activity
  • cargo check passed successfully.
  • All lints passed via the pre-commit hook.
  • Existing end-to-end prepare tests passed, confirming no regressions (no tests referenced touch_outputs).
  • The pull request was generated with 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.

@greptile-apps

greptile-apps Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes the touch_outputs prepare-provider option end-to-end — from the config struct, provider trait, engine execution logic, JSON schema, and documentation — replacing mtime-based freshness explanations with accurate blake3 hash-based descriptions. The removal is mechanically complete and consistent across all layers.

Key changes:

  • touch_outputs field deleted from PrepareProviderConfig in src/prepare/rule.rs
  • touch_outputs() method removed from ProviderBase, the PrepareProvider trait, and both parallel/dep-aware execution paths in engine.rs
  • filetime import dropped from engine.rs (the crate is still used elsewhere so Cargo.toml is correctly unchanged)
  • JSON schema entry for touch_outputs removed from schema/mise.json
  • Docs updated to describe blake3 hashing and outputs semantics (existence check, not mtime comparison)

Issue to watch:
PrepareProviderConfig is annotated with #[serde(deny_unknown_fields)]. Removing touch_outputs means any existing mise.toml that explicitly sets touch_outputs = true or touch_outputs = false will now fail to deserialize, breaking those configs. Since touch_outputs was a documented option (default true), users who opted out via touch_outputs = false will be silently broken on upgrade. The field should be kept in the struct (silently ignored / skipped during serialization) until a proper deprecation cycle is complete.

Confidence Score: 3/5

  • Mostly safe refactor, but removing a previously-documented field from a deny_unknown_fields struct is a breaking config-parse change for any user who set touch_outputs explicitly.
  • The code changes themselves are correct and complete. The single concern that lowers the score is the backward-compatibility breakage introduced by deleting touch_outputs from a #[serde(deny_unknown_fields)] struct — users with that key in their config will get a hard deserialization error after upgrading, with no graceful fallback.
  • src/prepare/rule.rs — the deny_unknown_fields / deleted field combination is the only file that requires attention before merge.

Important Files Changed

Filename Overview
src/prepare/rule.rs Removes touch_outputs field from PrepareProviderConfig. Because the struct uses #[serde(deny_unknown_fields)], any existing config containing this key will fail to deserialize, which is a breaking change for users who had explicitly set the option.
src/prepare/engine.rs Cleanly removes the touch flag from PrepareJob and both callsites of touch_outputs() / Self::touch_outputs(), as well as the filetime import. No issues found.
src/prepare/mod.rs Removes the touch_outputs() method from the PrepareProvider trait. Change is consistent and complete; no remaining references.
src/prepare/providers/mod.rs Removes touch_outputs() helper from ProviderBase and updates the doc-comment. Clean removal.
schema/mise.json Removes the touch_outputs JSON Schema property from the prepare provider definition. Consistent with the Rust-side removal.
docs/dev-tools/prepare.md Updates freshness description from mtime-based to blake3 hash-based, removes touch_outputs from the Provider Options table, and updates the outputs description to reflect its new semantics (existence check only, not newer-than comparison).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PrepareEngine::run] --> B{outputs empty?}
    B -- yes --> C[NoOutputs → always stale]
    B -- no --> D{any output missing?}
    D -- yes --> E[OutputsMissing → stale]
    D -- no --> F{sources empty?}
    F -- yes --> G[NoSources → fresh]
    F -- no --> H[Load PrepareState from .mise/prepare-state.toml]
    H --> I{Stored hashes exist?}
    I -- no --> J[first run → Stale]
    I -- yes --> K[Hash source files with blake3]
    K --> L{Hashes match?}
    L -- yes --> M[Fresh ✓]
    L -- no --> N[Stale: file changed/added/removed]
    C --> O[Execute run command]
    E --> O
    J --> O
    N --> O
    O --> P[Save new hashes to state file]
    P --> Q[Done]
    M --> Q
Loading

Comments Outside Diff (1)

  1. src/prepare/rule.rs, line 24-26 (link)

    Breaking deserialization for users with touch_outputs in config

    PrepareProviderConfig is decorated with #[serde(deny_unknown_fields)] (line 25). Removing the touch_outputs field from the struct means that any user who previously set touch_outputs = true or touch_outputs = false in their mise.toml will now get a hard deserialization error when mise loads their config — their entire prepare section will fail to parse.

    The old docs listed touch_outputs in the Provider Options table with default: true, so real-world configs may have it set explicitly (especially when users wanted to opt out with touch_outputs = false).

    A safer migration strategy would be to retain the field but silently ignore it:

    /// Deprecated: touch_outputs is no longer used (freshness is blake3 hash-based).
    /// Retained for backward-compatible config parsing only.
    #[serde(default, skip_serializing)]
    pub touch_outputs: Option<bool>,

    Or, at minimum, add a note to the changelog / migration guide so users know to remove the field before upgrading.

Fix All in Claude Code

Last reviewed commit: 5effa4b

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread src/prepare/rule.rs
/// Whether to update mtime of output files/dirs after a successful run (default: true)
/// This is useful when the prepare command is a no-op (e.g., `uv sync` when all is well)
/// so that the outputs appear fresh for subsequent freshness checks.
pub touch_outputs: Option<bool>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Removing field with deny_unknown_fields breaks existing configs

High Severity

PrepareProviderConfig has #[serde(deny_unknown_fields)], so removing the touch_outputs field means any existing user config that includes touch_outputs = true (or false) will fail deserialization with an "unknown field" error. This silently breaks existing configurations rather than gracefully ignoring the deprecated option.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

it's experimental so we don't need to worry about breaking changes

@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 refactors the 'prepare' feature by removing the touch_outputs configuration and its associated mtime-based logic. This is a good cleanup, as freshness checking is now exclusively based on blake3 content hashing. The documentation has been updated to reflect this change. The code changes are clean and consistently remove the dead code across the affected files. I have a couple of suggestions to improve the clarity and accuracy of the updated documentation.

Comment thread docs/dev-tools/prepare.md
Comment on lines +104 to +109
mise uses blake3 content hashing to determine if sources have changed since the last
successful run. Hashes are stored in `.mise/prepare-state.toml`.

1. Find the most recent mtime among all source files
2. Find the most recent mtime among all output files
3. If any source is newer than all outputs, the provider is stale
1. Compute blake3 hashes of all source files
2. Compare against stored hashes from the last successful run
3. If any file was added, removed, or changed, the provider is stale

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 description of freshness checking is a bit simplified as it omits the check for output existence, which is a key part of the logic. For better accuracy and to avoid user confusion, I suggest clarifying that both output existence and source content hashing are used.

Suggested change
mise uses blake3 content hashing to determine if sources have changed since the last
successful run. Hashes are stored in `.mise/prepare-state.toml`.
1. Find the most recent mtime among all source files
2. Find the most recent mtime among all output files
3. If any source is newer than all outputs, the provider is stale
1. Compute blake3 hashes of all source files
2. Compare against stored hashes from the last successful run
3. If any file was added, removed, or changed, the provider is stale
mise uses output existence and blake3 content hashing to determine if a provider is stale.
Hashes of source files are stored in '.mise/prepare-state.toml' after a successful run.
1. Check if all output files/directories exist. If not, the provider is stale.
2. Compute blake3 hashes of all source files.
3. Compare against stored hashes. If any file was added, removed, or changed, the provider is stale.

Comment thread docs/dev-tools/prepare.md

This means:

- If you modify `package-lock.json`, `node_modules/` will be considered stale

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 point could be rephrased for better clarity. With content hashing, the staleness is determined by changes in source files, not by a comparison with outputs. Mentioning node_modules/ might be confusing as it's an output, not part of the source hash check.

Suggested change
- If you modify `package-lock.json`, `node_modules/` will be considered stale
- If you modify a source file like 'package-lock.json', its content hash will change, and the provider will be considered stale.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@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 17.5 ± 1.1 16.0 25.7 1.00
mise x -- echo 17.7 ± 1.0 16.1 23.1 1.01 ± 0.08

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 env 16.9 ± 0.8 15.5 23.0 1.00
mise env 17.5 ± 1.0 15.9 21.9 1.04 ± 0.08

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 hook-env 17.3 ± 1.1 15.9 26.2 1.00
mise hook-env 17.4 ± 0.9 16.1 22.9 1.01 ± 0.08

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.5 ls 17.5 ± 0.9 16.1 23.7 1.00
mise ls 18.1 ± 0.8 16.7 23.7 1.04 ± 0.07

xtasks/test/perf

Command mise-2026.3.5 mise Variance
install (cached) 112ms 113ms +0%
ls (cached) 67ms 68ms -1%
bin-paths (cached) 66ms 66ms +0%
task-ls (cached) 690ms 702ms -1%

@jdx jdx merged commit 51b9b2f into main Mar 9, 2026
35 of 37 checks passed
@jdx jdx deleted the remove-touch-outputs branch March 9, 2026 13:37
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