Filed unassigned by the domain:ui execution seat (PM session session_013hfmP9hoMd3dJwTh85J4yB) — recording, not claiming.
Provenance: this is the enumeration answer to #6887's must-answer 2, measured on PR #7013 by the dev that landed it. #6887 fixed one copy (metadata-viewer.tsx) and the enumeration was deliberately left unfixed there, for filing rather than scope creep. ⛔ Nothing below was touched by that PR.
Dedupe: searched before filing, with a control query in the same session that returned live results (#7008 / #6909 / #3221 / #3291), so a nil result here is a reading and not a blind instrument. No open card covers this population.
The count
#6887's title said "a fifth copy". Measured on b458300ca: 8 further hand-written descriptions of the select-option contract remain, in three tiers.
Tier 1 — named types describing the same contract (3)
| # | path | line | shape | drift measurable today |
|---|
| 1 | packages/types/src/field-types.ts | 290 | SelectOptionMetadata — label, value, color?, icon?, disabled?, visibleWhen? | Yes — default is absent. This is the object-definition field face and it cannot describe the ruled-enforce key. Renamed away from the spec's symbol, so gate rule 1 has nothing to match; it claims alignment on visibleWhen only. |
| 2 | packages/types/src/form.ts | 266 | SelectOption — adds disabled / icon, widens value | No. Hand-written TS, but its Zod twin is a spec derivation pinned by select-option-spec-parity.test.ts + zod-mirror-parity.test.ts. Transitively backed. |
| 3 | packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx | 68 | interface Option { value: string; label?: string; color?: string } | Same relaxed-label divergence #7013 just removed, plus default and visibleWhen both absent. No claim comment, no pin. |
Tier 2 — anonymous inline restatements of the same triple (5)
| # | path | line | shape |
|---|
| 4 | packages/app-shell/src/services/MetadataService.ts | 112 | options?: Array<{ label: string; value: string; color? }> on FieldMetadataPayload |
| 5 | packages/types/src/data-display.ts | 415 | options?: Array<{ value: any; label: string; color? }> |
| 6 | packages/types/src/reports.ts | 124 | options?: Array<{ value: string | number; label: string; color? }> |
| 7 | packages/plugin-dashboard/src/recordFields.tsx | 216 | options?: Array<{ value: any; label: string; color? }> on FieldMeta |
| 8 | packages/plugin-list/src/UserFilters.tsx | 31 | ResolvedOption { label; value; color?; count? } (adds a resolved-only count) |
Tier 3 — declared-deliberate, already derived downstream (listed for completeness, not a defect)
packages/core/src/evaluator/optionRules.ts:40 — OptionLike { label; value; visibleWhen? }, documented in place as a deliberately minimal reader shape. MultiSelectField.tsx:10, RadioField.tsx:10, CheckboxesField.tsx:10 derive from it rather than restating it — this is the behaviour the class wants, and it is worth keeping as the model to copy.
Deliberately excluded, each already reasoned in place:ActionParamOption (ActionRunner.ts:582) and RawActionParamOption (resolveActionParams.ts:69) both carry a [key: string]: unknown catch-all, so they do not restate the vocabulary; RadioOption / ComboboxOption are distinct component vocabularies with their own spec schemas; the FieldOption shapes in plugin-tree / plugin-view are field pickers, where value is a field name — a different concept.
⭐ The part that matters more than the count: the gate cannot see any of this
scripts/check-spec-symbol-derivation.mjs reported identical numbers before and after #7013 (2 declared deliberate copies, 18 unbacked claims in 5 packages), even though the fix removed a real, drifted mirror. Two independent reasons, and the second is the structural one:
- The declaration carried no alignment claim, so rule 2 had nothing to match on.
- Both rules skip any declaration without an
export modifier (hasExportModifier, applied once per scanner). The metadata-viewer copy was module-local, so rule 1 could not see it either — although it was named after a spec export and had drifted, which is precisely rule 1's trigger.
objectui#5899 already measured that hole: forcing the export filter true takes rule 1 from 18 findings to 47, of which 22 of 30 additional sites are real mirrors and 12 carry a divergence measurable today.
⇒ So "the gate numbers did not move" is the correct outcome for #7013, not a missed step — and it means this class is invisible to its own gate. That is #6887's third candidate direction ("should the gate notice un-claimed structural copies at all"), now with a number attached.
One measured negative worth recording
After #7013, packages/types/src/form.ts:299 is the only declaration left in the tree carrying a select option's default key. The object-definition face (#1) does not, and neither does the authoring editor (#3). Given default is ruled enforce on the object-field face (objectstack#7246, PR #7388), that asymmetry is worth a look on its own.
What a round would need to decide (⛔ not proposing a disposition)
⛔ Not dispatched, and it should not be taken as one undifferentiated task.
Filed unassigned by the
domain:uiexecution seat (PM sessionsession_013hfmP9hoMd3dJwTh85J4yB) — recording, not claiming.Provenance: this is the enumeration answer to #6887's must-answer 2, measured on PR #7013 by the dev that landed it. #6887 fixed one copy (
metadata-viewer.tsx) and the enumeration was deliberately left unfixed there, for filing rather than scope creep. ⛔ Nothing below was touched by that PR.Dedupe: searched before filing, with a control query in the same session that returned live results (#7008 / #6909 / #3221 / #3291), so a nil result here is a reading and not a blind instrument. No open card covers this population.
The count
#6887's title said "a fifth copy". Measured on
b458300ca: 8 further hand-written descriptions of the select-option contract remain, in three tiers.Tier 1 — named types describing the same contract (3)
packages/types/src/field-types.tsSelectOptionMetadata—label,value,color?,icon?,disabled?,visibleWhen?defaultis absent. This is the object-definition field face and it cannot describe the ruled-enforcekey. Renamed away from the spec's symbol, so gate rule 1 has nothing to match; it claims alignment onvisibleWhenonly.packages/types/src/form.tsSelectOption— addsdisabled/icon, widensvalueselect-option-spec-parity.test.ts+zod-mirror-parity.test.ts. Transitively backed.packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsxinterface Option { value: string; label?: string; color?: string }labeldivergence #7013 just removed, plusdefaultandvisibleWhenboth absent. No claim comment, no pin.Tier 2 — anonymous inline restatements of the same triple (5)
packages/app-shell/src/services/MetadataService.tsoptions?: Array<{ label: string; value: string; color? }>onFieldMetadataPayloadpackages/types/src/data-display.tsoptions?: Array<{ value: any; label: string; color? }>packages/types/src/reports.tsoptions?: Array<{ value: string | number; label: string; color? }>packages/plugin-dashboard/src/recordFields.tsxoptions?: Array<{ value: any; label: string; color? }>onFieldMetapackages/plugin-list/src/UserFilters.tsxResolvedOption { label; value; color?; count? }(adds a resolved-onlycount)Tier 3 — declared-deliberate, already derived downstream (listed for completeness, not a defect)
packages/core/src/evaluator/optionRules.ts:40—OptionLike { label; value; visibleWhen? }, documented in place as a deliberately minimal reader shape.MultiSelectField.tsx:10,RadioField.tsx:10,CheckboxesField.tsx:10derive from it rather than restating it — this is the behaviour the class wants, and it is worth keeping as the model to copy.Deliberately excluded, each already reasoned in place:
ActionParamOption(ActionRunner.ts:582) andRawActionParamOption(resolveActionParams.ts:69) both carry a[key: string]: unknowncatch-all, so they do not restate the vocabulary;RadioOption/ComboboxOptionare distinct component vocabularies with their own spec schemas; theFieldOptionshapes inplugin-tree/plugin-vieware field pickers, wherevalueis a field name — a different concept.⭐ The part that matters more than the count: the gate cannot see any of this
scripts/check-spec-symbol-derivation.mjsreported identical numbers before and after #7013 (2 declared deliberate copies, 18 unbacked claims in 5 packages), even though the fix removed a real, drifted mirror. Two independent reasons, and the second is the structural one:exportmodifier (hasExportModifier, applied once per scanner). Themetadata-viewercopy was module-local, so rule 1 could not see it either — although it was named after a spec export and had drifted, which is precisely rule 1's trigger.objectui#5899 already measured that hole: forcing the export filter true takes rule 1 from 18 findings to 47, of which 22 of 30 additional sites are real mirrors and 12 carry a divergence measurable today.
⇒ So "the gate numbers did not move" is the correct outcome for #7013, not a missed step — and it means this class is invisible to its own gate. That is #6887's third candidate direction ("should the gate notice un-claimed structural copies at all"), now with a number attached.
One measured negative worth recording
After #7013,
packages/types/src/form.ts:299is the only declaration left in the tree carrying a select option'sdefaultkey. The object-definition face (#1) does not, and neither does the authoring editor (#3). Givendefaultis ruledenforceon the object-field face (objectstack#7246, PR #7388), that asymmetry is worth a look on its own.What a round would need to decide (⛔ not proposing a disposition)
getFieldreturnsany).⛔ Not dispatched, and it should not be taken as one undifferentiated task.