fix(profiles): keep deleted Desktop bot profiles from reappearing - #94842
fangliquanflq wants to merge 17 commits into
Conversation
Related: #94840 prevents cron-only profile shells from being discovered, while this PR prevents a deleted profile from being recreated by stale multiplex-cron membership. The fixes are complementary and should be reviewed together. |
|
@fangliquanflq Closing my duplicate #95239 in favor of your #94842 (you opened earlier). Two unique contributions offered for absorption: 1. forgetLastProfileForAllConnections() in apps/desktop/src/store/connections.ts (path B: cross-workspace localStorage cleanup; my repro showed deleted profile persisted in $lastProfileByConnection after delete from non-active workspace) 2. SQLite WAL/journal awareness in identity-marker check (LOCAL_PROFILE_IDENTITY_MARKERS should arguably also accept state.db-wal / state.db-journal as evidence of active profile). Happy to rebase and submit a smaller follow-up PR for path B if your patch doesn't already cover it. Either way, thanks for picking up the canonical. |
|
Follow-up after re-checking both points against current head (8dd67e2) — i.e. against what this PR actually does, rather than against my withdrawn #95239: 1. Cross-workspace 2. SQLite WAL/journal awareness in Net: nothing left to absorb from #95239 — one point landed, the other is moot by design. Thanks @fangliquanflq for carrying the canonical fix. |
|
Heads-up, @fangliquanflq — you were the earliest PR on this cluster (before #95239, #96508, #96637, #96643), and most of it is now on main by other routes: cron Two pieces of yours are not on main, which is why this stays open rather than closing: the live |
|
Thanks @fangliquanflq — this landed on main through #113377 (fix(bot-mode): deleted bot profiles stay deleted across cron ticks and updates (#95188, #9), merged as 693430d. Your commits/analysis were carried in with credit (see that PR's body and Co-authored-by trailers); the salvage rebased onto current main, widened to sibling surfaces where the review found gaps, and was live-verified in the real Electron app. Closing this one as superseded — thank you for the fix. |
What does this PR do?
Deleted Desktop bot profiles could silently reappear as unusable cron-only directories, so users could not make profile deletion stick. This change makes explicit deletion durable across long-lived multiplex cron workers while allowing an explicit profile create, import, or rename to restore the name intentionally.
Symptom
After deleting a bot profile in Desktop, the profile returns within the cron ticker interval with only
cron/, lock files,executions.db, output, and heartbeat markers.Impact
Affected users cannot permanently remove bot profiles through the supported UI. The ghost rows are not functional profiles, but continue to appear in the Desktop roster.
Bug Cause
Trigger:
gateway/run.pymultiplex cron startup andcron/scheduler_provider.py::InProcessCronScheduler._start_multiplexCausal chain:
profiles_to_serve()once and passes a frozen list of profile homes to the multiplex cron scheduler.Path.record_ticker_heartbeat()callsensure_dirs(), recreating the deleted profile as a cron-only directory.Why it is wrong: Profile membership is mutable for the lifetime of a gateway, but cron treated its startup snapshot as permanent authority.
Working sibling / contrast: A gateway restart rescans the profiles directory and drops the deleted profile, so the stale path exists only in the long-lived scheduler state.
Ruled out: Bot roster prewarming is not the cron-only recreator. Current Desktop deletion retires pooled profile backends before the REST delete, while the recreated tree contains only files written by cron initialization.
Fix
Profile deletion now publishes a persistent marker outside the removed directory. The authoritative
profiles_to_serve()scan excludes marked names, and the gateway passes a live profile-home supplier to cron so tick and heartbeat phases refresh membership. Explicit profile creation, import, and rename clear the marker only after the new profile is materialized.Related Issue
Closes #94823
Type of Change
Changes Made
hermes_cli/profiles.py- persist deletion intent and clear it on explicit profile materialization.gateway/run.py- provide live multiplex profile membership to cron.cron/scheduler_provider.py- refresh profile homes before ticks and heartbeats.tests/cron/test_scheduler_provider.py- cover deletion without resurrection and intentional recreation.tests/hermes_cli/test_profiles.py- cover deletion markers, failed deletes, and explicit recreation.How to Test
scripts/run_tests.sh tests/cron/test_scheduler_provider.py tests/gateway/test_multiplex_phase0.py -q scripts/run_tests.sh tests/hermes_cli/test_profiles.py -k 'tombstone or rmtree_failure' -q node --test apps/desktop/src/plugins/hermes-bots/tests/bot-delete.test.mjsChecklist
Code
fix(scope):,feat(scope):, etc.)Documentation & Housekeeping
Screenshots / Logs
N/A - automated lifecycle tests exercise the deletion, non-resurrection, and explicit recreation contract.