Skip to content

fix(env): include watch_files in fast-path early exit check#8317

Merged
jdx merged 1 commit intomainfrom
fix/watch-files-fast-path
Feb 23, 2026
Merged

fix(env): include watch_files in fast-path early exit check#8317
jdx merged 1 commit intomainfrom
fix/watch-files-fast-path

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Feb 23, 2026

Summary

  • Store resolved [[watch_files]] paths in HookEnvSession so the fast-path should_exit_early_fast() can detect changes without loading config
  • Check these paths in the fast-path alongside loaded_configs and tera_files

The fast-path (should_exit_early_fast()) runs before config is loaded and previously only checked config files, tera files, and data dirs. Files from [[watch_files]] patterns were invisible to it because they weren't stored in the session. This caused watch_files run commands to only trigger on the first file change — subsequent changes were missed because the fast-path exited early before the full check could run.

Closes #8264

Test plan

  • All unit tests pass (481 tests)
  • All lints pass
  • Manual testing: configure [[watch_files]] with a pattern, touch the file multiple times, verify the run command triggers every time

🤖 Generated with Claude Code


Note

Low Risk
Small, localized change to hook-env cache invalidation logic; main risk is extra stat calls or incorrect session serialization affecting early-exit behavior.

Overview
Fixes missed reruns for [[watch_files]] by making the hook-env fast-path consider watched file changes even before config is loaded.

HookEnvSession now persists the resolved watch file paths, build_session captures them when computing latest_update, and should_exit_early_fast() stats these paths (alongside config and tera files) to prevent incorrect early exits when watched files change or are deleted.

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

The fast-path `should_exit_early_fast()` runs before config is loaded
and only checked loaded_configs, tera_files, and data dir for changes.
Files from `[[watch_files]]` patterns were not checked because they
weren't stored in the session. This caused watch_files to only trigger
on the first file change — subsequent changes were invisible to the
fast-path, which would exit early before the full check could run.

Store resolved watch_file paths in HookEnvSession and check them in
the fast-path so file modifications are detected on every prompt.

Closes #8264

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 23, 2026 15:14
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jdx, 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 resolves an issue where changes to files defined in [[watch_files]] patterns were not being correctly recognized by the fast-path early exit mechanism. By integrating these watched files directly into the session and the fast-path check, the system can now reliably detect file modifications and trigger associated run commands, enhancing the overall responsiveness and correctness of file change detection.

Highlights

  • Fast-path watch_files detection: Modified should_exit_early_fast() to include checks for changes in files specified by [[watch_files]] patterns, ensuring that modifications to these files are detected promptly.
  • HookEnvSession update: Stored resolved [[watch_files]] paths within HookEnvSession to enable the fast-path check without needing to reload the full configuration, improving performance and accuracy.
Changelog
  • src/hook_env.rs
    • Added a watch_files field to the HookEnvSession struct to store resolved paths from [[watch_files]] patterns.
    • Modified the should_exit_early_fast function to iterate through and check the modification times of the newly stored watch_files.
    • Updated the build_session function to populate the watch_files field with the resolved paths during session construction.
Activity
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.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

The pull request addresses a critical bug where watch_files run commands were not consistently triggering due to the fast-path early exit check. The changes correctly integrate watch_files into the HookEnvSession and the fast-path logic, ensuring that modifications to watched files are always detected. The solution is well-implemented and directly resolves the reported issue. The changes also include a minor refactoring to improve how watch_files are handled during session building, which is a good improvement for clarity and maintainability.

Comment on lines +201 to +211
// Check if any files from [[watch_files]] patterns have been modified
for path in &PREV_SESSION.watch_files {
if let Ok(metadata) = path.metadata() {
if let Ok(modified) = metadata.modified()
&& mtime_to_millis(modified) > PREV_SESSION.latest_update
{
return false;
}
} else if !path.exists() {
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This new block correctly checks for modifications in watch_files within the fast-path. This is a critical fix that ensures watch_files patterns are respected, preventing missed triggers for run commands.

Comment on lines +353 to +356
/// Resolved file paths from [[watch_files]] config patterns.
/// Stored so the fast-path can detect changes without loading config.
#[serde(default)]
watch_files: Vec<PathBuf>,
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Adding watch_files to HookEnvSession is essential for the fast-path mechanism to work correctly. This ensures that the resolved paths are persisted and available for subsequent checks without needing to reload the full configuration.

Copy link
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 updates the hook-env “fast-path” early-exit logic so that changes to files referenced by [[watch_files]] can be detected without loading config, preventing missed hook re-runs across repeated file edits.

Changes:

  • Persist resolved [[watch_files]] file paths into HookEnvSession (__MISE_SESSION payload).
  • Extend should_exit_early_fast() to stat the persisted watch-file paths alongside loaded config and tera-dependent files.

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

Comment on lines +201 to +206
// Check if any files from [[watch_files]] patterns have been modified
for path in &PREV_SESSION.watch_files {
if let Ok(metadata) = path.metadata() {
if let Ok(modified) = metadata.modified()
&& mtime_to_millis(modified) > PREV_SESSION.latest_update
{
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

Fast-path only checks the previously resolved watch_files paths. For glob-based patterns (root: Some(...)), get_watch_files() resolves to the current matches only, so newly created files that match the glob after the session is built will not be in PREV_SESSION.watch_files and can be missed by the early-exit check. Consider also persisting the glob roots (and/or patterns) in the session and treating any root-dir mtime change as a reason to skip the fast-path so the full get_watch_files() re-glob can run.

Copilot uses AI. Check for mistakes.
Comment on lines 420 to 422
tera_files: config.tera_files.clone(),
watch_files: resolved_watch_files.into_iter().collect(),
loaded_configs,
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

HookEnvSession is serialized into the __MISE_SESSION environment variable; storing every resolved [[watch_files]] path here can grow the session payload significantly for broad glob patterns (and increase both serialization cost and per-prompt stat calls in should_exit_early_fast). It may be worth adding a guard/limit, or storing a more compact representation (e.g., roots + patterns / a digest) so large watch globs don’t risk hitting environment size limits or slowing the fast-path.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.19 x -- echo 24.0 ± 0.5 23.0 26.6 1.00
mise x -- echo 24.3 ± 1.7 23.1 49.6 1.01 ± 0.07

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.19 env 22.8 ± 0.6 21.8 28.5 1.00 ± 0.04
mise env 22.7 ± 0.5 21.8 27.0 1.00

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.19 hook-env 23.2 ± 0.4 22.4 26.5 1.00
mise hook-env 23.4 ± 0.4 22.4 25.2 1.01 ± 0.02

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.19 ls 20.7 ± 0.4 19.9 23.5 1.00
mise ls 21.1 ± 0.6 20.1 25.4 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.2.19 mise Variance
install (cached) 126ms 126ms +0%
ls (cached) 77ms 77ms +0%
bin-paths (cached) 80ms 80ms +0%
task-ls (cached) 813ms ⚠️ 2735ms -70%

⚠️ Warning: task-ls cached performance variance is -70%

@jdx jdx merged commit 2a825ca into main Feb 23, 2026
39 of 41 checks passed
@jdx jdx deleted the fix/watch-files-fast-path branch February 23, 2026 15:36
mise-en-dev added a commit that referenced this pull request Feb 25, 2026
### 🚀 Features

- **(conda)** replace custom backend with rattler crates by @jdx in
[#8325](#8325)
- **(task)** enforce per-task timeout configuration by @tvararu in
[#8250](#8250)
- **(vsix)** added vsix archives to http backend by @sosumappu in
[#8306](#8306)
- add core dotnet plugin for .NET SDK management by @jdx in
[#8326](#8326)

### 🐛 Bug Fixes

- **(conda)** preserve conda_packages on locked install and fix temp
file race by @jdx in [#8335](#8335)
- **(conda)** deduplicate repodata records to fix solver error on Linux
by @jdx in [#8337](#8337)
- **(env)** include watch_files in fast-path early exit check by @jdx in
[#8317](#8317)
- **(env)** clear fish completions when setting/unsetting shell aliases
by @jdx in [#8324](#8324)
- **(lockfile)** prevent lockfile writes when --locked is set by @jdx in
[#8308](#8308)
- **(lockfile)** prune orphan tool entries on mise lock by @mackwic in
[#8265](#8265)
- **(lockfile)** error on contradictory locked=true + lockfile=false
config by @jdx in [#8329](#8329)
- **(regal)** Update package location by @charlieegan3 in
[#8315](#8315)
- **(release)** strip markdown heading prefix from communique release
title by @jdx in [#8303](#8303)
- **(schema)** enforce additionalProperties constraint for env by
@adamliang0 in [#8328](#8328)

### 📚 Documentation

- Remove incorrect oh-my-zsh plugin ordering comment by @bvosk in
[#8323](#8323)
- require AI disclosure on GitHub comments by @jdx in
[#8330](#8330)

### 📦 Registry

- add `oxfmt` by @taoufik07 in
[#8316](#8316)

### New Contributors

- @adamliang0 made their first contribution in
[#8328](#8328)
- @tvararu made their first contribution in
[#8250](#8250)
- @bvosk made their first contribution in
[#8323](#8323)
- @taoufik07 made their first contribution in
[#8316](#8316)
- @charlieegan3 made their first contribution in
[#8315](#8315)
- @sosumappu made their first contribution in
[#8306](#8306)

## 📦 Aqua Registry Updates

#### New Packages (3)

- [`Tyrrrz/FFmpegBin`](https://github.com/Tyrrrz/FFmpegBin)
- [`elixir-lang/expert`](https://github.com/elixir-lang/expert)
- [`erikjuhani/basalt`](https://github.com/erikjuhani/basalt)

#### Updated Packages (5)

- [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner)
-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`jackchuka/mdschema`](https://github.com/jackchuka/mdschema)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
- [`peco/peco`](https://github.com/peco/peco)
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
## Summary

- Store resolved `[[watch_files]]` paths in `HookEnvSession` so the
fast-path `should_exit_early_fast()` can detect changes without loading
config
- Check these paths in the fast-path alongside loaded_configs and
tera_files

The fast-path (`should_exit_early_fast()`) runs before config is loaded
and previously only checked config files, tera files, and data dirs.
Files from `[[watch_files]]` patterns were invisible to it because they
weren't stored in the session. This caused `watch_files` run commands to
only trigger on the first file change — subsequent changes were missed
because the fast-path exited early before the full check could run.

Closes jdx#8264

## Test plan

- [x] All unit tests pass (481 tests)
- [x] All lints pass
- [ ] Manual testing: configure `[[watch_files]]` with a pattern, touch
the file multiple times, verify the run command triggers every time

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small, localized change to hook-env cache invalidation logic; main
risk is extra stat calls or incorrect session serialization affecting
early-exit behavior.
> 
> **Overview**
> Fixes missed reruns for `[[watch_files]]` by making the hook-env
fast-path consider watched file changes even before config is loaded.
> 
> `HookEnvSession` now persists the resolved watch file paths,
`build_session` captures them when computing `latest_update`, and
`should_exit_early_fast()` stats these paths (alongside config and tera
files) to prevent incorrect early exits when watched files change or are
deleted.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
90fd6c3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
### 🚀 Features

- **(conda)** replace custom backend with rattler crates by @jdx in
[jdx#8325](jdx#8325)
- **(task)** enforce per-task timeout configuration by @tvararu in
[jdx#8250](jdx#8250)
- **(vsix)** added vsix archives to http backend by @sosumappu in
[jdx#8306](jdx#8306)
- add core dotnet plugin for .NET SDK management by @jdx in
[jdx#8326](jdx#8326)

### 🐛 Bug Fixes

- **(conda)** preserve conda_packages on locked install and fix temp
file race by @jdx in [jdx#8335](jdx#8335)
- **(conda)** deduplicate repodata records to fix solver error on Linux
by @jdx in [jdx#8337](jdx#8337)
- **(env)** include watch_files in fast-path early exit check by @jdx in
[jdx#8317](jdx#8317)
- **(env)** clear fish completions when setting/unsetting shell aliases
by @jdx in [jdx#8324](jdx#8324)
- **(lockfile)** prevent lockfile writes when --locked is set by @jdx in
[jdx#8308](jdx#8308)
- **(lockfile)** prune orphan tool entries on mise lock by @mackwic in
[jdx#8265](jdx#8265)
- **(lockfile)** error on contradictory locked=true + lockfile=false
config by @jdx in [jdx#8329](jdx#8329)
- **(regal)** Update package location by @charlieegan3 in
[jdx#8315](jdx#8315)
- **(release)** strip markdown heading prefix from communique release
title by @jdx in [jdx#8303](jdx#8303)
- **(schema)** enforce additionalProperties constraint for env by
@adamliang0 in [jdx#8328](jdx#8328)

### 📚 Documentation

- Remove incorrect oh-my-zsh plugin ordering comment by @bvosk in
[jdx#8323](jdx#8323)
- require AI disclosure on GitHub comments by @jdx in
[jdx#8330](jdx#8330)

### 📦 Registry

- add `oxfmt` by @taoufik07 in
[jdx#8316](jdx#8316)

### New Contributors

- @adamliang0 made their first contribution in
[jdx#8328](jdx#8328)
- @tvararu made their first contribution in
[jdx#8250](jdx#8250)
- @bvosk made their first contribution in
[jdx#8323](jdx#8323)
- @taoufik07 made their first contribution in
[jdx#8316](jdx#8316)
- @charlieegan3 made their first contribution in
[jdx#8315](jdx#8315)
- @sosumappu made their first contribution in
[jdx#8306](jdx#8306)

## 📦 Aqua Registry Updates

#### New Packages (3)

- [`Tyrrrz/FFmpegBin`](https://github.com/Tyrrrz/FFmpegBin)
- [`elixir-lang/expert`](https://github.com/elixir-lang/expert)
- [`erikjuhani/basalt`](https://github.com/erikjuhani/basalt)

#### Updated Packages (5)

- [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner)
-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`jackchuka/mdschema`](https://github.com/jackchuka/mdschema)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
- [`peco/peco`](https://github.com/peco/peco)
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.

2 participants