mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-27 11:22:03 +00:00
fix(update): default pre-update backup to off (#52729)
The pre-update HERMES_HOME zip shipped on by default (DEFAULT_CONFIG + runtime fallback both True), so every `hermes update` zipped the entire ~/.hermes — sessions DB, caches, skills — adding minutes to each update. The shipped cli-config.yaml.example, the --backup help, and the example config all already said "off by default," so the live default contradicted its own documentation. Flip the default to off everywhere: DEFAULT_CONFIG, the runtime `.get(..., False)` fallback in _run_pre_update_backup, and the stale --backup help string. Users who want the #48200 safety net opt in via updates.pre_update_backup: true or --backup for a single run. Updated test_default_enabled_creates_backup -> test_default_disabled_is_silent to assert the new default (silent no-op, no zip).
This commit is contained in:
parent
e4ff494860
commit
208f0d7c3b
4 changed files with 23 additions and 27 deletions
|
|
@ -2784,14 +2784,14 @@ DEFAULT_CONFIG = {
|
|||
"updates": {
|
||||
# Run a full ``hermes backup``-style zip of HERMES_HOME before every
|
||||
# ``hermes update``. Backups land in ``<HERMES_HOME>/backups/`` and
|
||||
# can be restored with ``hermes import <path>``. Defaults to true
|
||||
# after the #48200 incident: a ``hermes update --yes`` run that
|
||||
# computed a wrong path silently wiped the user's ``.env``,
|
||||
# ``MEMORY.md``, ``kanban.db``, custom skills, and scripts in one
|
||||
# go. The cost of a few minutes of zip time per update is
|
||||
# negligible compared to the alternative. Set to false to opt
|
||||
# out, or pass ``--no-backup`` for a single update run.
|
||||
"pre_update_backup": True,
|
||||
# can be restored with ``hermes import <path>``. Off by default:
|
||||
# zipping a large HERMES_HOME (sessions DB, caches, skills) can add
|
||||
# minutes to every update. The #48200 incident — a ``hermes update
|
||||
# --yes`` run that computed a wrong path and silently wiped the
|
||||
# user's ``.env``, ``MEMORY.md``, ``kanban.db``, custom skills, and
|
||||
# scripts — is the reason this knob exists; enable it (here, or via
|
||||
# ``--backup`` for a single run) if you want that safety net.
|
||||
"pre_update_backup": False,
|
||||
# How many pre-update backup zips to retain. Older ones are pruned
|
||||
# automatically after each successful backup. Values below 1 are
|
||||
# floored to 1 — the backup just created is always preserved. To
|
||||
|
|
|
|||
|
|
@ -8324,13 +8324,12 @@ def _run_pre_update_backup(args) -> None:
|
|||
cfg = {}
|
||||
|
||||
updates_cfg = cfg.get("updates", {}) if isinstance(cfg, dict) else {}
|
||||
# The default config ships with ``pre_update_backup: true`` (see
|
||||
# ``hermes_cli/config.py``). Fall back to true if the key is missing
|
||||
# (e.g. a user has an older custom config without the field). The
|
||||
# ``False`` default from before #48200 caused silent data loss when
|
||||
# an update step computed a wrong path — the cost of a few minutes
|
||||
# of zip time per update is negligible compared to the alternative.
|
||||
enabled = updates_cfg.get("pre_update_backup", True)
|
||||
# The default config ships with ``pre_update_backup: false`` (see
|
||||
# ``hermes_cli/config.py``). Fall back to false if the key is missing
|
||||
# so the default behaviour matches the shipped config: zipping a large
|
||||
# HERMES_HOME can add minutes to every update. Users who want the
|
||||
# #48200 safety net opt in via the config knob or ``--backup``.
|
||||
enabled = updates_cfg.get("pre_update_backup", False)
|
||||
keep = updates_cfg.get("backup_keep", 5)
|
||||
|
||||
if not enabled and not force_backup:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def build_update_parser(subparsers, *, cmd_update: Callable) -> None:
|
|||
"--backup",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Force a pre-update backup for this run (off by default; overrides updates.pre_update_backup)",
|
||||
help="Force a pre-update backup for this run (off by default; overrides updates.pre_update_backup=false)",
|
||||
)
|
||||
update_parser.add_argument(
|
||||
"--yes",
|
||||
|
|
|
|||
|
|
@ -1863,21 +1863,18 @@ class TestRunPreUpdateBackup:
|
|||
backups = list((hermes_home / "backups").glob("pre-update-*.zip"))
|
||||
assert len(backups) == 1
|
||||
|
||||
def test_default_enabled_creates_backup(self, hermes_home, capsys):
|
||||
"""With the new safe default (``pre_update_backup: true``), every
|
||||
``hermes update`` creates a backup before any destructive step
|
||||
runs — the cost is a few minutes of zip time vs. the alternative
|
||||
of silent total data loss of ``~/.hermes/`` observed in #48200
|
||||
when an update step computes a wrong path and the user had no
|
||||
safety net.
|
||||
def test_default_disabled_is_silent(self, hermes_home, capsys):
|
||||
"""With the default (``pre_update_backup: false``), ``hermes update``
|
||||
does NOT create a backup and stays silent — zipping a large
|
||||
HERMES_HOME can add minutes to every update. Users who want the
|
||||
#48200 safety net opt in via the config knob or ``--backup``.
|
||||
"""
|
||||
from hermes_cli.main import _run_pre_update_backup
|
||||
_run_pre_update_backup(Namespace(no_backup=False, backup=False))
|
||||
out = capsys.readouterr().out
|
||||
assert "Creating pre-update backup" in out
|
||||
assert "Saved:" in out
|
||||
backups = list((hermes_home / "backups").glob("pre-update-*.zip"))
|
||||
assert len(backups) == 1
|
||||
assert out == ""
|
||||
assert not list((hermes_home / "backups").glob("pre-update-*.zip")) \
|
||||
if (hermes_home / "backups").exists() else True
|
||||
|
||||
def test_no_backup_flag_skips(self, hermes_home, capsys):
|
||||
from hermes_cli.main import _run_pre_update_backup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue