mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(skills_sync): don't poison manifest on new-skill collision
When a new bundled skill's name collided with a pre-existing user skill (from hub, custom, or leftover), sync_skills() recorded the bundled hash in the manifest even though the on-disk copy was unrelated to bundled. On the next sync, user_hash != origin_hash (bundled_hash) marked the skill as "user-modified" permanently, blocking all bundled updates for that skill until the user ran `hermes skills reset`. Fix: only baseline the manifest entry when the user's on-disk copy is byte-identical to bundled (safe to track — this is the reset re-sync or coincidentally-identical install case). Otherwise skip the manifest write entirely: the on-disk skill is unrelated to bundled and shouldn't be tracked as if it were. This preserves reset_bundled_skill()'s re-baseline flow (its post-delete sync still writes to the manifest when user copy matches bundled) while fixing the poisoning scenario for genuinely unrelated collisions. Adds two tests following the existing test_failed_copy_does_not_poison_manifest pattern: one verifying the manifest stays clean after a collision with differing content, one verifying no false user_modified flag on resync.
This commit is contained in:
parent
91d6ea07c8
commit
3a97fb3d47
2 changed files with 69 additions and 2 deletions
|
|
@ -206,9 +206,18 @@ def sync_skills(quiet: bool = False) -> dict:
|
|||
# ── New skill — never offered before ──
|
||||
try:
|
||||
if dest.exists():
|
||||
# User already has a skill with the same name — don't overwrite
|
||||
# User already has a skill with the same name — don't overwrite.
|
||||
# Only baseline in the manifest when the on-disk copy is
|
||||
# byte-identical to bundled (e.g. a reset that re-syncs, or
|
||||
# a coincidentally identical install); that case is harmless
|
||||
# to track. If the copy differs (custom skill, hub-installed,
|
||||
# or user-edited) skip the manifest write: recording
|
||||
# bundled_hash there would poison update detection by making
|
||||
# user_hash != origin_hash read as "user-modified" on every
|
||||
# subsequent sync, permanently blocking bundled updates.
|
||||
skipped += 1
|
||||
manifest[skill_name] = bundled_hash
|
||||
if _dir_hash(dest) == bundled_hash:
|
||||
manifest[skill_name] = bundled_hash
|
||||
else:
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copytree(skill_src, dest)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue