Skip to content

fix(install): reset tree on conflicting stash apply so Hermes stays runnable - #51390

Closed
xxxigm wants to merge 2 commits into
NousResearch:mainfrom
xxxigm:fix/46791-installer-stash-apply-conflict-reset
Closed

xxxigm wants to merge 2 commits into
NousResearch:mainfrom
xxxigm:fix/46791-installer-stash-apply-conflict-reset

Conversation

@xxxigm

@xxxigm xxxigm commented Jun 23, 2026 •

Copy link
Copy Markdown

Summary

The repository stage of scripts/install.sh and scripts/install.ps1 stashes
local changes, pulls, then git stash applys the user's work back on top. When
that apply conflicts, git writes <<<<<<< Updated upstream /
>>>>>>> Stashed changes markers into the tracked source files.

Both shell installers left those markers behind on a conflicting apply
(install.sh exit 1, install.ps1 throw), bricking the checkout. A
poisoned toolsets.py then raises SyntaxError on import and the gateway
never starts — the exact symptom users hit after switching install methods:

File "...\toolsets.py", line 1
    <<<<<<< Updated upstream
    ^^
SyntaxError: invalid syntax

The hermes update Python path (_restore_stashed_changes) already guards
this: on a conflicting apply it git reset --hard HEAD to the freshly-pulled
tree and keeps the stash for manual recovery. This brings the two shell
installers to parity — fixing the whole bug class across the sibling install
paths.

Changes

  • scripts/install.sh / scripts/install.ps1: after git stash apply,
    detect a conflict via a non-zero exit or unmerged paths
    (git diff --name-only --diff-filter=U). On conflict, git reset --hard HEAD to restore a clean, runnable tree and keep the stash (never
    silently drop the user's work, per the fix(update): stop stash/restore from clobbering desktop source on managed clones #38542 data-loss class). The code
    update itself succeeded, so the install now completes with a runnable Hermes
    instead of aborting on a poisoned tree.
  • install.sh captures the apply exit code with || apply_rc=$? so a failing
    apply doesn't trip set -e before the cleanup runs.
  • tests/test_install_stash_apply_conflict.py: reproduces the conflicting
    apply end-to-end and asserts the tree self-heals (no markers, content matches
    HEAD, stash preserved, install doesn't abort), plus the unchanged clean-apply
    happy path and an install.ps1 source-contract check.

Verification

scripts/run_tests.sh tests/test_install_stash_apply_conflict.py \
  tests/test_install_unmerged_index.py \
  tests/hermes_cli/test_update_autostash.py \
  tests/hermes_cli/test_update_post_pull_syntax_guard.py
# 47 passed
bash -n scripts/install.sh   # syntax OK

Scope

Narrowly targets the conflicting-git stash apply-leaves-markers gap in the
shell installers. Complementary to #47373 (recovery-marker / ref-verify
hardening), which does not clean the poisoned working tree on a conflicting
apply. Does not attempt the broader shared-resolver refactor, so it
intentionally does not auto-close #46791.

Refs #46791

xxxigm added 2 commits June 23, 2026 21:20
…unnable

The installer's update path stashes local changes, pulls, then `git stash
apply`s them back. When that apply conflicts, git writes
`<<<<<<< Updated upstream` markers into tracked source files. Both shell
installers left those markers behind (install.sh `exit 1`, install.ps1
`throw`), bricking the checkout: a poisoned toolsets.py raises SyntaxError
on import and the gateway never starts.

Mirror the `hermes update` Python path (`_restore_stashed_changes`): detect a
conflicting apply via a non-zero exit OR unmerged paths, then `git reset
--hard HEAD` to restore the freshly-pulled tree while KEEPING the stash for
manual recovery. The code update itself succeeded, so the install now
completes with a runnable Hermes instead of aborting on a broken tree.

Refs NousResearch#46791
…pdate path

Reproduces the exact NousResearch#46791 poisoning (a conflicting `git stash apply` that
writes `<<<<<<< Updated upstream` into toolsets.py) and asserts the tree
self-heals: no conflict markers, content matches the pulled HEAD, the stash
is preserved, and the install does not abort. Also covers the unchanged
happy path (clean apply restores work and drops the stash) and an
install.ps1 source-contract check.

Refs NousResearch#46791
@xxxigm xxxigm closed this Jun 23, 2026
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists labels Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Repository stage stash/local-changes handling is fragile and can leave the tree in unrecoverable dirty state after interrupted updates

2 participants