From db84a7f722e416be82dfa353f6e4cd48e1fd123e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 18:42:27 +0000 Subject: [PATCH] Self-heal stale managed presets on rename/re-point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The managed-preset name embeds the queue name and slot profile, so renaming a queue (or re-pointing a tuned slot at a different profile) minted a fresh preset on the next switch and orphaned the old one in the user's preset list forever. ensureManagedPreset now deletes the preset a slot previously owned whenever its derived name has changed, before saving the new one — scanning every supported API's manager since a re-pointed slot's stale preset may live under a different API, and gated on the manager actually listing the name (deletePreset on a keyed API splices by indexOf and must not run for unknown names). Invariant after this change: a tuned slot owns at most one managed preset at any time; it is renamed-in-effect on queue rename, and removed on slot or queue deletion as before. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01XDAj3aSdkvffKR6ZetqcyV --- src/sampling.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/sampling.js b/src/sampling.js index 1ae2e17..b6bd7c5 100644 --- a/src/sampling.js +++ b/src/sampling.js @@ -212,6 +212,27 @@ export async function ensureManagedPreset(slot, queueName) { if (!presetMgr) return null; const desiredName = managedPresetName(slot, queueName); + + // Self-heal a stale preset: the managed name embeds the queue name and + // profile, so renaming the queue (or re-pointing the slot) would mint a + // new preset and orphan the old one forever. If this slot already owns + // a preset under a different name, delete that one first. The stale + // preset may live under a different API's manager (slot re-pointed + // across APIs), so scan them all — gated on existence, because + // deletePreset on a keyed API splices by indexOf and must never be + // called with a name the manager doesn't list. + const staleName = slot.tuning.presetName; + if (staleName && staleName !== desiredName) { + for (const id of Object.keys(API_PARAM_MAP)) { + const mgr = getPresetManager(id); + if (mgr && mgr.getAllPresets().includes(staleName)) { + try { await mgr.deletePreset(staleName); } + catch (err) { console.error('[Roulette] stale managed preset cleanup failed:', err); } + break; + } + } + } + const snapshot = snapshotCurrentSettings(apiId); if (!snapshot) return null; const tunedSettings = overlayParams(snapshot, slot.tuning.params, apiId);