Two small boundaries
This track ends with two boundaries that look minor and are not. One keeps a soul's reference settings from leaking into another soul's. The other keeps Pippa Refine from seeing more than Pippa may see. Both are the same idea at different scales: a piece of work belongs to one identity, and nothing borrowed from a wider view may slip into it.
The bug class: a draft that was not its own
A soul's reference settings are edited in a dialog opened from that soul in Soul collections. The first version, built on the birth night, edited the studio's composition tray directly. The tray is the multi-soul list of images being gathered for a generation. Opening the dialog filled an empty tray with the soul's profile, and saving an override wrote whatever the tray held. Convenient for a minute. Then the failures line up. Open Ttori's settings while the tray holds Pippa's images, save, and Ttori's profile now holds Pippa. Open Pippa's editor, switch to Ttori before Pippa's profile finishes loading, and the late answer paints Pippa into Ttori's dialog. Press save on Pippa, switch to Ttori, and Pippa's save finishing closes Ttori's editor.
The fix landed the same night and gave the editor a draft of its own. Three mechanisms, one for each failure:
- A key per soul. The exported component renders the editor with
key={props.soul.soul_pk}. When the soul changes, React discards the old editor and mounts a fresh one, so no state survives from the previous soul. - A cancelled flag per load. The effect that fetches the profile sets
cancelledin its cleanup, and a response arriving after that is dropped. - An active ref around saves. After an awaited save, the editor checks
active.currentbefore it callsonSavedoronCloseor sets state, so a save that finishes after its editor closed or changed soul touches nothing.
Browsing the library and uploading inside the editor now change the draft, never the tray, and closing discards unsaved edits. Nine component tests in ReferenceProfile.test.tsx pin the behaviour, with names that read like the bug reports they prevent: opens and saves Ttori's own profile while the studio tray contains Pippa, ignores a late previous-soul response in the keyed editor, does not close a new soul's editor when an earlier save finishes. A follow-up minutes later handled an empty registry, after the packaged WebKit test caught a null comparison there: with no soul selected, the settings button is disabled.
Refine is a Pippa turn
The prompt field on the Create image page has a Pippa Refine button. It sends the prompt, the workflow, the chosen subjects and references, and a little context (the collection and its frames, for a set) to POST /api/refine. Avatars resolves the references, then asks Pippa's utility completion to rewrite the prompt as Pippa, under a system prompt that sets the limits: return only the improved English prompt; preserve identity, subjects, emotion, pose, reference order and the intended changes; invent no extra people, change no workflow, generate nothing; consult no playbook.
The interesting part is whose turn it is. The WebUI is an admin surface, and Dad, signed in, can see every soul, protected ones included. Refine does not inherit that view. The route resolves subjects and references with "pippa" as the acting soul and checks the resulting subjects again as Pippa. Its comment says why: Pippa Refine is a Pippa turn: protected subjects are never placed in that turn merely because the admin UI can see them. If the draft names a protected soul Pippa may not see, or uses an image that descends from one, Refine refuses instead of carrying that soul into Pippa's context. It is the confused-deputy problem solved in advance: the helper gets exactly her own authority, not the authority of the screen that called her.
Two more limits are worth naming.
- Words, not pictures. Refine receives the prompt and the context text, never the reference images. The identity rules of the named subjects ride in the context, labelled as rules Avatars appends automatically, so the refined prompt has no reason to restate them.
- A proposal, not an action. The architecture is exact: Refine proposes text; it does not generate, submit, alter references/model/size/count or publish. The answer opens a dialog titled
Pippa’s refined promptwith two buttons,Keep originalandUse refined prompt. Choosing the refined text keeps the one you wrote asoriginal_prompton the request, so the record holds both what Dad wrote and what was sent.
The same idea twice
The editor bug and the Refine rule share a shape. In both, a wider context sat right there: the studio's multi-soul tray, the admin's full view of the registry. In both, the fix scoped the work to one identity and let nothing in from outside it. Track 8 applies the same rule to pixels.