The details panel reads its selected file as soon as the page lists. When the
test's source change landed before that read was answered, the page found the
file again on its own (409 -> rescope -> relist), so the card under the old
numbering the test was about to click was gone. Every test in the spec now
waits for that read before changing sources.
Closes#484
The gallery root scope and the Images listing cursor were keyed with a
per-process random key, so every ComfyUI restart made an open tab's
scopes answer 409 source-changed (blank Tag image preview, a Generate
that did nothing) and its cursors fail Load more.
- utils/workspace_keys.py: one random secret in workspace-scope.key
beside the database (owner-only, never config.json or the database),
two derived keys; per-process fallback with a warning. Move library
copies it.
- Cursor v2 binds the listing scope in its MAC instead of sending an
unkeyed hash of the root paths; an unverifiable cursor answers 400
cursor-stale and Images offers Refresh instead of a dead Retry.
- POST /prompt_manager/images/rescope maps a stale target to its
current root only when the held scope was issued for it.
- Images finds a renumbered file again from the inspector, the viewer
and the Tag image dialog (the dialog stays open, draft kept); nothing
else is kept by an old root_index:path key.
- Tag image dialog: a state that blocks Save shows its reason above the
actions with Refresh, disabled actions look disabled, and an empty
preview says "Preview unavailable" (D147).