… F1 v2)
Add a snapshot-before-write + atomic-restore safety net so a user-triggered
/refine can be undone with '/refine undo'.
v2 correction over the dropped first attempt:
- Skill-primary surface (R8): harness logic + docs live in
skills/continual-harness/ (SKILL.md + standalone inspector script); the
CLI is a thin shim. No special-casing in core write paths.
- Data-loss guard: restore refuses to wipe a live dir when its snapshot
storage is missing files the manifest promised (capture/store corruption),
instead reporting the skipped target. A genuinely-empty snapshot target
still restores to empty (legitimate undo).
- Snapshot resolves the live profile skills dir via _skills_dir() (multi-
profile aware) rather than the static import-time SKILLS_DIR.
Implementation:
- agent/refine_rollback.py: stdlib-only snapshot/restore/list/index with the
corruption guard (fully unit-tested, 8 hermetic tests).
- hermes_cli/cli_commands_mixin.py: /refine snapshots memory+skills before the
background fork; new /refine undo restores the latest session snapshot.
- run_agent._spawn_background_review + agent/background_review
(spawn_background_review_thread/_run_review_in_thread): thread snapshot_id
passthrough + 'undo: /refine undo' hint in the completion summary.
- skills/continual-harness/{SKILL.md,scripts/refine_rollback_cli.py}: user
docs + standalone inspector (list/restore/delete/latest).
Off by default: snapshot is opt-in per /refine call; automatic post-turn
reviews unchanged. No conversation/system-prompt mutation (F1 touches only
memory/skill files), so prompt-cache and message-role invariants hold.
Validation: 8 hermetic F1 tests pass; background_review + refine + goals
suites green (24 + 36) with no regressions; py_compile clean.
Summary
Adds a snapshot-before-write + atomic-restore safety net to the existing
/refineso a review run that writes memory/skills can be undone with/refine undo. Ports prime-agent's "reversible self-improvement" feature by extending the existing/refineprimitive — no architecture fork, no prompt-cache or message-role invariant break (F1 touches only memory/skill files).Closes #90283.
Changes
agent/refine_rollback.py(new, stdlib-only, fully unit-tested): snapshot/restore/list/index. Includes a data-loss guard — restore refuses to wipe a live dir when its snapshot storage is missing files the manifest promised (capture/store corruption), reporting the skipped target instead of emptying the user's memory.hermes_cli/cli_commands_mixin.py:/refinesnapshots memory + skills synchronously before the background fork writes (best-effort; never blocks the review). New/refine undorestores the latest session snapshot; surfaces a precise message for the corruption-guard skip case.run_agent._spawn_background_review+agent/background_review(spawn_background_review_thread/_run_review_in_thread): threadsnapshot_idpassthrough +undo: /refine undohint in the completion summary.skills/continual-harness/(skill-primary, R8):SKILL.md+ standalone inspector script (list/restore/delete/latest). Core changes are a thin shim — no special-casing in core write paths (CONTRIBUTING: don't special-case in core).Design notes
/refinecall; automatic post-turn reviews are unchanged.skillsdir via_skills_dir()(multi-profile safe) rather than the static import-timeSKILLS_DIR.HERMES_HOME/review_snapshots/<id>/with a per-session index. v1 covers files only (memory.md+ skills); the SQLite cognitive store is excluded.Relationship to existing work (Step-0 duplicate search, see #90283)
/refinecold-cache false-empty on messaging — unrelated.Test plan
tests/hermes_cli/test_refine_rollback.py: 8 tests (snapshot copy, index, restore, missing, list filter, delete, corruption guard, empty-target undo).test_background_review.py(10), review/isolation suites (24),test_goals.py(36) — green, no regressions in touched modules.py_compileclean on all touched modules.Invariants preserved
/refine.Notes / asks
/refine undothin shim vs. pure skill+config flag; snapshot storage path; v1 file-only scope.