feat(desktop): worktree agent data sync + retired persona cleanup#728
Open
wpfleger96 wants to merge 5 commits into
Open
feat(desktop): worktree agent data sync + retired persona cleanup#728wpfleger96 wants to merge 5 commits into
wpfleger96 wants to merge 5 commits into
Conversation
1f346d8 to
22f245a
Compare
55e79bd to
737773a
Compare
Worktree dev builds (SPROUT_SHARE_IDENTITY=1) had empty agent panels because each worktree gets its own data directory that was never seeded. Copy-with-overwrite on every launch syncs the 3 agent JSON files from the canonical dev data dir, so worktrees see the same agents/personas/ teams as the main instance. Also cleans up 6 retired personas (Orchestrator, Researcher, Planner, Builder, Refactor, Reviewer) that persist from before the Solo/Kit/Scout transition -- unmodified ones are removed, user-customized ones are soft-deprecated as "<Name> (retired)" with is_active=false.
Both files grew past the default 500/900-line limits with the worktree sync and retired persona migration additions.
…sona migration The worktree agent-data sync copied managed-agents.json with runtime_pid values intact, causing the worktree instance to kill the canonical instance's running agents. The retired persona migration removed unmodified records, orphaning persona_id references in managed-agents.json and teams.json. The same-dir guard used byte comparison, which fails on case-insensitive APFS. Key changes: - Scrub runtime_pid and 5 other volatile fields from copied managed-agents.json after sync (new scrub_managed_agents_runtime_state) - Always soft-deprecate retired personas (never delete), preserving the user's display name and refreshing updated_at - Use fs::canonicalize for the same-dir guard to handle symlinks and case-insensitive FS - Extract sibling_data_dir helper to DRY legacy_data_dir and canonical_dev_data_dir - Expand module docstring, SHARED_AGENT_FILES doc, and lib.rs ordering comment - Replace tautology test, expand idempotency test to 4 cases, fix clippy &mut Vec → &mut [_] lint
cargo fmt expanded assert! blocks from single lines to multi-line, pushing the file past the 620-line limit.
737773a to
4481cd9
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.
Worktree dev builds launched with
SPROUT_SHARE_IDENTITY=1show empty agent panels because each worktree gets its own~/Library/Application Support/<identifier>/data directory that starts with empty defaults. Meanwhile, users who ran Sprout before the Solo/Kit/Scout transition still carry 6 retired personas (Builder, Orchestrator, Planner, Refactor, Researcher, Reviewer) that clutter their persona list.This PR adds two things: a per-launch data sync from the canonical dev instance to worktree instances, and a migration that soft-deprecates retired personas.
Worktree agent-data sync
sync_shared_agent_data()inmigration.rscopiesmanaged-agents.json,personas.json, andteams.jsonfrom the canonicalxyz.block.sprout.app.devdata directory to the current worktree's data directory, overwriting on every launch. Copy-if-not-exists (themigrate_legacy_data_dirpattern) doesn't work here because pre-existing worktree data dirs already have empty/default files from prior launches.Guards:
SPROUT_SHARE_IDENTITY=1, validSPROUT_PRIVATE_KEY, canonical dir differs from current dir (viafs::canonicalizefor case-insensitive APFS / symlinks), canonical dir exists.After the copy,
scrub_managed_agents_runtime_state()stripsruntime_pidand 5 other process-local fields from the copiedmanaged-agents.jsonusingserde_json::Value. Without this, the worktree'skill_stale_tracked_processessees the canonical instance's PIDs as stale and kills its running agents.agents/packs/is intentionally excluded — recursive directory sync is out of scope. Pack personas appear in the worktree but ACP processes that read pack files at runtime may fail; install packs in the worktree separately if needed.Retired persona migration
migrate_retired_personas()inpersonas.rsappends" (retired)"to retired personas' display names, setsis_active = false, and refreshesupdated_at. Called frommerge_personas()after the existing demotion pass.Always soft-deprecates, never deletes. Removing records would orphan
persona_idreferences inmanaged-agents.jsonandteams.json—resolve_persona_envfails closed on missing personas, blocking agent spawn. The cost is 6 extra records for pre-transition users. Preserves the user's display name (a persona renamed to "My Reviewer" becomes "My Reviewer (retired)"). Idempotent: already-retired records are skipped on subsequent launches.Other changes
sibling_data_dir()helper shared bylegacy_data_dirandcanonical_dev_data_dirmigration.rsmodule docstring to cover both legacy migration and worktree syncSHARED_AGENT_FILES/LEGACY_FILESrelationship andidentity.keyexclusionsync_shared_agent_dataintolib.rssetup hook aftermigrate_legacy_data_dir, beforerestore_managed_agents_on_launchmigration.rs(640) andpersonas.rs(980)