Skip to content

finding(mobile): SpecResponsiveConfig is a renamed hand-copy of the spec's ResponsiveConfig — same key set, no compile-time tie #4598

Description

@yinlianghui

Observation-class finding, surfaced by the structural census run for #4592. Nothing is changed for it there — #4592 owns scripts/** only, and packages/mobile is another seat's surface.

What was found

packages/mobile/src/useResponsiveConfig.ts:26 declares:

/**
 * Spec-aligned ResponsiveConfig (mirrors @objectstack/spec ResponsiveConfigSchema).
 * ...
 */
export interface SpecResponsiveConfig {
  breakpoint?: BreakpointName;
  hiddenOn?: BreakpointName[];
  columns?: Partial< Record< BreakpointName, number > >;
  order?: Partial< Record< BreakpointName, number > >;
}

This is the #4588 shape exactly: a hand-written interface mirroring a spec object, renamed away from the spec's symbol (ResponsiveConfigSpecResponsiveConfig), carrying a canonical-sounding claim, with no import, no z.infer, and no other compile-time tie to the spec.

Of the 38 structural census hits in #4592, this was one of only three that ALSO carried an unbacked prose claim, and the only one of those three whose duplication is not deliberate and reasoned at the declaration (the other two — MarketplacePackageTranslation, bundle size; ElementDataSourceConfig, a documented filter divergence — are in the gate's CLAIM_ALLOW with those reasons).

It agrees with the spec TODAY — that is the whole point

Measured against @objectstack/spec 17.0.0-rc.6: the spec's ResponsiveConfig declares exactly breakpoint?, hiddenOn?, columns?, order?, all optional, over the same six breakpoint names (BreakpointName in @object-ui/types includes 2xl). Key-for-key and optionality-for-optionality identical — 1.00 overlap.

So this is not a live defect and nothing is broken. It is the state the derivation guard's header calls "one spec release away from drifting": the agreement is maintained by nobody, checked by nothing, and the comment already tells the next session it is canonical. ViewNavigationConfig (#4588) presumably read exactly like this on the day it was written, and had drifted on mode by the time anyone looked.

Options, if it is picked up

  • Derive itexport type SpecResponsiveConfig = ResponsiveConfig (or z.infer< typeof ResponsiveConfigSchema >), which is what finding(types): @object-ui/types publishes two spellings of the spec's navigation config, and the hand-written ViewNavigationConfig still requires mode #4588's fix did for ViewNavigationConfig and what makes the claim structural. Costs an @objectstack/spec dependency edge from @object-ui/mobile, which may be the reason it was hand-written; that is worth checking before assuming it is an oversight.
  • Keep the copy and say why, moving it to the gate's CLAIM_ALLOW with the reason (the route MarketplacePackageTranslation takes for bundle size).
  • Add a parity test pinning the key set both directions, the way select-option-spec-parity.test.ts does — the cheapest option that makes drift loud without adding a dependency edge.

Not established here: which of the three is right, and whether the dependency-edge concern is real.

It is named in the shrink-only CLAIM_DEBT ledger added by #4592, so the gate reports it until it is resolved one of those ways.

Refs #4592, #4588, #4550.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions