Filed by the domain:ui PM seat (session_01YBWFb5YgMU5dw8p2VKj16S) from the objectui#8481 dev's measurement (PR #8495). ⛔ Not claimed. Placement of a cross-package predicate is a maintainer call, not a PM one.
The count, measured
Five surfaces each hold their own answer to "is this value empty":
| surface |
predicate |
plugin-detail |
hasCellValue (emptiness.ts) |
plugin-detail |
RelatedList.isValueEmpty |
plugin-list |
ObjectGallery.tsx:571, inline |
plugin-kanban |
ObjectKanban.tsx:604, inline |
@object-ui/fields |
seven private guard idioms across the renderers |
⇒ objectui#8481 was the third rediscovery of the same hole. objectui#8474 and objectui#8459 each fixed it at their own door first.
⚠️ The constraint that decides the shape
The disagreements above the floor are deliberate, and several are on the record:
⇒ any predicate strong enough to satisfy plugin-detail would break a decision already made on the record. Whatever ships can only ever be the weakest common claim — null, undefined, empty string, empty array — with every surface extending it.
Options, costed by the reporting dev
- A — leave the five private answers. Cost: the next consumer rediscovers the hole. This card exists because that already happened three times.
- B — put the weakest common claim in
@object-ui/types or @object-ui/core, below every consumer, and let each surface extend it. Cost: a real cross-package change; every extension point has to be re-justified once. Reporting dev's recommendation, and mine.
- C — export
isEmptyMultiValue from @object-ui/fields and have the two plugin-detail predicates call it. ⛔ Measured wrong: it inverts the dependency for ObjectGallery and ObjectKanban, which would then import a fields helper to decide whether to call a fields renderer.
What the maintainer is actually being asked
Not whether — where, and whether the cost is worth paying now. @object-ui/types and @object-ui/core are both below every consumer; picking between them is a dependency-graph decision this seat should not make on its own. And B is only worth doing if the extension points are re-justified rather than inherited — otherwise it becomes a sixth answer wearing a shared name.
⚠️ Whoever takes it must not collapse the deliberate disagreements. The floor is a floor.
Related
objectui#8481 / PR #8495 (the census: 53 field types × 3 shapes = 159 rendered outputs) · objectui#8474 / PR #8482 ({} is a value, pinned) · objectui#8459 / PR #8476 (RelatedList's local predicate, pinned as deliberately different) · objectui#8489 · objectui#8490 · objectui#8491
Dedup
Bounded: filed by the PM that reviewed the card it came from, with every prior instance cited above. No independent search was run.
Filed by the
domain:uiPM seat (session_01YBWFb5YgMU5dw8p2VKj16S) from the objectui#8481 dev's measurement (PR #8495). ⛔ Not claimed. Placement of a cross-package predicate is a maintainer call, not a PM one.The count, measured
Five surfaces each hold their own answer to "is this value empty":
plugin-detailhasCellValue(emptiness.ts)plugin-detailRelatedList.isValueEmptyplugin-listObjectGallery.tsx:571, inlineplugin-kanbanObjectKanban.tsx:604, inline@object-ui/fields⇒ objectui#8481 was the third rediscovery of the same hole. objectui#8474 and objectui#8459 each fixed it at their own door first.
The disagreements above the floor are deliberate, and several are on the record:
JsonCellRendererdraws the array literal on purpose — objectui#8474 measured{}as a value and pinned it.BooleanCellRenderermust keepfalsea value.DateCellRenderer's!valuedeliberately treats the epoch as empty.RelatedList's local predicate was measured better shaped for a grid than the shared one and pinned as deliberately different (objectui#8459 / PR fix(plugin-detail): RelatedList's column pruning and its cell placeholder share ONE definition of emptiness #8476).⇒ any predicate strong enough to satisfy
plugin-detailwould break a decision already made on the record. Whatever ships can only ever be the weakest common claim —null,undefined, empty string, empty array — with every surface extending it.Options, costed by the reporting dev
@object-ui/typesor@object-ui/core, below every consumer, and let each surface extend it. Cost: a real cross-package change; every extension point has to be re-justified once. Reporting dev's recommendation, and mine.isEmptyMultiValuefrom@object-ui/fieldsand have the twoplugin-detailpredicates call it. ⛔ Measured wrong: it inverts the dependency forObjectGalleryandObjectKanban, which would then import afieldshelper to decide whether to call afieldsrenderer.What the maintainer is actually being asked
Not whether — where, and whether the cost is worth paying now.
@object-ui/typesand@object-ui/coreare both below every consumer; picking between them is a dependency-graph decision this seat should not make on its own. And B is only worth doing if the extension points are re-justified rather than inherited — otherwise it becomes a sixth answer wearing a shared name.Related
objectui#8481 / PR #8495 (the census: 53 field types × 3 shapes = 159 rendered outputs) · objectui#8474 / PR #8482 (
{}is a value, pinned) · objectui#8459 / PR #8476 (RelatedList's local predicate, pinned as deliberately different) · objectui#8489 · objectui#8490 · objectui#8491Dedup
Bounded: filed by the PM that reviewed the card it came from, with every prior instance cited above. No independent search was run.