Files
buzz/desktop/src-tauri
Will Pfleger 25536f07c4 feat(personas): sync symlinked pack changes on read
When a persona pack is installed as a symlink, edits to the pack source
files are never reflected in the running app — import_persona_pack()
snapshots data into personas.json at install time and all runtime reads
go through that snapshot exclusively.

Add sync_packs_from_dir() / sync_one_pack() (pure, testable) and a thin
sync_symlinked_packs() AppHandle wrapper. The sync step is inserted into
load_personas() after merge_personas(), reusing the existing read →
reconcile → write-back pattern. The frontend's 30s poll on
usePersonasQuery() becomes the refresh trigger with zero new
infrastructure.

Key design decisions:
- Mtime short-circuit: stat the symlink target dir before calling
  resolve_pack(). Unchanged mtime = skip. Common case pays one stat()
  per symlinked pack instead of a full re-parse.
- Quick pre-scan in the AppHandle wrapper: if no symlinked packs exist,
  managed_agents.json is never loaded (Thufir's concern about the hot
  path loading two JSON files on every poll).
- Removal safety gate: when a persona is removed from the source pack
  but a managed agent still references it by persona_id UUID, deactivate
  (is_active = false) rather than delete to avoid orphaning running
  agents. managed_agents.json is only loaded when removals are detected.
- Non-symlinked packs are completely unaffected.
- Broken symlinks (canonicalize fails) log a warning and are skipped.
- name_pool is always Vec::new() for pack personas (matches existing
  import_persona_pack() behavior).
2026-06-06 14:59:24 -04:00
..