Migrated from objectstack-ai/objectstack#5432 under the file-at-destination ruling (objectstack-ai/objectstack#7167, maintainer 2026-08-10). Originally filed 2026-08-05T11:11:46Z. The full prior thread — including triage rulings and hold/restart conditions — remains on the source issue and MUST be read before acting on this card.
Observation-class finding, noticed while fixing objectstack#5407. Nothing a user hits today with any urgency — it needs a field gated on two or more controlling fields, which is rare — so it carries finding and no pm:queue. Recording it because objectstack-ai/objectstack#5407 has just established the mechanism that fixes it.
objectstack-ai/objectstack#5407 item 4 established that a list separator is a locale property, and added validation.formInvalidJoiner (per-pack: ", " for Latin scripts and Korean, "、" for zh/ja, U+060C + space for Arabic) after measuring Intl.ListFormat and finding its output unusable for a truncated list.
Two other sites join user-visible names with a hardcoded separator, and they do not even agree with each other:
| Site | Separator | Sentence |
|---|
packages/fields/src/widgets/LookupField.tsx | ", " | lookup.selectFirst |
packages/components/src/renderers/form/form.tsx (option-field gate) | " / " | fields.options.selectFirst |
Both fill the {{fields}} slot of what is deliberately one shared sentence — the form renderer's own comment says the two callers exist so "the gate can never read differently depending on which side produced it" — yet a field gated on two parents reads Select Account, Owner first from the lookup and 请先选择Account / Owner from the select. Under zh/ja both separators are wrong for the script on top of that.
Suggested fix
Reuse the mechanism objectstack-ai/objectstack#5407 added rather than inventing a second one: either read validation.formInvalidJoiner at both sites, or (if the gate hint wants its own punctuation) add one fields.gateJoiner key across the ten packs. Either way it has to be one key read by both callers — two keys would recreate the divergence the shared sentence exists to prevent.
Note for the implementer: LookupField receives the labels through the dependsOnLabels prop objectstack-ai/objectstack#5407 added, so the joining happens in dependsOnFieldsText there; the form's copy is in the gatedHint memo.
Observation-class finding, noticed while fixing objectstack#5407. Nothing a user hits today with any urgency — it needs a field gated on two or more controlling fields, which is rare — so it carries
findingand nopm:queue. Recording it because objectstack-ai/objectstack#5407 has just established the mechanism that fixes it.objectstack-ai/objectstack#5407 item 4 established that a list separator is a locale property, and added
validation.formInvalidJoiner(per-pack:", "for Latin scripts and Korean,"、"for zh/ja, U+060C + space for Arabic) after measuringIntl.ListFormatand finding its output unusable for a truncated list.Two other sites join user-visible names with a hardcoded separator, and they do not even agree with each other:
packages/fields/src/widgets/LookupField.tsx", "lookup.selectFirstpackages/components/src/renderers/form/form.tsx(option-field gate)" / "fields.options.selectFirstBoth fill the
{{fields}}slot of what is deliberately one shared sentence — the form renderer's own comment says the two callers exist so "the gate can never read differently depending on which side produced it" — yet a field gated on two parents readsSelect Account, Owner firstfrom the lookup and请先选择Account / Ownerfrom the select. Under zh/ja both separators are wrong for the script on top of that.Suggested fix
Reuse the mechanism objectstack-ai/objectstack#5407 added rather than inventing a second one: either read
validation.formInvalidJoinerat both sites, or (if the gate hint wants its own punctuation) add onefields.gateJoinerkey across the ten packs. Either way it has to be one key read by both callers — two keys would recreate the divergence the shared sentence exists to prevent.Note for the implementer:
LookupFieldreceives the labels through thedependsOnLabelsprop objectstack-ai/objectstack#5407 added, so the joining happens independsOnFieldsTextthere; the form's copy is in thegatedHintmemo.