Editor: reset confirmation must list every key the reset wipes
The reset confirmation read per-scene scene_refinement_keys (which drops keys via its divergence fallback), but the backend _v2_reset_prompt_keys wipes the scene-count-independent pool (prompt_scene_shortcut_keys all_keys). So a second key being trained could be reset without ever being listed in the confirmation — a silent wipe. Expose refinement_key_pool on the preview (= refinement_keys_in_text over the whole prompt, which equals the backend's all_keys) and list the reset confirmation from it. Verified pool == backend reset set, including the divergence case where the per-scene list showed nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ec8b5005b9
commit
0b72037c5b
@@ -2,6 +2,14 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
- "Reset Studio session" silently wiped keys it never listed. The confirmation read the per-scene
|
||||
`scene_refinement_keys` (which drops keys via its divergence fallback), while the backend reset
|
||||
wipes the scene-count-independent **pool** (`prompt_scene_shortcut_keys.all_keys` — every key
|
||||
fired in the prompt). So a second key you were training could be cleared without ever appearing
|
||||
in the confirmation. The preview now exposes `refinement_key_pool` (mirrors the backend reset
|
||||
exactly) and the confirmation lists from it, so what's shown is precisely what gets wiped.
|
||||
|
||||
## [3.0.2] - 2026-06-15
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -102,6 +102,19 @@ def scene_refinement_keys(prompt: str, scene_count: int, default_key: str = "def
|
||||
return out
|
||||
|
||||
|
||||
def refinement_key_pool(prompt: str) -> list:
|
||||
"""Every non-default refinement key whose shortcut fires anywhere in the prompt — the exact
|
||||
set a Studio session reset will wipe. Scene-count independent, so it mirrors the backend
|
||||
`_v2_reset_prompt_keys` (which clears `prompt_scene_shortcut_keys(...).all_keys`), NOT the
|
||||
per-scene `scene_refinement_keys` (whose divergence fallback can drop a key the reset still
|
||||
wipes). Used so the reset confirmation lists exactly what will be cleared."""
|
||||
keys_in_text = _funpack_attr("conditioning", "refinement_keys_in_text")
|
||||
try:
|
||||
return sorted(k for k in keys_in_text(str(prompt or "")) if k)
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
|
||||
def validate_generation_prompt(full, target) -> dict:
|
||||
"""Build the generation prompt and run fingerprint; track changes since last queue."""
|
||||
from .timeline import (
|
||||
|
||||
@@ -2811,16 +2811,23 @@
|
||||
);
|
||||
}
|
||||
|
||||
// Every refinement key a reset will wipe: the project/default key plus every non-default
|
||||
// key whose shortcut fires in the current prompt (those keys also get TRAINED per scene, so
|
||||
// a reset must clear them too). Mirrors the backend _v2_reset_prompt_keys union.
|
||||
// Every refinement key a reset will wipe: the project/default key plus every non-default key
|
||||
// whose shortcut fires anywhere in the prompt. Uses the scene-count-independent
|
||||
// refinement_key_pool, which mirrors the backend _v2_reset_prompt_keys EXACTLY — the per-scene
|
||||
// scene_refinement_keys can drop a key via its divergence fallback, which would under-report and
|
||||
// let the reset silently wipe a key the user wasn't warned about. Falls back to the per-scene
|
||||
// list only for an older preview payload without the pool.
|
||||
function sessionResetKeys() {
|
||||
const pv = state.preview || {};
|
||||
const defKey = (state.project?.refinement_key || "default").trim() || "default";
|
||||
const out = new Set([defKey]);
|
||||
(pv.scene_refinement_keys || []).forEach((rk) => {
|
||||
if (rk && !rk.uses_default) (rk.keys || []).forEach((k) => { if (k) out.add(k); });
|
||||
});
|
||||
if (Array.isArray(pv.refinement_key_pool)) {
|
||||
pv.refinement_key_pool.forEach((k) => { if (k) out.add(k); });
|
||||
} else {
|
||||
(pv.scene_refinement_keys || []).forEach((rk) => {
|
||||
if (rk && !rk.uses_default) (rk.keys || []).forEach((k) => { if (k) out.add(k); });
|
||||
});
|
||||
}
|
||||
return [...out];
|
||||
}
|
||||
|
||||
|
||||
@@ -1144,6 +1144,7 @@ if web is not None and PromptServer is not None:
|
||||
result["parsed_scenes"] = len(parsed.get("scenes", []))
|
||||
result["scene_refinement_keys"] = bridge.scene_refinement_keys(
|
||||
prompt, len(parsed.get("scenes", [])), p.refinement_key)
|
||||
result["refinement_key_pool"] = bridge.refinement_key_pool(prompt)
|
||||
except Exception as e: # noqa: BLE001
|
||||
result["parse_error"] = str(e)
|
||||
return web.json_response(result)
|
||||
@@ -1161,6 +1162,7 @@ if web is not None and PromptServer is not None:
|
||||
result["parsed_scenes"] = got
|
||||
result["scene_refinement_keys"] = bridge.scene_refinement_keys(
|
||||
prompt, got, p.refinement_key)
|
||||
result["refinement_key_pool"] = bridge.refinement_key_pool(prompt)
|
||||
if expected and got != expected:
|
||||
result["warning"] = (
|
||||
f"Studio split produced {got} scene(s) but the timeline has {expected}. "
|
||||
|
||||
Reference in New Issue
Block a user