From a172d76f2d334db4d36df46a375eb54b4145efd0 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Mon, 14 Sep 2026 17:58:39 -0700 Subject: [PATCH] fix(update): also ignore backups/ and the vault on flat installs; document the flat-install rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `backups/` is where the pre-update snapshot the updater restores a swept state.db FROM lives — leaving it unignored means the recovery copy is swept together with the live database. `vault.key`/`vault.json.enc` are the local secret vault. Docs: website/docs/getting-started/updating.md explains that on a flat install (checkout root == $HERMES_HOME) runtime state is git-ignored and never enters the autostash. --- .gitignore | 8 ++++++-- .../test_update_flat_install_state_gitignore.py | 3 +++ website/docs/getting-started/updating.md | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 53c8faa1ab..d20a120afc 100644 --- a/.gitignore +++ b/.gitignore @@ -174,8 +174,9 @@ docs/superpowers/* # WAL/SHM/journal sidecars and retired-WAL capture dirs, the legacy transcripts, # the cron job store (jobs.json) and executions ledger, gateway lock/pid/state # files, cache/spill directories, and the profile's own config/credential/ -# memory/profile/pairing roots are Hermes-managed runtime state, never code -# changes. (`*-snapshots/` above already covers state-snapshots/.) +# memory/profile/pairing roots, the pre-update backups (the very copies a +# swept state.db is restored from) and the secret vault are Hermes-managed +# runtime state, never code changes. (`*-snapshots/` above already covers state-snapshots/.) # Ignore them so `hermes update`'s `git stash push --include-untracked` cannot # sweep the live state.db/-wal into the stash and unlink it under the running # gateway (#110648). Nested installs keep all of this under $HERMES_HOME outside @@ -219,6 +220,9 @@ docs/superpowers/* /mcp-tokens/ /pairing/ /platforms/ +/backups/ +/vault.key +/vault.json.enc # Persistent dev sandbox dir (scripts/dev-sandbox.sh --persistent) .hermes-sandbox/ diff --git a/tests/hermes_cli/test_update_flat_install_state_gitignore.py b/tests/hermes_cli/test_update_flat_install_state_gitignore.py index 10abde0017..8c6183beb5 100644 --- a/tests/hermes_cli/test_update_flat_install_state_gitignore.py +++ b/tests/hermes_cli/test_update_flat_install_state_gitignore.py @@ -68,6 +68,9 @@ FLAT_INSTALL_RUNTIME_STATE = ( "mcp-tokens/server.json", "pairing/telegram.json", "platforms/pairing/x.json", + "backups/2026-09-14T06-00-00-pre-update/state.db", + "vault.key", + "vault.json.enc", ) diff --git a/website/docs/getting-started/updating.md b/website/docs/getting-started/updating.md index 85ef1a7de4..8543137cc8 100644 --- a/website/docs/getting-started/updating.md +++ b/website/docs/getting-started/updating.md @@ -89,6 +89,8 @@ When the parked branch has **uncommitted changes** (dirty tree), Hermes does **n When you run `hermes update` in a terminal, Hermes stashes any uncommitted source-tree changes, pulls, then **asks** whether to restore them — exactly as it always has. Nothing changes for interactive updates. +The autostash only ever covers *source-tree* changes. On a **flat install** — where the git checkout root is also `$HERMES_HOME` (for example an install made with `HERMES_INSTALL_DIR=$HERMES_HOME`, or one created by an older installer) — the profile's runtime state (`state.db` and its WAL/SHM sidecars, `state-snapshots/`, `backups/`, `sessions/`, `cron/jobs.json`, `cron/executions.db`, `config.yaml`, `auth.json`, `memories/`, lock/pid files, …) lives inside the checkout as untracked files. Those paths are git-ignored, so the autostash never touches them and the running gateway keeps its database through the update. If you keep other untracked files in a flat install's root, move them out of the checkout or add them to `.git/info/exclude`; anything untracked and not ignored is swept into the autostash like a source edit. + When the update runs **without a terminal** — from the desktop/chat app's "Update" button or a gateway-triggered update — there's no prompt to answer. The `updates.non_interactive_local_changes` setting decides what happens to your stashed changes: ```yaml