Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .changeset/dangling-spec-citations-4597.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
"@object-ui/types": patch
"@object-ui/i18n": patch
---

Doc comments no longer cite `@objectstack/spec` symbols the pinned spec has retired

Eight exported declarations carried a doc comment claiming alignment with a
`@objectstack/spec` symbol that `17.0.0-rc.6` does not export — four locale
formatting shapes in `@object-ui/i18n` (`SpecPluralRule`, `SpecDateFormat`,
`SpecNumberFormat`, `SpecLocaleConfig`) and four activity-feed shapes in
`@object-ui/types` (`FieldChangeEntry`, `Mention`, `Reaction`,
`RecordSubscription`). A citation that points at nothing is worse than a stale
one: the next reader cannot tell whether the protocol retired the symbol,
renamed it, or never had it.

Measuring all eight against the published registry answered that question, and
the answer was not "these names never existed". Every one was a real export the
protocol retired on purpose, and every local key set was faithful to the schema
it named. The feed four left `@objectstack/spec/data` in the `16.0.0` major,
when the feed surface was replaced by the data API over `sys_comment` /
`sys_activity`. The i18n four left `@objectstack/spec/ui` in `17.0.0-rc.6`
itself — they were still present in `rc.5` — retired under ADR-0049
enforce-or-remove because no authorable shape carried them and nothing ever
parsed them.

Each comment now records that provenance, including the version the symbol left
and what (if anything) replaced it, so the shapes read as declarations these
packages own rather than as a view onto a protocol type. Type shapes, runtime
behaviour and exports are unchanged — the published `.d.ts` files differ only in
comment text, which is why this is graded `patch`.
60 changes: 43 additions & 17 deletions packages/i18n/src/utils/spec-formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,38 @@
*/

/**
* @object-ui/i18n - Spec-aligned i18n utilities
* @object-ui/i18n - locale formatting helpers
*
* Runtime consumers for @objectstack/spec v2.0.7 i18n types:
* - PluralRuleSchema → resolvePlural()
* - DateFormatSchema → formatDateSpec()
* - NumberFormatSchema → formatNumberSpec()
* - LocaleConfigSchema → applyLocaleConfig()
* ## Provenance of the four shapes below (objectui#4597)
*
* They were authored against `@objectstack/spec/ui`, which exported
* `PluralRuleSchema`, `DateFormatSchema`, `NumberFormatSchema` and
* `LocaleConfigSchema` up to and including 17.0.0-rc.5. The pinned
* 17.0.0-rc.6 removed all four under ADR-0049 enforce-or-remove
* (objectstack#5055, maintainer ruling 2026-08-06): they carried no key on any
* authorable shape and nothing ever parsed them, so the vocabulary was retired
* rather than given a door. The key sets here were faithful to the retired
* schemas — this is a retirement, not a drift.
*
* Nothing in the pinned protocol models locale formatting today, so the
* interfaces below are declarations this package owns outright, not a view onto
* a protocol type. The retirement note records that localisation returns as
* authorable metadata through a new ADR — "the formatter that reads a
* LocaleConfig first, the vocabulary second" — so re-derive these at that point
* instead of assuming they still track anything upstream.
*
* @module spec-formatters
*/

// ============================================================================
// PluralRuleSchema Consumer
// Plural rules
// ============================================================================

/**
* Spec-aligned PluralRule (mirrors @objectstack/spec PluralRuleSchema).
* Plural forms for a single translation key, in CLDR categories.
*
* Local shape — authored against the protocol's `PluralRuleSchema`, retired in
* 17.0.0-rc.6 (see the module doc), so there is nothing upstream to derive from.
*/
export interface SpecPluralRule {
/** Translation key */
Expand Down Expand Up @@ -81,11 +96,14 @@ export function resolvePlural(
}

// ============================================================================
// DateFormatSchema Consumer
// Date formatting
// ============================================================================

/**
* Spec-aligned DateFormat (mirrors @objectstack/spec DateFormatSchema).
* Date/time formatting options passed through to `Intl.DateTimeFormat`.
*
* Local shape — authored against the protocol's `DateFormatSchema`, retired in
* 17.0.0-rc.6 (see the module doc), so there is nothing upstream to derive from.
*/
export interface SpecDateFormat {
dateStyle?: 'full' | 'long' | 'medium' | 'short';
Expand All @@ -95,7 +113,7 @@ export interface SpecDateFormat {
}

/**
* Format a date using @objectstack/spec DateFormatSchema configuration.
* Format a date using a {@link SpecDateFormat} configuration.
*
* @example
* ```ts
Expand Down Expand Up @@ -124,11 +142,15 @@ export function formatDateSpec(
}

// ============================================================================
// NumberFormatSchema Consumer
// Number formatting
// ============================================================================

/**
* Spec-aligned NumberFormat (mirrors @objectstack/spec NumberFormatSchema).
* Number formatting options passed through to `Intl.NumberFormat`.
*
* Local shape — authored against the protocol's `NumberFormatSchema`, retired
* in 17.0.0-rc.6 (see the module doc), so there is nothing upstream to derive
* from.
*/
export interface SpecNumberFormat {
style?: 'currency' | 'percent' | 'decimal' | 'unit';
Expand All @@ -140,7 +162,7 @@ export interface SpecNumberFormat {
}

/**
* Format a number using @objectstack/spec NumberFormatSchema configuration.
* Format a number using a {@link SpecNumberFormat} configuration.
*
* @example
* ```ts
Expand Down Expand Up @@ -170,11 +192,15 @@ export function formatNumberSpec(
}

// ============================================================================
// LocaleConfigSchema Consumer
// Locale configuration
// ============================================================================

/**
* Spec-aligned LocaleConfig (mirrors @objectstack/spec LocaleConfigSchema).
* One locale's formatting defaults, resolved by `applyLocaleConfig()`.
*
* Local shape — authored against the protocol's `LocaleConfigSchema`, retired
* in 17.0.0-rc.6 (see the module doc), so there is nothing upstream to derive
* from.
*/
export interface SpecLocaleConfig {
/** BCP 47 language code (e.g., 'en-US', 'zh-CN') */
Expand All @@ -190,7 +216,7 @@ export interface SpecLocaleConfig {
}

/**
* Apply a LocaleConfigSchema to configure i18n formatting defaults.
* Apply a {@link SpecLocaleConfig} to configure i18n formatting defaults.
* Returns resolved formatting functions bound to the locale config.
*
* @example
Expand Down
44 changes: 36 additions & 8 deletions packages/types/src/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,18 @@ export interface ActivityEntry {
}

// ============================================================================
// Feed / Chatter Protocol Types
// Aligned with @objectstack/spec FeedItemSchema, MentionSchema, ReactionSchema,
// FieldChangeEntrySchema, RecordSubscriptionSchema
// Feed / Chatter timeline types
//
// Provenance (objectui#4597): `@objectstack/spec/data` exported `FeedItemSchema`,
// `MentionSchema`, `ReactionSchema`, `FieldChangeEntrySchema` and
// `RecordSubscriptionSchema` through 15.1.1. The 16.0.0 major removed the whole
// feed surface, directing consumers to the data API over `sys_comment` /
// `sys_activity` — reactions and threaded replies are fields on `sys_comment`.
// `FeedItemType` and `FeedFilterMode` were deliberately KEPT as live activity-
// timeline config, which is why the import below still resolves.
//
// So the interfaces in this section are shapes this package owns: the protocol
// no longer models them, and there is nothing upstream left to derive from.
// ============================================================================

/**
Expand All @@ -348,7 +357,10 @@ export type { FeedItemType };

/**
* FeedItem — A single item in the unified activity feed.
* Aligned with @objectstack/spec FeedItemSchema.
*
* Local shape; its cited `FeedItemSchema` went with the 16.0.0 feed removal
* (see the section banner). Only `type` is still protocol-bound, through the
* `FeedItemType` import above.
*/
export interface FeedItem {
/** Unique identifier */
Expand Down Expand Up @@ -393,7 +405,13 @@ export interface FeedItem {

/**
* FieldChangeEntry — A single field change within a feed item.
* Aligned with @objectstack/spec FieldChangeEntrySchema.
*
* Local shape; its cited `FieldChangeEntrySchema` went with the 16.0.0 feed
* removal (see the section banner). The pinned protocol's nearest surviving
* shape is `FieldChangeSchema` in `@objectstack/spec/kernel`, but that is a
* different thing — change tracking keyed `path` / `originalValue` /
* `currentValue` / `changedBy` / `changedAt`, with none of the display keys a
* timeline row needs. Do not re-point this at it.
*/
export interface FieldChangeEntry {
/** Field API name */
Expand All @@ -412,7 +430,10 @@ export interface FieldChangeEntry {

/**
* Mention — An @mention within a feed item.
* Aligned with @objectstack/spec MentionSchema.
*
* Local shape; its cited `MentionSchema` went with the 16.0.0 feed removal (see
* the section banner), and no shape of this meaning survives under any other
* name in the pinned protocol.
*/
export interface Mention {
/** Mention target type */
Expand All @@ -429,7 +450,10 @@ export interface Mention {

/**
* Reaction — An emoji reaction on a feed item.
* Aligned with @objectstack/spec ReactionSchema.
*
* Local shape; its cited `ReactionSchema` went with the 16.0.0 feed removal
* (see the section banner). Reactions are now persisted as fields on
* `sys_comment` rather than modelled as their own protocol shape.
*/
export interface Reaction {
/** Emoji identifier (e.g. '👍', '❤️', '🎉') */
Expand All @@ -444,7 +468,11 @@ export interface Reaction {

/**
* RecordSubscription — Notification subscription state for a record.
* Aligned with @objectstack/spec RecordSubscriptionSchema.
*
* Local shape; its cited `RecordSubscriptionSchema` went with the 16.0.0 feed
* removal (see the section banner). The `Subscription` shapes the pinned
* protocol still exports are unrelated — realtime transport channels, event
* subscriptions and app billing — so none of them is a replacement.
*/
export interface RecordSubscription {
/** Record ID */
Expand Down
31 changes: 19 additions & 12 deletions scripts/check-spec-symbol-derivation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -466,35 +466,42 @@ export const CLAIM_ALLOW = {
// - derive it (`z.infer< typeof SpecX >`, `SpecAuthoredInput< … >`, or an
// import of the spec type) — the claim becomes structural and the entry goes;
// - keep the copy and move it to CLAIM_ALLOW with the reason it exists;
// - or delete the claim from the comment, because it was never true. Eight of
// these name a spec symbol the installed spec does not export at all
// (`DateFormatSchema`, `NumberFormatSchema`, `PluralRuleSchema`,
// `LocaleConfigSchema`, `FieldChangeEntrySchema`, `MentionSchema`,
// `ReactionSchema`, `RecordSubscriptionSchema`) — a canonical-sounding
// pointer to nothing, which is the planted premise in its purest form. The
// failure message names them, so the next reader does not have to re-measure.
// - or delete the claim from the comment, because it is not true here.
//
// Eight entries left by that last route in objectui#4597 — the i18n formatters'
// four and views.ts's four, which cited `DateFormatSchema`, `NumberFormatSchema`,
// `PluralRuleSchema`, `LocaleConfigSchema`, `FieldChangeEntrySchema`,
// `MentionSchema`, `ReactionSchema` and `RecordSubscriptionSchema`. Measuring
// them answered the question #4597 left open, and the answer was NOT "these
// names never existed": all eight were real exports the protocol RETIRED, and
// each local key set was faithful to the schema it named. The feed four went
// from `@objectstack/spec/data` in the 16.0.0 major (feed surface replaced by
// the data API over `sys_comment` / `sys_activity`); the i18n four went from
// `@objectstack/spec/ui` in 17.0.0-rc.6 itself — present through rc.5 — under
// ADR-0049 enforce-or-remove (objectstack#5055). Their comments now record that
// provenance instead of vouching for a symbol the pinned spec has dropped.
//
// Worth keeping for whoever measures the next batch: "the installed spec does
// not export it" does not distinguish a name that never existed from one the
// protocol retired on purpose, and the fix differs. Read the spec's CHANGELOG
// and its own retirement notes before concluding a citation was always wrong.
const CLAIM_DEBT_ISSUE = 4592;
const CLAIM_DEBT = {
"@object-ui/types": [
"FieldChangeEntry",
"ListViewExportOptions",
"ManagedByBucket",
"Mention",
"ObjectFormSchema",
"ObjectFormSection",
"PageRegionWidth",
"Reaction",
"RecordActivityComponentProps",
"RecordChatterComponentProps",
"RecordComponentAriaProps",
"RecordDetailsComponentProps",
"RecordHighlightsComponentProps",
"RecordPathComponentProps",
"RecordRelatedListComponentProps",
"RecordSubscription",
"SubmitBehavior",
],
"@object-ui/i18n": ["SpecDateFormat", "SpecLocaleConfig", "SpecNumberFormat", "SpecPluralRule"],
"@object-ui/core": ["ResultDialogFieldSpec", "ViewDataConfig"],
"@object-ui/app-shell": ["RecordLookupBinding"],
"@object-ui/plugin-view": ["ROW_HEIGHT_OPTIONS"],
Expand Down
Loading