fix(desktop): repair team-persona mismatch and deduplicate legacy imports#949
Merged
wpfleger96 merged 1 commit intoJun 10, 2026
Merged
Conversation
1c222c9 to
a65a37e
Compare
…orts Teams created before PR 852 store the pack manifest ID (e.g. com.wpfleger.sietch-tabr) in PersonaRecord.source_team but the sync and delete predicates compared against TeamRecord.id (a UUID). Additionally TeamRecord.source_dir was often null, so the sync gate never passed. Introduces team_persona_key() as the single derivation used by sync, delete-cascade, and import — extracts the directory name from source_dir (the manifest ID), falling back to team.id for non-directory teams. On launch, sync_team_personas runs a one-time idempotent repair: 1. Backfills source_dir by matching persona source_team values to directories under teams/ 2. Deduplicates PersonaRecords sharing (source_team, slug) — keeps newest by updated_at desc / id asc, repoints TeamRecord.persona_ids and ManagedAgentRecord.persona_id to the winner 3. Self-healing scrub removes any dangling references that point to persona IDs not in the surviving set (crash-window recovery) Saves are ordered reference-holders-first (teams, agents) before the personas they point to, so a crash mid-repair leaves over-pointing (harmless) rather than dangling references (permanent). All repair logic — derivation, backfill, dedup, and the launch orchestrator — lives in team_repair.rs, keeping teams.rs under the base 1000-line file size limit without a per-file override. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
a65a37e to
a4d6620
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
This is the fix for the bug this channel is named for: editing a persona's
system_promptin the source config and relaunching the app did not update the prompt shown in the UI.Wes's #930 ("persona is source of truth at spawn") was supposed to fix exactly this. It made the spawn site resolve the prompt from the live persona record instead of a cached or pack-bundled copy. And it worked — for teams created after #852.
But the symptom persisted for older teams. The reason is upstream of Wes's change: for teams created before #852,
sync_team_from_dirnever ran. A team/persona identity mismatch combined with a nullsource_dirmeant the sync gate never passed, so the source files on disk were never read back into the persona records. Wes's spawn-time code faithfully read the "live record" — but that record had never been refreshed from disk, so it still held the stale prompt.#949 closes that upstream gap. It backfills
source_dir, fixes the matching predicate so sync actually fires for legacy teams, and dedupes the duplicate personas those legacy imports left behind. Once sync refreshes the records, Wes's #930 spawn-time read finally sees the edited prompt — and system prompts update on relaunch the way they always should have.Problem
Teams created before #852 have a three-way identity mismatch:
PersonaRecord.source_teamholds the pack manifest ID (e.g.com.wpfleger.sietch-tabr)TeamRecord.id(a UUID)TeamRecord.source_dirwas often null for legacy teams, so the sync gate never passedThis caused
sync_team_from_dirto skip these teams entirely, and repeated imports created duplicatePersonaRecords.Solution
Shared matching predicate:
team_persona_key()extracts the directory name fromsource_dir(the manifest ID), falling back toteam.id. Sync, delete-cascade, and import all route through it — the three paths can never disagree about identity.One-time launch repair (idempotent, self-healing):
source_dirby matching personasource_teamvalues to directories underteams/PersonaRecords sharing(source_team, slug)— keeps newest byupdated_atdesc /idasc, repointsTeamRecord.persona_idsandManagedAgentRecord.persona_idto the winnerCrash safety: Saves are ordered reference-holders-first (teams, agents) before the personas they point to. A crash mid-repair leaves over-pointing (harmless, converges on next launch) rather than dangling references (permanent).
File size: Repair logic extracted to
team_repair.rsto stay within the 1020-line cap onteams.rs.Constraints honored
team.idfallback namespace (UUIDs) is near-disjoint from manifest IDs (dotted reverse-domain) — collision near-zero probability (noted, not fixed)Changes
desktop/src-tauri/src/managed_agents/team_repair.rs— new module:team_persona_key(),backfill_source_dirs(),dedup_personas(),sync_team_personas()desktop/src-tauri/src/managed_agents/teams.rs— uses sharedteam_persona_keyin sync/delete/import pathsdesktop/src-tauri/src/managed_agents/mod.rs— declares and re-exportsteam_repair