feat(user-memory): restore dismissed memories to the active set (issue 670)

Merged
IC
3d ago
+160-0

Approved issue: #670

What

Adds the reverse edge to the user-memory state machine: a dismissed user memory can be restored to the active set from the dashboard's User Memories page, and running sessions pick the restored entry up again.

Changes

  • packages/plugin/.../user-memory/storage-user-memory.ts: restoreUserMemory(db, id) next to dismissUserMemory — UPDATE user_memories SET status = 'active'. The profile-version bump stays with the caller, matching how dismissUserMemory is used by review-user-memories.
  • packages/dashboard/src-tauri/src/db.rs: restore_user_memory, mirroring dismiss_user_memory including bump_project_user_profile_version on affected > 0, so the cached m[0] block is invalidated for live sessions.
  • Commands: commands.rs (tauri), serve/dispatch.rs (serve mode), main.rs (registration).
  • Frontend: api.ts restoreUserMemory(id); UserMemories.tsx Restore button on dismissed cards, behind the inverse of the Show gate wrapping Dismiss.
  • Tests: Rust restore_user_memory_returns_row_to_active_set_and_bumps_global_profile (row back in the active set, user_profile_version bumped, memory_epoch untouched); TS user-memory restore > returns a dismissed memory to the active set.
  • Docs: dashboard.md notes dismiss is reversible.

Harness coverage (required)

  • OpenCode 1: covered — shared plugin storage (storage-user-memory.ts)
  • OpenCode 2: covered — same source file in the v2 build
  • Pi: covered — same plugin + shared context.db
  • OMP: covered — same plugin + shared context.db
  • Rust module: covered — db.rs + commands.rs + serve/dispatch.rs + main.rs

Notes

The TS restoreUserMemory currently has no in-plugin caller (dashboard restore goes through the Rust path); it mirrors dismissUserMemory as the storage-layer primitive named in the approved shape. Rust changes were not compiled locally (no Rust toolchain on the contributor machine) — they mirror dismiss_user_memory line for line; CI's rust-crates job is the first real build.


Summary by cubic

Adds a Restore action for dismissed user memories so they can be brought back to the active set and injected into <user-profile> again.

Dismissal was previously irreversible from the dashboard. The new restoreUserMemory/restore_user_memory mirrors dismiss at the plugin storage and dashboard Rust layers, sets the memory's status back to active, and bumps the cached user-profile version so running sessions pick up the restored entry. The update is scoped with AND status = 'dismissed', so restoring an already-active row is a no-op that neither rewrites updated_at nor invalidates every running session's cached profile. A Restore button appears on dismissed cards in the User Memories page with the same error and refetch handling as existing memory actions, and the docs now note dismiss is reversible. Tests cover the restored row returning to the active set, the profile-version bump, the no-op case, and dashboard entry points for both Tauri and serve modes.

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no new blocking issue was found.

Summary

Adds Restore for dismissed user memories in the dashboard.

  • Dismissed user memories can return to the active set.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  D[Dismissed memory] -->|Restore| A[Active memory]
  A --> V[Update profile version]
  V --> P[Refresh cached user profile]
  E[Already active] -->|Restore| N[No write or version change]

Reviews (4) · Last reviewed commit: "fix(user-memory): scope restore to dismi..." · Reviewed by Greptile