Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(types,plugin-markdown,plugin-kanban): one authority for `MarkdownSchema` and the in-package Kanban pair by claude[bot] · Pull Request #6971 · objectstack-ai/objectui · GitHub
Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(types,plugin-markdown,plugin-kanban): one authority for `MarkdownSchema` and the in-package Kanban pair by claude[bot] · Pull Request #6971 · objectstack-ai/objectui · GitHub
Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

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

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(types,plugin-markdown,plugin-kanban): one authority for `MarkdownSchema` and the in-package Kanban pair by claude[bot] · Pull Request #6971 · objectstack-ai/objectui · GitHub
Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(types,plugin-markdown,plugin-kanban): one authority for `MarkdownSchema` and the in-package Kanban pair by claude[bot] · Pull Request #6971 · objectstack-ai/objectui · GitHub
Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(types,plugin-markdown,plugin-kanban): one authority for `MarkdownSchema` and the in-package Kanban pair by claude[bot] · Pull Request #6971 · objectstack-ai/objectui · GitHub
Skip to content

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

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

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair - #6971

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority
Aug 31, 2026
Merged

fix(types,plugin-markdown,plugin-kanban): one authority for MarkdownSchema and the in-package Kanban pair#6971
os-sam merged 2 commits into
mainfrom
claude/issue-6172-markdown-kanban-one-authority

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Refs #6172two of the four names converge here.MarkdownSchema is fully
converged; KanbanCard / KanbanColumn converge inside @object-ui/plugin-kanban
(three declarations to one). KanbanSchema, and the remaining cross-package
KanbanCard / KanbanColumn pair, are escalated rather than guessed — see
"What is NOT resolved here". A closing keyword is deliberately not used.

⛔ Draft by dispatch order. Do not mark ready, enqueue, or enable auto-merge.

Verified on 10340f225, clean tree.

MarkdownSchema — converged, and the fork branch was tested and rejected

The ruling allowed forking the name "if it turns out to be a real semantic
difference, not a drift."
It is drift. Five independent statements in this
repository already say content is required; the plugin's own interface was the
only one saying otherwise:

statementsays
plugin-markdown/src/index.tsx registration — { name: 'content', required: true }required
plugin-markdown/src/index.test.ts:44 — pins contentInput?.required === truerequired
MarkdownImpl.tsxMarkdownImplProps.content: string (the renderer that consumes it)required
types/src/zod/data-display.zod.ts:276content: z.string(), not .optional(), parity-testedrequired
authored corpus — every type: 'markdown'node in the treesupplies it
plugin-markdown/src/types.tscontent?: stringoptional ← the outlier

Corpus measurement, because this narrows the accepted set (clause ②, the
irreversible direction). 34 type: 'markdown' object literals in the tree, brace-
matched rather than line-grepped. Every one that omits content is not a markdown
node
: they are rich-text FIELD metadata (MarkdownFieldMetadata,
packages/types/src/field-types.ts:198 — a different type with max_length), plus
one source comment and two doc restatements of the declaration itself. Zero
authored markdown nodes omit content
, so the narrowing changes nothing in-tree.

Direction is forced, not chosen: @object-ui/types is the zero-workspace-dependency
bottom layer (dependencies = @objectstack/spec, zod), so it cannot re-point at a
plugin without a cycle. plugin-markdown already depends on it, so no new edge.

className is not lost — it is declared by BaseSchema, which both copies
extended, so it was always inherited rather than added by the plugin. The plugin's
face does gain sanitize and components; both are optional, and neither is read
by any renderer
— sanitization is unconditional (rehypeSanitize is a fixed link in
the rehype chain). That deadness is recorded as a finding, not fixed here.

KanbanCard / KanbanColumn — the in-package ×3 converge to ×1

Remedy picked by a TypeScript-AST probe (heritage clause, member set, and each
shared member's declared type and optionality), not by reading:

pairsharedonly in Aonly in Btyped differentlyverdict
types.ts vs KanbanImpl.tsxKanbanCard4030strict subset copy
types.ts vs KanbanEnhanced.tsxKanbanCard4010strict subset copy
types.ts vs KanbanImpl.tsxKanbanColumn5000exact duplicate
types.ts vs KanbanEnhanced.tsxKanbanColumn5010strict subset copy

Nothing typed differently anywhere ⇒ stale copies, so the re-point branch, exactly
as #6936 treated the Breadcrumb pair. The extras (cardSubtitle, cardFieldCells,
coverImage, collapsed) move onto the one declaration in ./types; all four are
optional, so every value that type-checked before still does. Both .tsx modules keep
their previous export surface through export type { … } from './types', so no import
path changes.

⚠️ One AST-probe caveat worth recording: a first pass reported badges as "typed
differently" between types.ts and both .tsx copies. That was an artifact — JSDoc
prose inside the type literal, and a trailing member separator. After normalising
comments and separators the difference is zero. Comparing raw getText() would
have produced the wrong verdict (rename instead of re-point).

Why direction (a) was not used

The gate counts export type X = / export interface X as an authority and
deliberately does not count export type { X } from …. A derived downstream
declaration is still a declaration, so it cannot deliver the baseline deletion. The
live proof is on the tree: ComponentMeta was converged the (a) way by PR #6297 and
its KNOWN_COLLISIONS row is still there today.

The shrink-only baseline

Re-derived on this branch's merge-base rather than inherited: 39 rows at
main = 8f1d995ef447… — the card body's table says 46 and is seven rows stale.

  • MarkdownSchemarow deleted (39 → 38). One authority remains.
  • KanbanCard / KanbanColumnrows shrunk from four sites to two.reconcile
    compares sites, so leaving the four-site rows would have failed the stale
    direction. The two survivors are the cross-package pair.
  • KanbanSchema — unchanged.

Ablation — direction predicted in writing before each run

Both legs mutate the fact, never the assertion, under trap … EXIT INT TERM with
absolute paths from git rev-parse --show-toplevel, restoring with
git checkout HEAD -- ABSOLUTE_PATH.

Leg A — predicted: restoring the deleted MarkdownSchema row while the collision
is gone reds in the stale direction. Observed exactly that:
MarkdownSchema — no longer collides at:, exit 1, 1 failed / 10 passed.

Leg B — predicted: reverting the source convergence while the row stays deleted
reds in the fresh direction. Observed exactly that:
MarkdownSchema — a NEW colliding name, exit 1, 1 failed / 10 passed.

Mutation proved on disk both times (anchored count moved 0→1 / re-export 1→0, and
git hash-object moved off the HEAD blob); restore proved both times (hash back to
the HEAD blob and git diff HEAD empty). Together the two legs show the gate is
non-vacuous in both of its directions for this change.

What is NOT resolved here, and why it is not a guess

The cross-package KanbanCard / KanbanColumn / KanbanSchema collision between
@object-ui/types and @object-ui/plugin-kanban stays open.

These are two genuinely different dialects, not a stale copy — items where the plugin
says cards, labels where it says badges; KanbanSchema shares 3 keys of 7 and 19
with columns required on one side and optional on the other. That is the
ActionSchema signature, whose remedy is rename — and because the bottom-layer
package cannot re-point at a plugin, a rename here means removing a published name
from one of the two packages
.

The 2026-08-25 ruling named a cross-package authority for FormField ("the
@objectstack/spec copy is the contract-side authority"
) but its Kanban clause is
about in-package multi-declarations. It does not say which package owns the bare
name here, so that authority call is escalated on the card rather than made in a PR.

Measurement is in hand for whoever rules: the plugin's dialect is the live one —
authored corpus writes cards13× against items (and that single items
site is the types copy's own demo file); every registered renderer (kanban,
kanban-ui, kanban-enhanced, object-kanban) consumes the plugin shape; and the
types copy's distinguishing keys draggable / onColumnAdd / onCardAdd are read by
nothing. Against that, renaming the @object-ui/types trio touches its barrel,
registry.ts's ComponentSchemaMap, the ComplexSchema union, the Zod mirror and its
parity test, plus two docs pages — a published-surface removal well outside this
dispatch's declared file surface.

#6155 is only partially addressed and stays open. It measured KanbanCard /
KanbanColumn as declared four times; after this diff they are declared twice. The
remaining two are the cross-package pair above.

Docs truth kept in step

content/docs/plugins/plugin-markdown.mdx asserted "Declared by
@object-ui/plugin-markdown … the plugin ships its own copy of this name."
This diff
makes that false, so the page is corrected in the same PR: it now names the declaring
package and file path (a checkable existence claim), records that content is required
and why, and documents sanitize / components as declared-but-unread rather than
silently listing them as behaviour.

Gates — exit codes captured by redirect BEFORE any pipe

gateverdict
root vitest, scripts/__tests__/one-authority… + packages/{types,plugin-kanban,plugin-markdown}/exit 0 — 101 files / 1095 tests, on final commit 10340f225
type-check, the 3 affected packagesexit 0 — Scope: 3 of 47 workspace projects (not a zero-match)
check:control-bytesexit 0 — 5796 tracked text files
check:doc-snippetsexit 0 — 271 of 271 blocks judged, 0 failed
check:doc-fencesexit 0 — 224 documents
check:doc-typesexit 0 — every documented component type registered
docs:check-linksexit 0 — 17 scan roots
check:self-importexit 0 — 0 self-imports
check:phantom-depsexit 0 — every in-scope import declared by its publishing package
check:esm-specifiersexit 0
check-changeset-presence (direct)exit 0 — 4 published source files changed, 1 changeset
check-changeset-no-major / -fixed / -overwriteexit 0

Coverage measured, not assumed.check:doc-snippets was first run against an
unbuilt tree and returned exit 2 — PRECONDITION NOT MET, which the gate itself
labels "I could not run, NOT I ran and found errors." It was re-run after building the
32 packages its own --build-filter names; only that second run is quoted. And the
edited page is genuinely in the covered set: content/docs/plugins/plugin-markdown.mdx
appears 0 times in the script's declared 43-page ungated list.

Declared narrowing.check:readme-exports exits 1 on this tree, and it is
not attributable to this change: every one of its findings is
type entry ./dist/index.d.ts is not on disk — run pnpm build first for packages this
branch never touches. After building the two edited plugins, judged self-imports rose
85 → 91 with 0 wrong-path and 0 fabricated, and no failure line names either
edited README
. The repo-wide pnpm lint was likewise not run here; CI runs the full
farm regardless.


Generated by Claude Code

…Schema` and the in-package Kanban pair
`MarkdownSchema` converges onto `@object-ui/types`: the plugin's second
declaration differed on one member (`content`, optional there and required in
types), measured as drift rather than a semantic difference — the plugin's own
registration marks the input `required: true` (test-pinned), its renderer props
type is non-optional, the Zod mirror is `z.string()`, and every authored
`type: 'markdown'` node supplies it. plugin-markdown now re-exports the one
authority.
`KanbanCard` / `KanbanColumn`: the three in-package declarations converge to
one. An AST comparison found `KanbanImpl.tsx` and `KanbanEnhanced.tsx` strict
subset copies of `./types` with nothing typed differently, so their extra
members (`cardSubtitle`, `cardFieldCells`, `coverImage`, `collapsed` — all
optional) move onto the canonical declaration and both files re-point at it,
keeping their export surface via re-export.
Baseline `one-authority-per-exported-name-6273`: `MarkdownSchema` row deleted;
the `KanbanCard` / `KanbanColumn` rows shrink from four sites to the two
cross-package ones, which are escalated rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3179.9 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-DkRl-aik.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)12.46KB4.71KB
app-shell (runtime-config.js)20.61KB7.35KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)175.69KB48.80KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

… scope the Kanban authority note
C1: the "Schema API" block in packages/plugin-markdown/README.md still spelled
`content` as optional — the exact outlier spelling this branch removes, in a
doc that ships in the npm tarball. The canonical declaration is non-optional:
`content: z.string()` at packages/types/src/zod/data-display.zod.ts:276 and
`content: string` at packages/plugin-markdown/src/MarkdownImpl.tsx:31. No gate
catches this; check-readme-exports judges export existence, not shape prose.
C2: KanbanEnhanced.tsx's authority comment now carries the "in this package"
qualifier its KanbanImpl twin already spells. The cross-package Kanban pair is
deliberately open, so the unqualified wording overstated what this branch settles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 45 chunks)3180.2 KB3222.7 KB
Main entry chunk (gzip)143.6 KB350 KB
Entry fileindex-BAL6K3Gv.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)12.46KB4.71KB
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)512.09KB116.42KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)177.67KB49.45KB
fields (index.js)243.65KB61.63KB
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.95KB10.97KB
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)64.68KB18.35KB
plugin-chatbot (index.js)190.53KB45.18KB
plugin-dashboard (index.js)133.48KB34.51KB
plugin-designer (index.js)212.87KB43.19KB
plugin-detail (index.js)247.26KB63.17KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)133.11KB32.61KB
plugin-gantt (index.js)165.21KB40.37KB
plugin-grid (index.js)202.08KB54.61KB
plugin-kanban (index.js)53.14KB14.64KB
plugin-list (index.js)113.15KB27.59KB
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.05KB8.37KB
plugin-tree (index.js)8.98KB3.08KB
plugin-view (index.js)85.79KB21.10KB
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)76.75KB25.49KB
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

@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

C1 and C2 are discharged in 892625f. Still draft, nothing else touched.

C1 (was blocking)packages/plugin-markdown/README.md:65, the "Schema API" block:

- content?: string, // Markdown content (supports GitHub Flavored Markdown)+ content: string, // Markdown content (supports GitHub Flavored Markdown)

Re-derived against the declaration rather than taken on the review's word: content: z.string() with no .optional() at packages/types/src/zod/data-display.zod.ts:276, and content: string at packages/plugin-markdown/src/MarkdownImpl.tsx:31. The comment column stays aligned with the className? row under it.

C2packages/plugin-kanban/src/KanbanEnhanced.tsx:37 now carries the qualifier its twin already spells:

-// One authority for these two names, in `./types` (objectui#6172 / #6155).+// One authority for these two names in this package: `./types` (objectui#6172 / #6155).

matching KanbanImpl.tsx:52 ("have ONE authority in this package"). The cross-package Kanban pair stays open, which is the point of the qualifier.

Verification at 892625f, every command from the repo root:

  • node scripts/check-changeset-presence.mjs — exit 0, its own verdict line: 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/6172-markdown-kanban-one-authority.md. No changeset added, as directed.
  • node scripts/check-readme-exports.mjs — exit 0 on a built tree: check-readme-exports: OK (... 386 self-imports judged (386 real, 0 wrong-path, 0 fabricated); 3286 export symbol(s) read from 37 of 40 package(s) ...). On the unbuilt tree it first exited 1 with the population COLLAPSED -- this run proves nothing and 36 unbuilt — the documented unbuilt-tree path, not a red — so the closure was built (turbo: 43 successful, 43 total) and the gate re-run.
  • vitest union over packages/types packages/plugin-kanban packages/plugin-markdown scripts/__tests__/one-authority-per-exported-name-6273.test.ts: Test Files 101 passed (101) / Tests 1095 passed (1095) — matches the review's 101/1095 exactly.
  • git diff --stat against the previous head: 2 files changed, 2 insertions(+), 2 deletions(-) — the two files above, nothing else.

The shrink-only baseline scripts/__tests__/one-authority-per-exported-name-6273.test.ts was not edited; it runs green inside the union above.

Generated by Claude Code


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review August 31, 2026 07:57
@os-sam
os-sam added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit b3d562cAug 31, 2026
32 checks passed
@os-sam
os-sam deleted the claude/issue-6172-markdown-kanban-one-authority branch August 31, 2026 08:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin: kanbanplugin: markdownplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-sam@claude