Skip to content

fix(config): default release age cutoff should not disable installed-version resolution#10315

Merged
jdx merged 2 commits into
mainfrom
claude/clever-borg-53d7eb
Jun 11, 2026
Merged

fix(config): default release age cutoff should not disable installed-version resolution#10315
jdx merged 2 commits into
mainfrom
claude/clever-borg-53d7eb

Conversation

@jdx

@jdx jdx commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the performance regression reported in #10308: upgrading 2026.6.1 → 2026.6.2 took shell startups from ~2.5s to ~65s.

The built-in 24h minimum_release_age default (#10279) set a before_date on every tool resolution, which flipped should_filter_installed_versions on for all non-prefer-offline commands (mise which, mise use, ...). That disabled the installed-version fast paths, so every invocation fetched remote version lists for the entire toolset — ~75ms shell-startup calls became ~2.5s each.

The fix

Cutoff resolution now reports where the cutoff came from (BeforeDateSource::Provided/Explicit/Default):

  • The built-in default only gates which versions remote resolution may pick — its actual purpose of delaying brand-new releases at install time. It no longer suppresses installed-version fast paths, so resolution stays on-disk when an installed version satisfies the request.
  • Explicit cutoffs (--minimum-release-age, a per-tool minimum_release_age option, or the minimum_release_age setting) keep their date-aware resolution semantics from feat(cli): add minimum release age flag to lock and ls-remote #9269, since opting in was a deliberate choice there.

ResolveOptions gains a before_date_from_default flag (set via a shared apply_before_date_for_tool helper, also visible in trace output as before_date=... (default)), and the two should_filter_installed_versions gates in resolve_version/resolve_prefix now require an explicit cutoff.

Tests

  • e2e test_which_no_remote_fetch pins the regression using aqua-backed jq (subject to the built-in default): installed match + fuzzy request must resolve from disk with zero remote version fetches. Verified it fails on unfixed code (which resolved remotely to a non-installed jq) and passes with the fix.
  • e2e test_hook_env_no_remote_fetch guards the prefer-offline paths: a spy copy of the dummy plugin records a marker if its version-listing scripts ever run during mise hook-env, with and without a release-age cutoff, across latest/prefix/exact requests. Verified it fails if hook-env is removed from the prefer-offline list.
  • New unit test for cutoff source provenance; all 1121 unit tests, related e2e suites (test_install_before*, test_install_prefer_offline_no_refresh, test_ls_remote, test_upgrade*, test_outdated, test_which), and lint pass.

Manually verified both directions with an aqua tool: default cutoff → local resolution, no fetch; explicit MISE_MINIMUM_RELEASE_AGE=24h → date-aware remote resolution (unchanged).

Fixes #10308

🤖 Generated with Claude Code


Note

Medium Risk
Changes core version-resolution behavior for all tools on aqua-like backends; explicit minimum_release_age semantics are preserved but the default path is subtly different from 2026.6.2.

Overview
Fixes a performance regression (#10308) where the built-in 24h minimum_release_age default treated every resolution as date-filtered, skipped installed-version fast paths, and triggered remote version-list fetches on commands like mise which and mise hook-env.

Cutoff resolution now records provenance via BeforeDateSource and ResolveOptions.before_date_from_default. The built-in default still applies before_date for remote picks at install time, but filters_installed_versions() only runs for explicit cutoffs (CLI, setting, or per-tool option)—not for the default—so fuzzy requests can resolve from disk when an install already matches.

Resolution paths use shared apply_before_date_for_tool instead of overwriting before_date blindly; upgrade warnings use the same helper. E2e tests assert mise which and mise hook-env do not refetch remote versions when a local install satisfies the request.

Reviewed by Cursor Bugbot for commit 0d075c0. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented unnecessary remote version-list fetches for hook-env and which when an installed tool already satisfies the request, improving reliability and performance.
    • Clarified how the minimum-release-age cutoff is applied so default vs. explicit settings are distinguished, yielding more predictable version resolution and warnings.
  • Tests

    • Added end-to-end regression tests verifying no remote fetches occur in these scenarios.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e6ec9108-2868-4342-8842-0928bc2ca572

📥 Commits

Reviewing files that changed from the base of the PR and between 15da3ee and 0d075c0.

📒 Files selected for processing (8)
  • e2e/cli/test_hook_env_no_remote_fetch
  • e2e/cli/test_which_no_remote_fetch
  • src/cli/install.rs
  • src/cli/upgrade.rs
  • src/cli/use.rs
  • src/install_before.rs
  • src/toolset/tool_request.rs
  • src/toolset/tool_version.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/cli/use.rs
  • src/cli/install.rs
  • e2e/cli/test_which_no_remote_fetch
  • e2e/cli/test_hook_env_no_remote_fetch
  • src/toolset/tool_request.rs
  • src/toolset/tool_version.rs

📝 Walkthrough

Walkthrough

Tracks the source of the resolved install "before" cutoff (Provided, Explicit, Default), preserves provenance in ResolveOptions, uses it to decide whether installed versions are filtered, updates CLI callers to opt out of default-based filtering, and adds e2e tests preventing unnecessary remote version-list fetches.

Changes

Before-date provenance tracking

Layer / File(s) Summary
Before-date source tracking contract and implementation
src/install_before.rs, tests/install_before.rs
BeforeDateSource enum (Provided, Explicit, Default) and new resolve_before_date_for_tool_with_source API return both timestamp and origin. Internal resolver refactored to yield provenance tuples; existing timestamp-only APIs derive from the source-aware resolver. Tests verify source differentiation across default, per-tool, and global settings.
ResolveOptions provenance field and helper methods
src/toolset/tool_version.rs
ResolveOptions gains before_date_from_default: bool field and apply_before_date_for_tool public method to compute cutoff and provenance. Private filters_installed_versions predicate gates filtering: installed versions are allowed when cutoff is default-sourced, filtered when explicit. Display formatting annotates default-sourced cutoffs.
ToolVersion resolution using provenance-aware filtering
src/toolset/tool_version.rs
resolve, latest_version_with_opts, resolve_version, and resolve_prefix now apply cutoff/provenance via apply_before_date_for_tool and consult filters_installed_versions() instead of direct before_date.is_some() checks to respect provenance when deciding whether to filter installed versions.
CLI commands and tool request before-date application
src/cli/install.rs, src/cli/upgrade.rs, src/cli/use.rs, src/toolset/tool_request.rs
install, upgrade, use commands set before_date_from_default: false to indicate CLI-provided cutoffs. ToolRequest::resolve_options delegates before-date computation to the new apply_before_date_for_tool method, removing direct call to the old resolver. The upgrade warning path now applies per-tool cutoffs via cloned ResolveOptions and skips tools without an effective cutoff.
E2E regression tests for no-remote-fetch behavior
e2e/cli/test_which_no_remote_fetch, e2e/cli/test_hook_env_no_remote_fetch
Two regression test scripts verify that mise which and mise hook-env do not trigger remote version-list fetches when an installed version satisfies the request under the built-in default minimum_release_age cutoff, using marker files and cache inspection to detect unwanted remote operations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • jdx/mise#10277: Modifies minimum-release-age cutoff computation in src/install_before.rs; related to this PR's provenance-aware resolver changes.
  • jdx/mise#10279: Introduces the 24h built-in default for release-age; complements this PR's tracking and propagation of default-based cutoffs.
  • jdx/mise#10310: Touches src/install_before.rs cutoff semantics; likely connected to the resolve-before-date logic refactor here.

Poem

🐰 I tunneled through timestamps and flags,
Found where the cutoff came from, not just when.
Defaults stay gentle, installed versions rest,
No distant fetches, no rustling nets,
Hop, hop — versions snug in their den.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: fixing a performance regression where the default release age cutoff was incorrectly disabling installed-version resolution fast paths.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a performance regression introduced in #10279 where the built-in 24h minimum_release_age default caused every tool resolution to disable installed-version fast paths, forcing remote version-list fetches even when a locally installed version already satisfied the request.

  • Adds BeforeDateSource (Provided/Explicit/Default) to install_before.rs and threads provenance into ResolveOptions via a new before_date_from_default flag set by the shared apply_before_date_for_tool helper. The two should_filter_installed_versions gates in resolve_version/resolve_prefix now only skip the installed-version fast-path for explicit cutoffs.
  • Two new e2e tests (test_which_no_remote_fetch, test_hook_env_no_remote_fetch) pin the regression with observable side effects (cache-file presence, marker file) across both default and explicit minimum_release_age configurations. The previous P2 comment about upgrade.rs using the old resolve_before_date_for_tool without source propagation is fully resolved by this PR's refactor to apply_before_date_for_tool.

Confidence Score: 5/5

Safe to merge. The change is narrowly scoped to the installed-version fast-path guards, well-covered by two new regression e2e tests that were verified to fail on unfixed code, and the refactor to apply_before_date_for_tool correctly handles all provenance cases.

The core logic is sound: BeforeDateSource provenance flows cleanly through all construction paths, both should_filter_installed_versions gates were updated consistently, and the upgrade.rs warning section now uses apply_before_date_for_tool which addresses the prior review concern. No installed-version fast-path edge cases appear reachable through broken provenance.

The find call in test_which_no_remote_fetch searches the entire cache dir rather than just the jq subdirectory, which could cause a false failure if other e2e tests share the same MISE_CACHE_DIR.

Important Files Changed

Filename Overview
src/toolset/tool_version.rs Adds before_date_from_default to ResolveOptions, apply_before_date_for_tool, and filters_installed_versions; the two should_filter_installed_versions gates now correctly skip the installed-version fast-path only for explicit cutoffs.
src/install_before.rs Adds BeforeDateSource enum and resolve_before_date_for_tool_with_source; all internal logic is correct and well-tested.
src/cli/upgrade.rs Warning section refactored to use apply_before_date_for_tool, correctly propagating before_date_from_default for default cutoffs. Previous comment's concern is resolved by this PR.
src/toolset/tool_request.rs Replaces manual resolve_before_date_for_tool call with apply_before_date_for_tool, propagating provenance correctly.
src/cli/install.rs Adds before_date_from_default: false to explicit struct literal; correct since this cutoff comes from the CLI flag.
src/cli/use.rs Same as install.rs — adds before_date_from_default: false to the explicit ResolveOptions struct literal.
e2e/cli/test_which_no_remote_fetch New regression test for mise which; the find $MISE_CACHE_DIR -name 'remote_versions*' check scans the entire cache dir and could match other tools' cached files if the cache is shared.
e2e/cli/test_hook_env_no_remote_fetch New regression test for mise hook-env; marker-file approach is robust and tests both default and explicit minimum_release_age across all three version-spec shapes.

Reviews (2): Last reviewed commit: "refactor(upgrade): use apply_before_date..." | Re-trigger Greptile

…version resolution

The built-in 24h minimum_release_age default (#10279) set a before_date on
every resolution, which disabled the installed-version fast paths for all
non-prefer-offline commands (mise which, mise use, ...). Every invocation
then fetched remote version lists for the entire toolset, turning ~75ms
shell-startup calls into ~2.5s each (reported as ~65s shell startups in
discussion #10308).

The built-in default now only gates which versions remote resolution may
pick — its actual purpose of delaying new installs. Explicit cutoffs (the
--minimum-release-age flag, a per-tool minimum_release_age option, or the
minimum_release_age setting) keep their date-aware resolution semantics
from #9269, since opting in was a deliberate choice there.

- install_before: cutoff resolution reports a BeforeDateSource
  (Provided/Explicit/Default) alongside the timestamp
- ResolveOptions: new before_date_from_default flag, set via a shared
  apply_before_date_for_tool helper; the should_filter_installed_versions
  gates in resolve_version/resolve_prefix require an explicit cutoff
- e2e: test_which_no_remote_fetch pins the regression (fails on unfixed
  code); test_hook_env_no_remote_fetch guards the prefer-offline paths so
  hook-env can never start fetching remote versions

Fixes #10308

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jdx jdx force-pushed the claude/clever-borg-53d7eb branch from 15da3ee to d44b36b Compare June 11, 2026 19:53
…arning

Keeps before_date_from_default provenance consistent in the upgrade
warning path instead of reconstructing ResolveOptions with the
provenance-less resolver. Inert today (latest_versions=true bypasses the
installed-version gates) but prevents a future caller of
latest_for_upgrade from inheriting broken provenance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jdx

jdx commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

Addressed the Greptile finding: the upgrade hidden-version warning path now uses apply_before_date_for_tool instead of reconstructing ResolveOptions with the provenance-less resolver, so before_date_from_default stays consistent there too (0d075c0).

This comment was generated by an AI coding assistant.

@github-actions

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 x -- echo 21.0 ± 1.6 18.7 28.3 1.00
mise x -- echo 24.0 ± 3.9 19.3 57.3 1.14 ± 0.21
⚠️ Inconclusive: x -- echo measured 14% slower, but hyperfine reported statistical outliers.

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 env 20.5 ± 1.2 18.5 26.8 1.00
mise env 20.6 ± 1.2 18.5 25.3 1.01 ± 0.08

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 hook-env 20.5 ± 1.1 18.5 25.7 1.00
mise hook-env 21.1 ± 1.1 19.2 27.1 1.03 ± 0.08

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 ls 16.9 ± 1.0 15.1 22.9 1.00
mise ls 18.9 ± 1.4 16.4 27.8 1.12 ± 0.11
⚠️ Inconclusive: ls measured 12% slower, but the relative uncertainty overlaps the 10% threshold.

xtasks/test/perf

Command mise-2026.6.2 mise Variance
install (cached) 146ms 149ms -2%
ls (cached) 66ms 66ms +0%
bin-paths (cached) 79ms 83ms -4%
task-ls (cached) 140ms 144ms -2%

@jdx

jdx commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

Re the hyperfine flags (x -- echo +14%, ls +12%, both marked inconclusive): ran a controlled A/B on one machine — isolated env, 50 runs with 5 warmups, binaries built from merge-base main (4f7e26f) vs this branch:

Command main PR
mise ls 24.1 ± 1.3 ms 22.0 ± 0.6 ms
mise x -- echo hi 40.2 ± 1.5 ms 38.0 ± 1.2 ms
mise hook-env 21.7 ± 1.0 ms 21.3 ± 0.7 ms

No regression (the deltas favor the PR slightly, likely noise). The CI baseline is the released 2026.6.2 binary rather than merge-base, so its delta also includes everything on main since the release.

This comment was generated by an AI coding assistant.

@jdx jdx merged commit 77393ab into main Jun 11, 2026
34 checks passed
@jdx jdx deleted the claude/clever-borg-53d7eb branch June 11, 2026 20:50
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