Skip to content

feat(desktop): worktree agent data sync + retired persona cleanup#728

Open
wpfleger96 wants to merge 5 commits into
mainfrom
wpfleger/worktree-agent-sync-retired-personas
Open

feat(desktop): worktree agent data sync + retired persona cleanup#728
wpfleger96 wants to merge 5 commits into
mainfrom
wpfleger/worktree-agent-sync-retired-personas

Conversation

@wpfleger96
Copy link
Copy Markdown
Collaborator

@wpfleger96 wpfleger96 commented May 22, 2026

Worktree dev builds launched with SPROUT_SHARE_IDENTITY=1 show 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() in migration.rs copies managed-agents.json, personas.json, and teams.json from the canonical xyz.block.sprout.app.dev data directory to the current worktree's data directory, overwriting on every launch. Copy-if-not-exists (the migrate_legacy_data_dir pattern) doesn't work here because pre-existing worktree data dirs already have empty/default files from prior launches.

Guards: SPROUT_SHARE_IDENTITY=1, valid SPROUT_PRIVATE_KEY, canonical dir differs from current dir (via fs::canonicalize for case-insensitive APFS / symlinks), canonical dir exists.

After the copy, scrub_managed_agents_runtime_state() strips runtime_pid and 5 other process-local fields from the copied managed-agents.json using serde_json::Value. Without this, the worktree's kill_stale_tracked_processes sees 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() in personas.rs appends " (retired)" to retired personas' display names, sets is_active = false, and refreshes updated_at. Called from merge_personas() after the existing demotion pass.

Always soft-deprecates, never deletes. Removing records would orphan persona_id references in managed-agents.json and teams.jsonresolve_persona_env fails 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

  • Extracted sibling_data_dir() helper shared by legacy_data_dir and canonical_dev_data_dir
  • Expanded migration.rs module docstring to cover both legacy migration and worktree sync
  • Documented SHARED_AGENT_FILES / LEGACY_FILES relationship and identity.key exclusion
  • Wired sync_shared_agent_data into lib.rs setup hook after migrate_legacy_data_dir, before restore_managed_agents_on_launch
  • Bumped file-size overrides for migration.rs (640) and personas.rs (980)

@wpfleger96 wpfleger96 force-pushed the wpfleger/worktree-agent-sync-retired-personas branch from 1f346d8 to 22f245a Compare May 22, 2026 21:29
@wpfleger96 wpfleger96 changed the title feat(desktop): worktree agent data sync + retired persona cleanup feat(desktop): worktree agent data sync, retired persona cleanup, and generalized skill symlinks May 22, 2026
@wpfleger96 wpfleger96 force-pushed the wpfleger/worktree-agent-sync-retired-personas branch 2 times, most recently from 55e79bd to 737773a Compare May 23, 2026 00:48
@wpfleger96 wpfleger96 changed the title feat(desktop): worktree agent data sync, retired persona cleanup, and generalized skill symlinks feat(desktop): worktree agent data sync + retired persona cleanup May 23, 2026
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.
@wpfleger96 wpfleger96 force-pushed the wpfleger/worktree-agent-sync-retired-personas branch from 737773a to 4481cd9 Compare May 23, 2026 00:54
@wpfleger96 wpfleger96 marked this pull request as ready for review May 23, 2026 17:15
@wpfleger96 wpfleger96 requested a review from a team as a code owner May 23, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant