docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history - #7262

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc
Sep 2, 2026
Merged

docs(types): widget.ts anchors describe the retired spec WidgetManifest/WidgetSource as history#7262
yinlianghui merged 2 commits into
mainfrom
claude/issue-5213-widget-ts-spec-anchor-jsdoc

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5213

Comment-only change to packages/types/src/widget.ts, plus the changeset that declares it. No type, member, signature, export or test moved.

What was wrong

The two JSDoc blocks on RuntimeWidgetManifest (:30) and RuntimeWidgetSource (:109) were written while @objectstack/spec/ui still exported a field-widget-plugin WidgetManifest and a WidgetSource union. They said the local types were "Renamed off the spec's WidgetManifest name (objectstack#4115)", in the present tense, and the manifest block enumerated the spec's shape key by key — { fieldTypes, category, lifecycle, events, properties, implementation, screenshots, license, aria, performance }.

None of that exists any more. That is the ADR-0033 failure the card names: an AI author reads a published docblock as present-tense fact, and a per-key description of a deleted schema is a planted premise, not stale documentation.

Installed-spec probe (measured in this worktree, not on the platform repo's main)

@objectstack/spec resolves to 17.2.0 here (node_modules/@objectstack/spec/package.json).

  • grep -rn "WidgetManifest\|WidgetSource" node_modules/@objectstack/spec/dist --include=*.d.ts --include=*.d.mtszero hits. Nothing is exported under either name.
  • grep -rn "WidgetManifestSchema\|WidgetSourceSchema" dist --include=*.js --include=*.mjszero hits. The only occurrences anywhere in the tarball are inside sourcesContent of dist/ui/index.js.map, i.e. the retired file's own tombstone comment.
  • The retirement is declared in the installed dist, so this PR quotes it rather than inventing history: the D3 SemanticMigrationui-widget-i18n-family-retired (surface ui.widgetManifest / ui.widgetLifecycle / ui.widgetEvent / ui.widgetProperty / ui.widgetSource …), and ui/WidgetManifest / ui/WidgetSource listed in RETIRED_DEFS_BY_MAJOR under the retired-def:17 block.

The sentence the new JSDoc quotes verbatim is that entry's own replacement text: "objectui's registry has always carried its own runtime manifest for that (RuntimeWidgetManifest / RuntimeWidgetSource in @object-ui/types, objectui#3161 / #4115), which models different keys and never derived from these". The same entry's acceptanceCriteria prescribes exactly this change: "packages/types/src/widget.ts's 'Renamed off the spec's WidgetManifest name' comments now point at names that no longer exist. Both are prescribed responses to this removal, not collateral damage."

What changed

Both blocks are now historical statements, and each says what is true today:

  • The spec ONCE exported those names; protocol 17 retired the whole widget-registration vocabulary under ADR-0049 enforce-or-remove (objectstack#5055, maintainer ruling 2026-08-06). There is no tombstone key to migrate because there was never a carrier key — field.widget is a z.string() naming a registered component and never referenced WidgetManifest.
  • The per-key enumeration of the retired schema is dropped, not re-dated. What is enumerated now is objectui's own key set, which is present-tense true.
  • RuntimeWidgetManifest is stated to be objectui's only widget-registration contract.
  • The bare names are owned by nobody, and the Runtime prefix is kept by choice — objectstack#4988's precedent, a freed word is not a reason to spend a second breaking rename taking it back. The unlock is recorded, not taken (objectui#4164).
  • The inline collision that made the WidgetSource rename urgent is kept, in the past tense — it is the reason the prefix exists, so deleting it would lose the reason while keeping the workaround.
  • Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns …" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts:652-653. A comment cannot go red; that table can.

Half 1 was already landed — verified on the ref, not assumed

page-nav-misc-spec-parity.test.ts already carries both names in its "spec no longer owns" table (:652-653) with the RuntimeXxx names kept — the card's option B — and the reverse assertions at :750-751 are intact. Nothing in that file is touched by this PR. packages/fields/src/__tests__/spec-symbol-batch7.test.ts and its FieldWidgetProps import are likewise untouched: FieldWidgetPropsSchema deliberately survived the retirement.

Changeset: @object-ui/types: patch, and the emit was measured

Both blocks sit on exported declarations, so they publish. Rebuilt from a cleared dist and tsconfig.tsbuildinfo on both sides and compared by SHA-256:

  • dist/widget.d.tsbb4f2fd702cac02a327b2bb498d01259313f6dc6004a99018b6ed036df9bba15 to db1d5fbd53d305f5c82bf634e76d3f17ac4a59f53bf6448420b49c5f148f1f62changed. A consumer reads this text on hover and in the API docs.
  • dist/widget.jsa3de34c54213a269074b1858248c0f26d689957dda18410443972f90e879b3e1 on both sides — byte-identical. Nothing runtime moved.

So a patch is the honest declaration and an empty-frontmatter "no release" changeset would not be. Never major.

Reverse-verification hygiene for that measurement: the implementation was committed first, the baseline text was restored with git checkout HEAD~1 -- "$REPO_ROOT/packages/types/src/widget.ts" (absolute path) under a trap … EXIT INT TERM, the mutation was proved on disk before measuring (grep -c "Renamed off the spec's" = 2, new-marker count = 0, git hash-object equal to the HEAD~1 blob), and the restore was proved by git diff HEAD --name-only being empty with the working blob hash back to the HEAD blob.

Gates — all run at the final commit 015bec4, tree clean

gateverdict
pnpm --filter @object-ui/types type-checkexit 0 — the script is tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, so the test project is included and the test sources really were checked
pnpm exec vitest run packages/types/src/__tests__/page-nav-misc-spec-parity.test.tsTest Files 1 passed (1) · Tests 45 passed (45)
pnpm exec eslint packages/types/src/widget.tsexit 0, no output
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5997 tracked text file(s); skipped 85 binary).
pnpm check:spec-symbols✅ spec symbol derivation: 1333 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages. — ✅ spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages.
node scripts/check-changeset-presence.mjs✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.
node scripts/check-changeset-overwrite.mjs✅ No pre-existing changeset was modified or deleted.
node scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.

Every heavy step ran through the shared verify lock (os-verify-lock.sh, slot issue-5213-objectui), each returning VERDICT command-exit 0. Exit codes were captured before any pipe.

Declared narrowing: the repo-wide farm (pnpm lint, the other 30-odd check:* scripts) was not run locally — CI runs it exactly once anyway. The targeted set above is derived from the change surface: one comment-only edit to packages/types/src/widget.ts plus one .changeset/*.md. check:spec-symbols is included because it is the gate that reads spec-symbol names and spec-alignment claims out of objectui source, which is precisely what this diff rewrites.

One non-gate note: pnpm --filter '@object-ui/types^...' build reports ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — None of the selected packages has a "build" script and exits 1. That is an empty dependency closure, not a failure: @object-ui/types is the base package with zero workspace dependencies. pnpm --filter @object-ui/types build itself exits 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd

…st/WidgetSource as history
The two JSDoc blocks on `RuntimeWidgetManifest` / `RuntimeWidgetSource` were
written when `@objectstack/spec/ui` still exported a field-widget-plugin
`WidgetManifest` / `WidgetSource`. Protocol 17 retired that whole
widget-registration vocabulary under ADR-0049 enforce-or-remove
(objectstack#5055), so both blocks described a schema that no longer exists —
in the present tense, including a per-key enumeration of it. That is the
ADR-0033 shape: an AI author reads a JSDoc claim as fact.
Rewritten as history: the spec ONCE owned the names, the retirement record is
the D3 `SemanticMigration` `ui-widget-i18n-family-retired` plus
`ui/WidgetManifest` in `RETIRED_DEFS_BY_MAJOR` for 17, the bare names are now
owned by nobody, and the `Runtime` prefix is kept BY CHOICE under the
objectstack#4988 precedent. The per-key enumeration of the retired schema is
dropped; the live assertion is the "spec no longer owns" row in
page-nav-misc-spec-parity.test.ts, which this comment now points at.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
…es patch
The docblocks sit on exported declarations, so they publish: rebuilt from a
cleared dist on both sides, `dist/widget.d.ts` changes (bb4f2fd7… -> db1d5fbd…)
while `dist/widget.js` is byte-identical (a3de34c5… both sides).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3hPr7riucnMfhcHY86Msd
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 48 chunks)3160.1 KB3191.4 KB
Main entry chunk (gzip)142.6 KB350 KB
Entry fileindex-C2Nqdo6R.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)15.33KB5.59KB
app-shell (runtime-config.js)20.68KB7.36KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)514.13KB117.19KB
core (index.js)5.55KB2.23KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)178.20KB49.60KB
fields (index.js)244.25KB61.73KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.98KB10.98KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)11.71KB4.29KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)6.24KB2.16KB
permissions (discardProofCache.js)1.04KB0.55KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)4.83KB2.27KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.92KB12.93KB
plugin-charts (index.js)70.02KB19.44KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)132.63KB34.56KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)250.65KB63.91KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)132.78KB32.58KB
plugin-gantt (index.js)166.77KB40.75KB
plugin-grid (index.js)208.87KB56.58KB
plugin-kanban (index.js)53.21KB14.66KB
plugin-list (index.js)113.55KB27.68KB
plugin-map (index.js)20.20KB6.66KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)29.34KB8.47KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.90KB21.12KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)81.07KB26.86KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)3.11KB1.48KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)20.57KB5.88KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)10.35KB3.60KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui@claude