Skip to content

ci(spec,type-check): spec-named symbols must be derived, 12 packages type-check their tests, ActionDef's keys get an inventory - #3032

Merged
os-zhuang merged 6 commits into
mainfrom
claude/zero-error-packages-ci-cleanup-1mgyew
Jul 30, 2026
Merged

ci(spec,type-check): spec-named symbols must be derived, 12 packages type-check their tests, ActionDef's keys get an inventory#3032
os-zhuang merged 6 commits into
mainfrom
claude/zero-error-packages-ci-cleanup-1mgyew

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Three issues, one theme: a rule that isn't a check isn't a rule. Each lands as CI, and each ships with a run showing the guard failing against pre-fix code.

  • objectstack#4115 — a spec-named symbol must be an import, not a declaration
  • objectstack#4118 — the 8 zero-error packages (measured: 12) type-check their tests
  • objectstack#4075 step 1 — inventory ActionDef's keys, warn on the ones nothing reads

objectstack#4115 — scripts/check-spec-symbol-derivation.mjs

objectui declares local types and consts under the same names as @objectstack/spec exports, with doc comments claiming spec canonicity. Every audited instance had drifted or was one release from it: ActionType (missing form), ChartType (7 of 19 members), ActionLocation + 2 (re-declared union + tuple + z.enum under a comment that said "re-export here"), ActionParamFieldType (16 of 49).

The cost is specific to agent-driven development: an agent reads the comment, takes it as ground truth, and builds on it. #2901 was filed with a backwards premise because the fork carried the spec's own symbol name.

How it works. Enumerates all 4231 spec export names — types and values, through the compiler's view of each subpath's .d.ts, because a runtime import() sees only values and the drifted symbols are mostly types. Then flags an exported declaration whose name the spec owns, unless it is derived.

Both sanctioned forms pass, because both bind the local name to the spec at compile time:

export type { ActionLocation } from '@objectstack/spec/ui';   // re-export
export type ActionType = z.infer<typeof SpecActionType>;      // derivation

Derivation must sit in a structural position — a type alias's own type node, an interface's extends, a const's initializer. A spec name merely mentioned inside a members block does not count, because that is what a fork looks like. Consts are stricter: array and object literals are not descended into, so export const ACTION_LOCATIONS = [...SpecLocations] is still flagged — a faithful copy passes every value comparison, and only reference identity distinguishes a re-export from a fork (#3003).

The ledger names symbols, not counts. 156 pre-existing collisions across 19 packages, listed by name. A per-package count is a budget: it lets the next fork land as long as an unrelated one was fixed in the same PR, and it makes the failure message point at whichever symbol sorts first rather than the one just written. --ledger regenerates the block, so burning them down is mechanical.

Barrel re-exports through a relative path or an @object-ui/* sibling aren't counted twice — the declaration they point at is judged on its own turn.

Discrimination proof — three ways it fails

1. Revert ActionType to the pre-#2231 hand-written union:

❌  a spec-named symbol is hand-written, not derived:
    • @object-ui/types declares 1 spec-named symbol the spec already owns:
        type `ActionType`  packages/types/src/ui-action.ts:80  (exported by `@objectstack/spec/ui`)

2. A new fork in a package with an empty ledger:

    • @object-ui/plugin-markdown declares 1 spec-named symbol the spec already owns:
        type `ChartType`  packages/plugin-markdown/src/__proof.ts:1  (exported by `@objectstack/spec/ui`)

3. Fixing a ledger symbol fails until its entry is deleted (shrink-only):

    • @object-ui/types lists 1 symbol in DEBT that no longer collide — `SelectOption`.

Runs in the type-check job after install (it reads the spec's .d.ts, not the build). 5.5s.


objectstack#4118 — 12 packages type-check their tests

A package tsconfig excludes test files — correctly, it is the BUILD config and they'd emit into dist. The hole is that no other tsc invocation read them. objectui#3009 found what that costs: spec-derived-unions.test.ts had built its whole contract on satisfies checks that never ran, under a header calling them "the real enforcement". Reverting a derived alias produced zero errors.

12 free wins, not 8. The extra four fell out of a better config template: plugin-calendar and plugin-kanban needed only the jest-dom matcher types, providers was already clean, and sdui-parser's 50 TS2304s were env globals — exactly as the issue suspected, not real errors.

Wiring sdui-parser up surfaced a real bug. render.test.tsx imports @object-ui/core and @object-ui/react with neither declared in its package.json — phantom dependencies resolved only through the root tsconfig's paths alias and vitest, never as a dependency a consumer would get. Both are devDependencies now, which is also what makes paths: {} in the new config meaningful: with the alias in place, an undeclared workspace import still compiles.

Every tsconfig.test.json follows objectui#3009's template — noEmit, composite: false, paths: {} to kill the TS6059 source-leak noise, and lib / types only where the tests actually need them (mobile reads Array.prototype.at, so ES2022; plugin-report pulls in a source file that reads process.env, so node).

The guard grows a second half so this can't silently regress. A package with test files either compiles them or carries a TEST_DEBT entry with a measured count — re-measured against current main, not copied from the issue's table: 240 code-tier errors across 15 packages. It also fails on a tsconfig.test.json that nothing runs, which is the objectui#3009 shape itself.

Discrimination proof — three ways it fails

1. Unchain plugin-tree's config:

    • @object-ui/plugin-tree (packages/plugin-tree) has a tsconfig.test.json that its "type-check" script never runs,
      so the file looks like enforcement while nothing compiles it — the exact shape of objectui#3009.

2. Delete the permissions TEST_DEBT entry:

    • @object-ui/permissions (packages/permissions) has 3 test files that no `tsc`
      invocation reads: its tsconfig.json excludes them (correctly — it is the build config)

3. A package in both DEBT and TEST_DEBT is rejected as one gap counted twice — this is how layout was caught during the sweep.


objectstack#4075 step 1 — ActionDef's key inventory

ActionDef ends with [key: string]: any. Deleting ActionDef.execute produced zero compile errors (objectui#2990); the same deletion against @object-ui/types' ActionSchema — no index signature — correctly produced TS2353. One reader can catch a retired key, the other is structurally incapable. That's how a typo (targt) and a tombstoned key both reach a runner that then silently does nothing — the #2169 shape.

Step 1 is the non-breaking half: make the key set visible, warn on anything outside it, change no types.

What the inventory found — step 2's worklist:

18 keys the spec owns that ActionDef never declared visible, locations, icon, variant, order, component, bulkEnabled, requiredPermissions, ai, aria, bodyExtra, bodyShape, mode, objectName, recordIdField, recordIdParam, requiresFeature, shortcut
17 keys ActionDef declares that the spec doesn't own actionType, api, chain, chainMode, close, condition, confirm, endpoint, modal, navigate, onClick, onFailure, onSuccess, redirect, reload, toast, actionParams

ActionEngine reads two of the first group through as any casts — (ra.action as any).visible, (action as any).locations. Those casts exist only because the field is undeclared, and they go away when step 2 promotes them.

Two things the inventory corrected:

  • execute is not simply gone from the spec — it's a live tombstone, still in ActionSchema so the parser can reject it by name with the rename prescription (verified by parsing). So it's warned about separately and more loudly: an unknown key is probably a typo, a retired key is metadata that used to work.
  • to / external / newTab / replace are a real objectui dialect — the navigation alias's own spelling, read off the action when no nested navigate object is present. Declared rather than left to trip the warning, with a tripwire test that fails if the spec ever adopts one.

The lists are data because TS types don't survive to runtime, and keyof ActionDef can't substitute — the index signature widens it to string | number, which is the problem itself. actionKeys.pin.test.ts re-derives each list from its real source (the interface via the AST, the spec via its schema), so a hand-maintained list can't drift from what it mirrors.

One pin is deliberately inverted: the suite asserts the index signature is still there. The day that fails, step 3 has landed, tsc catches unknown keys itself, and this warning plus executeScript's rename branch retire together.

Discrimination proof

Dropping any entry from ACTION_DEF_KEYS fails by name:

AssertionError: expected { missing: [ 'target' ], stale: [] } to deeply equal { missing: [], stale: [] }

The warning tests assert it stays silent on a well-formed action, names targt, gives execute its rename prescription, warns once per action rather than per click, still names a second action carrying the same typo, and says nothing in production.


Verification

  • pnpm type-check76/76 tasks successful (3m51s)
  • node scripts/check-type-check-coverage.mjs — green, both halves
  • node scripts/check-spec-symbol-derivation.mjs — green (5.5s)
  • node scripts/check-lint-coverage.mjs — 45/45 packages, 0 errors
  • node scripts/check-changeset-fixed.mjs — green
  • eslint on all new/changed files — 0 errors, 0 warnings
  • Core action tests — 208 passed (11 files), including 12 new
  • Every one of the 12 wired packages verified at 0 errors individually

Changeset: @object-ui/core minor (new public exports). The other 11 packages change only build wiring, so no runtime version bump.

Scope note: all three issues are filed on objectstack-ai/objectstack but every change is in objectui; the sibling repo is untouched.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 6 commits July 30, 2026 11:19
…ctstack#4115)

objectui declares local types and consts under the same names as
`@objectstack/spec` exports, with doc comments claiming spec canonicity. Every
audited instance had either drifted or was one spec release away from it:
`ActionType` (hand union, missing `form`), `ChartType` (7 of 19 members),
`ActionLocation` + 2 (re-declared union + tuple + `z.enum` under a comment that
said "re-export here"), `ActionParamFieldType` (16 of 49 members).

The cost is specific to agent-driven development: an agent reads the comment,
takes it as ground truth, and builds on it — #2901 was filed with a backwards
premise because the fork carried the spec's own symbol name. A wrong
canonical-claim is not stale documentation, it is a planted premise.

Lands as the check rather than an AGENTS.md paragraph, which is the same
"declared != enforced" landmine the thread is about.

- Enumerates all 4231 `@objectstack/spec` export names (types AND values, via the
  compiler's view of each subpath's `.d.ts` — a runtime `import()` sees only
  values, and the drifted symbols are mostly types).
- Flags an exported declaration whose name the spec owns unless it is derived:
  re-exported from the spec, or declared with a spec import in a STRUCTURAL
  position. A spec name merely mentioned inside a members block does not count —
  that is what a fork looks like. Consts do not descend into array/object
  literals, because a faithful copy passes every value comparison and only
  reference identity distinguishes a re-export from a fork.
- Ledger of the 156 pre-existing collisions names each symbol rather than
  counting per package: a count is a budget that lets the next fork land as long
  as an unrelated one was fixed, and it makes the failure point at whichever
  symbol sorts first instead of the one just written. `--ledger` regenerates it.
- Shrink-only both ways: a fresh collision fails by name, and a fixed symbol
  fails until its ledger entry is deleted.

Barrel re-exports through a relative path or a `@object-ui/*` sibling are not
counted twice; the declaration site they point at is judged on its own turn.

Discrimination proof — three ways it fails, run before landing:
1. reverting `ActionType` to the pre-#2231 hand union names it exactly:
   "type `ActionType` packages/types/src/ui-action.ts:80 (exported by
   `@objectstack/spec/ui`)"
2. a new fork in a package with an empty ledger fails on the PR that writes it
3. renaming a ledger symbol to a dialect fails until its entry is deleted

Refs objectstack#4115, objectstack#4074, #3003, #3009, #2944, #2911

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
…now declared (objectstack#4118)

A package tsconfig excludes test files — correctly, it is the BUILD config and
they would emit into `dist`. The hole is that no other `tsc` invocation read them
either, so for most packages nothing compiled a test at all. objectui#3009 found
what that costs: `spec-derived-unions.test.ts` had built its whole contract on
`satisfies` checks that never ran, under a header calling them "the real
enforcement". Reverting a derived alias produced zero errors.

Tests are where agents encode their understanding of a contract. Unchecked, a
wrong understanding accumulates silently and then reads as evidence.

Wires up every package measured at zero code-tier errors — 12, not the 8 the
issue estimated. The extra four fell out of a better config template:
`plugin-calendar` and `plugin-kanban` needed only the jest-dom matcher types,
`providers` was already clean, and `sdui-parser`'s 50 TS2304s were env globals
exactly as the issue suspected, not real errors.

Wiring `sdui-parser` up surfaced a real bug: `render.test.tsx` imports
`@object-ui/core` and `@object-ui/react` with neither declared in its
package.json. Both were phantom — resolved only through the ROOT tsconfig's
`paths` alias and vitest, never as a dependency a consumer would get. Declared as
devDependencies, which is also what makes the `paths: {}` in the new config
meaningful: with the alias in place an undeclared workspace import still compiles.

Every `tsconfig.test.json` follows objectui#3009's template — `noEmit`,
`composite: false`, `paths: {}` to kill the TS6059 source-leak noise, and `lib` /
`types` only where the tests actually need them (`mobile` reads
`Array.prototype.at`, so ES2022; `plugin-report` pulls in a source file that
reads `process.env`, so `node`).

The guard grows a second half so this cannot silently regress. A package with
test files either compiles them or carries a TEST_DEBT entry with a MEASURED
count — re-measured against current main, not copied from the issue's table:
240 code-tier errors across 15 packages. It also fails on a `tsconfig.test.json`
that nothing runs, which is the objectui#3009 shape itself: a file that looks
like enforcement while no compiler reads it.

Discrimination proof — three ways it fails, run before landing:
1. unchaining plugin-tree's config: "has a tsconfig.test.json that its
   type-check script never runs … the exact shape of objectui#3009"
2. deleting the `permissions` TEST_DEBT entry: "has 3 test files that no `tsc`
   invocation reads"
3. a package listed in both DEBT and TEST_DEBT is rejected as one gap counted
   twice (this is how `layout` was caught during the sweep)

Refs objectstack#4118, objectui#3009, objectstack#4074, #2911, #2901

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
…eads (objectstack#4075 step 1)

`ActionDef` ends with `[key: string]: any`, so it accepts any key of any type.
Deleting `ActionDef.execute` produced ZERO compile errors even though the field
had just been removed (objectui#2990), and stale metadata still authoring
`execute: 'markDone'` type-checks today. The same deletion against
`@object-ui/types`' `ActionSchema` — no index signature — correctly produced
TS2353 at the authoring site. One reader can catch a retired key; the other is
structurally incapable.

Step 1 is the non-breaking half: make the key set visible, warn on anything
outside it, change no types.

What the inventory found, which is step 2's worklist:

- 18 keys the SPEC owns that `ActionDef` never declared — `visible`, `locations`,
  `icon`, `variant`, `order`, `component`, `bulkEnabled`, `requiredPermissions`
  and 10 more. `ActionEngine` reads two of them through `as any` casts
  (`(ra.action as any).visible`, `(action as any).locations`); those casts exist
  only because the field is undeclared.
- 17 keys `ActionDef` declares that the spec does not own — `actionType`, `api`,
  `chain`, `onClick`, `toast` and others, several already marked legacy. This is
  objectui's own dialect and needs the #4115 treatment: documented as deliberate,
  or retired.
- `execute` is not simply gone from the spec — it is a live TOMBSTONE, still in
  `ActionSchema` so the parser can reject it BY NAME with the rename
  prescription. So it is warned about separately and more loudly than an unknown
  key: an unknown key is probably a typo, a retired key is metadata that used to
  work.
- `to` / `external` / `newTab` / `replace` are a real objectui dialect — the
  `navigation` alias's own spelling, read off the action when no nested
  `navigate` object is present. Declared here rather than left to trip the
  warning, with a tripwire test that fails if the spec ever adopts one.

The lists are data because TypeScript types do not survive to runtime, and
`keyof ActionDef` cannot substitute — the index signature widens it to
`string | number`, which is the problem itself. `actionKeys.pin.test.ts`
re-derives each list from its real source (the interface via the AST, the spec
via its schema) so a hand-maintained list cannot drift from what it mirrors.

The spec key list is pinned rather than resolved at runtime: `ActionSchema` is a
lazy proxy that does not forward `.shape`, so reading it means walking zod
internals — fine in a test, wrong in shipped code. `@object-ui/types` made the
same call for `ActionComponent`.

Discrimination proof: dropping any entry from `ACTION_DEF_KEYS` fails with
"ActionDef declares keys the inventory is missing: <name>"; the warning tests
assert it stays silent on a well-formed action, names `targt`, gives `execute`
its rename prescription, warns once rather than per click, and says nothing in
production. Core type-checks clean and all 207 existing action tests still pass.

One pin is deliberately inverted: the suite asserts the index signature is STILL
THERE. The day that fails, step 3 has landed, `tsc` catches unknown keys itself,
and this warning plus `executeScript`'s rename branch can retire together.

Refs objectstack#4075, objectstack#3903, objectui#2990, #3856, #3855, #2169, AGENTS.md PD #12

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
Also drops the last `no-explicit-any` lint warning from the pin test's zod
walk — `Record<string, unknown>` with a narrowing helper reads the same
internals without the escape hatch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
Leftover template-string noise from drafting; `${"components"}/src/ui/` is
just "components/src/ui/".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
Keying the warn-once memo on the unknown keys alone reported the FIRST action
carrying `targt` and stayed silent about every other one — sending the author to
fix a button that was only the first symptom. Keyed by action name too; the memo
is bounded by the number of authored actions either way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Jul 30, 2026 11:46am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 27.9 KB 350 KB
Entry file index-BfRGcQBC.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.20KB 2.97KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.12KB 3.41KB
auth (LoginForm.js) 17.86KB 5.29KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.43KB 2.09KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.25KB 1.01KB
auth (org-roles.js) 6.72KB 2.85KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.25KB 0.53KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 457.71KB 100.07KB
core (index.js) 2.16KB 0.78KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 134.67KB 34.24KB
fields (index.js) 222.07KB 54.35KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.46KB 0.96KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 5.37KB 1.72KB
i18n (useObjectLabel.js) 25.17KB 5.80KB
i18n (useSafeTranslation.js) 3.26KB 1.44KB
layout (index.js) 38.45KB 10.67KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.05KB 1.53KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 6.84KB 2.42KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.90KB 12.35KB
plugin-charts (index.js) 60.52KB 17.11KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 111.59KB 28.74KB
plugin-designer (index.js) 210.56KB 42.56KB
plugin-detail (index.js) 221.50KB 54.15KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 106.35KB 25.82KB
plugin-gantt (index.js) 162.26KB 39.53KB
plugin-grid (index.js) 180.86KB 47.45KB
plugin-kanban (index.js) 47.82KB 13.18KB
plugin-list (index.js) 102.39KB 24.18KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 40.32KB 10.53KB
plugin-timeline (index.js) 25.75KB 7.32KB
plugin-tree (index.js) 8.36KB 2.81KB
plugin-view (index.js) 85.91KB 20.99KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 3.47KB 1.54KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 0.77KB 0.41KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (index.js) 2.00KB 0.96KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.04KB 1.93KB
types (system-fields.js) 2.39KB 1.17KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 1.08KB 0.64KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@os-zhuang
os-zhuang marked this pull request as ready for review July 30, 2026 12:39
@os-zhuang
os-zhuang merged commit 62311b6 into main Jul 30, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/zero-error-packages-ci-cleanup-1mgyew branch July 30, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants