Stored values keep rendering across a fork
A record saved last month holds a common item id. Acme has since forked the list.
Ticket #4182
Helpdesk · editing a record saved before Acme forked Priority
Shows the fork's label (“Medium”, renamed by Acme from the common “Normal”) and, when opened, the menu marks the fork's “Medium” option as selected. No visible change beyond the label Acme chose: no badge, no notice, no flicker, no dirty-form marker — to the user it is simply the current value.
stored: front_sli_01jf8k2m3n4p5q6r7s8t9v0wa2 (common “Normal”)effective: front_sli_01jfq3w8z6y5x4c3b2a1n9m8b2 (fork “Medium”)submits: front_sli_01jf8k2m3n4p5q6r7s8t9v0wa2 (unchanged unless the user picks)
The picker's value is not rewritten: the host gave it the stored id and gets the same id
back unless the user picks something else (the picker's contract with its host is unchanged). Both ids keep resolving, so that is always
correct. A host that wants to migrate stored values passes onEffectiveValue(stored, effective); the picker calls it once
per redirected id after a successful resolve, and the host may write the effective id on its own next save — lazily, as the
contract intends. If the user picks a value, the picker emits that option's (fork) id, as for any pick.
Every resolve outcome a stored value can have
Each id renders independently. A batch with a mix of outcomes (some redirected, some missing) is a normal response, not a partial failure.
| Stored id | Situation | Resolve answers | Picker renders |
|---|---|---|---|
| front_sli_…v0wa2 | Common item; Acme has an org fork | fork label + effective_item_id |
Medium |
| front_sli_…v0wa2 | Common item; Acme's fork is private (draft) | common label, no redirect | Normal |
| front_sli_…v0wa3 | Common item; the fork's copy was deleted | falls back to the common item | High |
| front_sli_…m8b6 | Fork-only item (added by Acme); the fork was archived (reverted) | Acme's own item — still resolves, with the item's own status |
Blocker (styled by the returned status; archived → greyed + badge) |
| front_sli_…v0wa4 | Common item archived by the platform after Acme forked; Acme's active org fork still holds its copy | redirected: fork item's label + fork item's status + effective_item_id |
Urgent (fork copy still active — the source's archive does not reach it) |
| front_sli_…v0wa5 | Common item archived by the platform; no redirect applies (no active org fork, or the fork has no non-purged copy of it) | status: archived |
Critical (legacy) archived |
| front_sli_…zz09 | Another customer organization's item, or purged | in missing |
Unknown value |
Archived and missing rendering is unchanged from the approved 4.0.0 picker frame
selection-lists/14-picker-archived: read but not newly selectable; “Unknown value” keeps the id in the form.
States
Resolving a stored value
The stored id is never shown as a label placeholder, and the control is not editable until resolve settles
— choosing a value mid-resolve would race the label (and the host's onEffectiveValue) against the user's pick.
Resolve failed
The stored id stays in the form
untouched — onEffectiveValue is only ever called from a successful resolve.
Saving the form re-submits the original id.
Test hooks: [data-frame='10-picker-stored-values'] · [data-panel='picker'][data-state='redirected'] · [data-selected-label][data-redirected='true'] · [data-migration='host-opt-in'] · [data-persisted] · [data-panel='resolve-matrix'] · [data-resolve-case='redirect'] · [data-resolve-case='private-fork'] · [data-resolve-case='fork-item-purged'] · [data-resolve-case='fork-archived'] · [data-resolve-case='common-archived-redirect'] · [data-resolve-case='common-archived'] · [data-resolve-case='missing'] · [data-missing='true'] · [data-state='resolving'] · [data-state='resolve-error'] · [data-error='resolve-failed'] · [data-action='retry']
Contract: POST /v1/resolve (ResolvedSelectionListItem.effective_item_id, 4.1.0) · SelectionListItem.origin_item_id.
Tokens only — no raw hex, spacing or type outside tokens.css / frame.css.