Skip to content

fix: invalidate update cache when local HEAD changes - #18236

Closed
brijr wants to merge 1 commit into
NousResearch:mainfrom
brijr:fix/update-check-cache-head-invalidation
Closed

fix: invalidate update cache when local HEAD changes#18236
brijr wants to merge 1 commit into
NousResearch:mainfrom
brijr:fix/update-check-cache-head-invalidation

Conversation

@brijr

@brijr brijr commented May 1, 2026

Copy link
Copy Markdown

Summary

  • invalidate the update-check cache when the local git HEAD changes
  • read .git/HEAD directly so fresh cache entries survive without extra git subprocesses
  • add a regression test for the stale hermes version update banner after manual pulls/branch moves

Test Plan

  • source venv/bin/activate && python -m pytest tests/hermes_cli/test_update_check.py -q
  • rm -f ~/.hermes/.update_check && source venv/bin/activate && python -m hermes_cli.main version

Root cause

A fresh .update_check cache only keyed off HERMES_REVISION (or null for local git installs), so a manual git pull or branch switch could leave a stale cached "1 commit behind" result visible for up to 6 hours.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels May 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #9670 — same root cause: update-check cache not keyed on HEAD hash, stale after git pull/branch switch. Also overlaps with #9951 and #5359.

@Tranquil-Flow

Copy link
Copy Markdown
Contributor

Hit the exact gap this PR fixes today on main at dbe5d8497 — a git checkout fast-forwarded outside cmd_update() left .update_check reporting behind=2653 for the full 6-hour TTL because embedded_rev is None on git installs and the rev-keying check trivially passes (None == None). Filed reproduction details in #11007 asking the maintainer to reopen.

The approach here looks like the right one — pure-Python .git/HEAD resolution avoids subprocess overhead and the worktree handling (gitdir: pointer) is a nice touch most of the other competing PRs miss.

One thing to flag for the rebase

Since this PR was opened (May 1), check_for_updates() on main reordered the repo_dir resolution to prefer Path(__file__).parent.parent.resolve() over $HERMES_HOME/hermes-agent/ — the comment says "$HERMES_HOME/hermes-agent/ may be a stale copy from --clone-all; Path(file) always resolves to the actual installed checkout." This PR's new prelude:

if not embedded_rev:
    repo_dir = hermes_home / "hermes-agent"
    if not (repo_dir / ".git").exists():
        repo_dir = Path(__file__).parent.parent.resolve()

reinstates the old order. If a profile carries a stale --clone-all copy at $HERMES_HOME/hermes-agent/, _read_git_head will read the stale HEAD and cache a behind keyed to it — same shape of bug, different trigger. Swapping the two if blocks (and the fallback path the inner _check_via_local_git consumes) restores parity with the priority main currently uses.

Two minor polish suggestions

  1. _read_git_head doesn't handle the packed-refs symbolic-ref form (lines starting with # pack-refs with: etc. it does skip — good — but a ref: line inside packed-refs isn't handled). In practice HEAD is rarely symlinked into packed-refs so this is edge-case-of-edge-case.
  2. The cache field name local_head reads slightly oddly next to revhead would be more parallel. Not load-bearing.

Neither blocks the fix. Once rebased onto current main with the path priority restored, this should be ready to go — it's the cleanest of the 5 open PRs targeting this bug and the only one with a regression test for the actual HEAD-changed case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants