Skip to content

docs(types,fields): rows / options[].description docblocks stop asserting a refusal the spec no longer performs - #9588

Merged
os-justin merged 1 commit into
mainfrom
claude/issue-7635-spec-173-comment-repairs
Sep 16, 2026
Merged

os-justin merged 1 commit into
mainfrom
claude/issue-7635-spec-173-comment-repairs

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #7635

Five shipped doc comments assert that @objectstack/spec REFUSES rows and options[].description BY NAME. It declares both. This corrects the prose; it changes no runtime behaviour, type surface or export.

The premise the card was parked on is dead — re-derived, not inherited

The card calls itself 「bump-blocked」 and says 「The repo is still on 17.2.0 — so nothing is broken today」. Measured on origin/main's pnpm-lock.yaml: there is exactly one @objectstack/spec package entry and it is 17.4.0; every one of the 29 declared ranges resolves to it. The installed artifact agrees (node_modules/@objectstack/spec/package.json = 17.4.0). The bump landed and went past the version the card names, so the false comments are false on main, now.

⚠️ One correction to the dispatch's own reading: the histogram 24x17.0.0, 2x17.1.0, 1x17.2.0, 1x17.3.0, 7x17.4.0 is the specifier-range histogram (what package.json files ask for), not resolved versions. No @objectstack/spec resolves below 17.4.0. The conclusion is unchanged and strictly stronger.

What the contract actually holds (measured against installed 17.4.0, not the changelog)

measured
SelectOptionSchema keys color, default, description, label, value, visibleWhen — six, including description
option description ACCEPTED as a string; empty string valid; non-string answers invalid_type
field whose options carry it parses whole
rows on textarea/markdown/html/richtext ACCEPTED, integer >= 1 (0 answers too_small, 1.5 answers invalid_type: expected int)
rows on text / number refused — but by a cross-field refinement naming the key, ⛔ NOT unrecognized_keys
icon / disabled on an option still refused BY NAME — the live half
toolbar / preview / minHeight / maxHeight still refused BY NAME — the card's fence holds

The type-gating nuance is load-bearing and the old prose could not express it: "declared" does not mean "declared everywhere", and the refusal for the wrong field type arrives through a different channel than the one the old comments named.

The census — the card's "three comments" is not right

Re-derived from PRs #7510 / #7520 rather than trusted:

⇒ the real count is four false sites from those two PRs, not three, and the third PR-#7520 site is not one of them. Two further sites in the same family were falsified by the repair itself and are fixed here: the SelectOptionMetadata interface docblock (which listed description among the by-name refusals) and the RichtextFieldMetadata cross-reference registered on the card by comment 5576403316. Plus packages/types/src/select-option.ts, named by the pin's own header.

⭐ A gate DOES read these sites — the card's framing is out of date

The card says 「Nothing goes red」 and blames check:spec-symbols. That specific claim is correct — I ran it, it is green, and its member rule passes precisely because these citations now name keys the symbol does declare.

But check:installed-pin-claims (scripts/check-installed-spec-pin-claims.mjs, objectui#8924) landed after this card was filed and it reads two of these very sites — it had them ledgered as known-stale debt, with reasons written in anticipation of this repair ("re-parse the schema before moving the number"). Repairing the prose made it go red, by design:

FAIL LEDGER is stale: packages/fields/src/widgets/LookupField.optionDescription.test.tsx
  no longer carries a drifting @objectstack/spec 17.2.0 claim.
  Delete the entry in the same change that repaired the site.
FAIL LEDGER is stale: packages/types/src/field-types.ts ...

Both entries are deleted here, as that gate's both-direction ratchet requires. Taking Zone 3's "if a comment can be replaced by something a gate CAN read, that is better than better prose" literally, the two repaired claims are written as single-line claims about the installed pin, which is the shape the gate recognises. They therefore moved out of the ledger and into the checked population — 23 -> 25 at the pin, 52 -> 50 ledger entries, stale 45 -> 43. They now go red at the next bump instead of quietly lying. The other three sit on facts no instrument reads, and say so rather than reading as live (AGENTS.md #9).

⭐ An unreleased changeset would have shipped the same falsehood

check:changeset-claims flagged that .changeset/7014-select-option-spec-claim-correction.md — PR #7510's own changeset, still pending — names a file this change edits. Reading the paragraph as that gate asks: its dated 17.2.0 measurements are fine, but its present-tense guidance is now false and harmful — it tells authors that writing description on an option "makes PUT /api/v1/meta/object/:name fail the whole field with a 422", and that the comments "now say these are objectui-side read-model extensions that must never reach authored object metadata".

That body publishes verbatim into the CHANGELOG at the next release — the same release as this change's own entry, which says the opposite. Corrected in place, frontmatter untouched, per the precedent that gate names; check:changeset-overwrite records the deliberate modification (report-only, its case 2). This is the only site where the defect would have escaped the repo.

Gates

Hand-derived from this repo's package.json and .github/workflows/ — dispatch-gates.mjs refuses for objectui paths by design (it reads the objectstack tree), as the dispatch predicted. Exit codes captured to a file before reading, never through a pipe.

gate exit verdict line
check:installed-pin-claims 0 80 recognised claim site(s) - 25 at the pin, 50 ledger entr(ies)
check:spec-symbols 0 nothing cites a key its spec symbol does not declare
check:changeset-presence 0 4 source file(s) of 2 released package(s) ... declares 1 changeset(s)
check:changeset-claims 0 report-only; its one finding is answered above
check:changeset-overwrite 0 records the deliberate #7014 correction (report-only)
check:control-bytes 0 scanned 7739 tracked text file(s)
check:new-line-citations 0 0 new citation(s)
check:comment-mask-corpus 0 1 pre-existing disagreement, within the ceiling objectui#7882 holds open — not from this diff
tests 0 Test Files 193 passed (193) / Tests 4561 passed (4561)
type-check (types, fields) 0 both Done

Tests cover packages/types/, the LookupField site, and scripts/__tests__/check-installed-spec-pin-claims.test.ts — owed separately because this diff edits that gate script. Run from the repo root (pnpm exec vitest run <paths>); the pnpm --filter PKG exec vitest form is refused by the #3378 guard and is a false green. Heavy runs went through the shared verify lock. type-check first failed with TS2307 on an unbuilt dependency closure — built @object-ui/fields^... / @object-ui/types^..., then both passed.

Verified the repair reaches the published surface: after pnpm --filter @object-ui/types run build, dist/field-types.d.ts carries the corrected sentence and no dist/*.d.ts still says REFUSES \rows` BY NAME. The two surviving NOT a spec keystrings indist/select-option.d.tsare theicon/disabled` docblocks, which I measured as genuinely still refused.

Acceptance notes


🤖 Generated with Claude Code

https://claude.ai/code/session_01XeoGH6X7MtfbjcRDscyXi1


Generated by Claude Code

…rms for `rows` / `options[].description`

Five shipped doc comments told readers that `@objectstack/spec` REFUSES two
keys BY NAME. It declares both. The sentences were measured correctly against
17.2.0 and outlived the contract they described: 17.3.0 implemented the
maintainer's 2026-08-25 Option-A ruling on objectui#6140 / objectui#6153, and
this repo's pin has moved past it (measured: every lockfile resolution is
17.4.0). Docblocks under `packages/types/src` ship in `dist/*.d.ts`, so the
false prose was reaching consumers' editor tooltips.

Each site re-measured against the installed artifact, not the changelog:

- `rows` is ACCEPTED on textarea/markdown/html/richtext as an integer >= 1, and
  is TYPE-GATED — on other field types the refusal arrives as a cross-field
  refinement naming the key, deliberately NOT `unrecognized_keys`.
- `options[].description` is ACCEPTED as a string, and a field whose `options`
  carry it parses whole, so it may now be authored.
- `select-option.ts` no longer enumerates the spec's option keys at all: the
  enumeration is what went stale, and the keys arrive through the `Omit` by
  reference.

Two sites are now written as single-line claims about the installed pin, which
moves them out of `check-installed-spec-pin-claims.mjs`'s ledger of known-stale
debt and into the population that gate re-derives at every bump; their ledger
entries are deleted here, as that gate's both-direction ratchet requires.

Also corrects the UNRELEASED objectui#7014 changeset, which publishes verbatim
into the CHANGELOG at the next release and would have shipped the same false
guidance -- alongside this change's own entry contradicting it. Its dated
17.2.0 measurements are kept as the record; its present-tense claims are not.

No runtime behaviour, type surface or export changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeoGH6X7MtfbjcRDscyXi1
@os-justin os-justin added the documentation Improvements or additions to documentation label Sep 16, 2026 — with Claude
@os-justin os-justin added domain:ui objectui ui stream: fix lands on the published library or apps — objectui execution seat priority:p2 labels Sep 16, 2026 — with Claude
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3063.5 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-H4UJT5Gi.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 544.93KB 130.50KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.19KB 62.88KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.99KB 14.24KB
plugin-charts (index.js) 71.33KB 19.90KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 252.65KB 65.65KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.83KB 57.96KB
plugin-kanban (index.js) 46.63KB 14.53KB
plugin-list (index.js) 112.67KB 27.68KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 84.89KB 20.96KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 99.04KB 32.62KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.04KB 5.36KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-justin
os-justin marked this pull request as ready for review September 16, 2026 04:07
@os-justin
os-justin added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 544ecba Sep 16, 2026
38 checks passed
@os-justin
os-justin deleted the claude/issue-7635-spec-173-comment-repairs branch September 16, 2026 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation domain:ui objectui ui stream: fix lands on the published library or apps — objectui execution seat package: fields package: types priority:p2 tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants