Observation-class finding, measured while doing objectui#4389 (PR #4404). Nothing a user hits today — all three copies behave identically, and this one is fully pinned on its own surface. Filing so the last copy is retired deliberately rather than found later as drift, exactly as #4389 was.
What was found
objectui#4389 named two copies of the analytics label-net glue (plugin-dashboard's DatasetWidget and plugin-report's useDatasetDimensionLabels) and PR #4404 retired both. There is a third, which #4389 did not name and PR #4404 deliberately left alone as out of scope: packages/plugin-charts/src/ObjectChart.tsx.
It is the same shape, in the same order:
packages/plugin-charts/src/ObjectChart.tsx:259 — const apiFetch = context?.apiFetch;
:300 — locale-free optionMeta state, with a header saying why it is locale-free (objectui#4030), nearly word-for-word the one the other two carried
:355 — const doFetch = apiFetch ?? fetch;
:411 — apiFetch in the effect's deps (objectui#4121)
:422-448 — a translatorFor(path) closure and a buildDimensionLabelMap loop
translatorFor at :427 is logically identical to the two that PR #4404 deleted, down to the comment ("Bound to the object that OWNS the terminal field — crm_account for crm_account.industry, not the dataset's base object").
Why this is smaller than #4389 was
PR #4404 landed the React-free half in @object-ui/core:
dimensionOptionTranslator(meta, fieldOptionLabel) — exactly translatorFor
deriveDimensionLabelMaps(metaByPath, relabel, fieldOptionLabel) — exactly the loop
loadDimensionFieldMeta(loadObjectSchema, object, fieldPaths) — the read composition
So the derivation half is a pure-function swap with no React-layer change and no new dependency: plugin-charts already depends on @object-ui/core.
The hook half does not transfer as-is, and that is the part needing a decision rather than a patch. ObjectChart differs from the two surfaces #4389 covered:
- it serves TWO paths, aggregate and dataset, where the other two serve only dataset;
- its colour dimension is a single
colorPath (aggregate groupBy or first dimension), not the dataset-shaped relabel array;
- it carries
fieldByDim as a dimension name to field path MAP, where the shared hook carries an ordered array;
- its effect is keyed on
schema.objectName / datasetKey / aggregateKey / schema.xAxisKey, a different signature from the dataset one.
@object-ui/react's useDatasetDimensionMeta could likely serve the dataset path with the aggregate path staying local, but that is a judgement about ObjectChart's shape, not a mechanical lift — hence a finding for triage rather than a queued card.
Suggested direction (for triage, not a decision)
- Cheap and safe now: swap
translatorFor and the label-map loop for dimensionOptionTranslator / deriveDimensionLabelMaps. Pure functions, no behaviour change, no new dependency edge. This alone removes the third copy of the part that was actually duplicated three times.
- Needs a shape decision: whether the dataset path's read also moves onto
useDatasetDimensionMeta, or whether ObjectChart's two-path effect stays local.
The two bug-fix properties #4389 singly-expressed (apiFetch in the deps, objectui#4121; locale NOT in the deps, objectui#4030 / PR #4324) are currently stated correctly in this file too — so this is drift risk, not drift. Step 1 does not change that; step 2 would inherit them from the shared hook instead of restating them.
Generated by Claude Code
Observation-class finding, measured while doing objectui#4389 (PR #4404). Nothing a user hits today — all three copies behave identically, and this one is fully pinned on its own surface. Filing so the last copy is retired deliberately rather than found later as drift, exactly as #4389 was.
What was found
objectui#4389 named two copies of the analytics label-net glue (
plugin-dashboard'sDatasetWidgetandplugin-report'suseDatasetDimensionLabels) and PR #4404 retired both. There is a third, which #4389 did not name and PR #4404 deliberately left alone as out of scope:packages/plugin-charts/src/ObjectChart.tsx.It is the same shape, in the same order:
packages/plugin-charts/src/ObjectChart.tsx:259—const apiFetch = context?.apiFetch;:300— locale-freeoptionMetastate, with a header saying why it is locale-free (objectui#4030), nearly word-for-word the one the other two carried:355—const doFetch = apiFetch ?? fetch;:411—apiFetchin the effect's deps (objectui#4121):422-448— atranslatorFor(path)closure and abuildDimensionLabelMaplooptranslatorForat:427is logically identical to the two that PR #4404 deleted, down to the comment ("Bound to the object that OWNS the terminal field —crm_accountforcrm_account.industry, not the dataset's base object").Why this is smaller than #4389 was
PR #4404 landed the React-free half in
@object-ui/core:dimensionOptionTranslator(meta, fieldOptionLabel)— exactlytranslatorForderiveDimensionLabelMaps(metaByPath, relabel, fieldOptionLabel)— exactly the looploadDimensionFieldMeta(loadObjectSchema, object, fieldPaths)— the read compositionSo the derivation half is a pure-function swap with no React-layer change and no new dependency:
plugin-chartsalready depends on@object-ui/core.The hook half does not transfer as-is, and that is the part needing a decision rather than a patch.
ObjectChartdiffers from the two surfaces #4389 covered:colorPath(aggregategroupByor first dimension), not the dataset-shapedrelabelarray;fieldByDimas adimension nametofield pathMAP, where the shared hook carries an ordered array;schema.objectName/datasetKey/aggregateKey/schema.xAxisKey, a different signature from the dataset one.@object-ui/react'suseDatasetDimensionMetacould likely serve the dataset path with the aggregate path staying local, but that is a judgement aboutObjectChart's shape, not a mechanical lift — hence a finding for triage rather than a queued card.Suggested direction (for triage, not a decision)
translatorForand the label-map loop fordimensionOptionTranslator/deriveDimensionLabelMaps. Pure functions, no behaviour change, no new dependency edge. This alone removes the third copy of the part that was actually duplicated three times.useDatasetDimensionMeta, or whetherObjectChart's two-path effect stays local.The two bug-fix properties #4389 singly-expressed (
apiFetchin the deps, objectui#4121; locale NOT in the deps, objectui#4030 / PR #4324) are currently stated correctly in this file too — so this is drift risk, not drift. Step 1 does not change that; step 2 would inherit them from the shared hook instead of restating them.Generated by Claude Code