Skip to content

test(plugin-detail): stop the record:highlights header narrating a parse mode - #6926

Merged
os-sam merged 1 commit into
mainfrom
claude/issue-5881-record-highlights-header-prose
Aug 31, 2026
Merged

test(plugin-detail): stop the record:highlights header narrating a parse mode#6926
os-sam merged 1 commit into
mainfrom
claude/issue-5881-record-highlights-header-prose

Conversation

@os-sam

@os-sam os-sam commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Fixes #5881

packages/plugin-detail/src/__tests__/recordHighlightsInputs.spec-parity.test.ts took the pin-aware disposition in its body but not in its module header. Forty lines above the file's own behavioural probe, the header still narrated a parse mode as a present-tense fact about the installed @objectstack/spec:

 *     it is actively misleading. `RecordHighlightsProps` is a plain `z.object`,
 *     so an unknown top-level key is STRIPPED on parse with no error, the
 *     manifest gate only validates top-level props and raises no diagnostic,
 *     and the renderer never sees it.

Re-measured on this branch's merge-base — not copied from the card

The card's numbers were taken on 1939c9610. This branch's merge-base is e3d117ae1, installed @objectstack/spec 17.2.0. Measured with a declared-key control in the same run, so a red probe cannot be a rejection of fields:

installed @objectstack/spec = 17.2.0
=== RecordHighlightsProps ===
  control(declared keys only).success = true
  probe(+undeclared top-level key).success = false
  MODE = strict; issue codes = ["unrecognized_keys"]
  unrecognized_keys names = ["__objectui_5881_probe__"]
  specRefusesUnknownTopLevelKeys (as the file computes it) = true

Control green, probe red, exactly one unrecognized_keys naming exactly the probe key. The premise holds: "STRIPPED on parse with no error" is false as written on this pin.

What changed

The paragraph's verdict was never falsified — publishing a top-level input the spec does not declare is actively misleading — only the mechanism it cited. So the verdict stays and the mechanism is replaced by a pin-independent statement that names both shapes as alternatives and hands the present-tense question to the file's own specRefusesUnknownTopLevelKeys. Narrating strict mode as fact would be the same defect with the sign flipped, so the new text asserts neither.

Comment-only, proven rather than claimed

$ git diff -U0 -- packages/plugin-detail/src/__tests__/recordHighlightsInputs.spec-parity.test.ts \
    | grep -E '^[+-]' | grep -v '^[+-][+-][+-]' | grep -vE '^[+-][[:space:]]*\*'
(no output)
NON_COMMENT_LINES_EXIT=1   # grep found none = zero non-comment +/- lines

$ ... | grep -cE '^[+-][[:space:]]*\*'
16                          # all 16 changed lines are comment lines (5 removed, 11 added)

No assertion added, changed or removed — that is deliberately #5887's separate work, not this branch's.

Verification (exit codes captured before any pipe; verdict lines quoted from the tools themselves)

Run at 47c3da232, the branch head this PR carries.

check result
pnpm exec vitest run packages/plugin-detail/src/__tests__/recordHighlightsInputs.spec-parity.test.ts (repo root) before Test Files 1 passed (1) / Tests 5 passed (5)VERDICT command-exit 0
same, after Test Files 1 passed (1) / Tests 5 passed (5)VERDICT command-exit 0 — identical, since nothing executable changed
pnpm --filter @object-ui/plugin-detail type-check > @object-ui/plugin-detail@17.6.0 type-check / > tsc --noEmit && tsc -p tsconfig.test.jsonVERDICT command-exit 0
pnpm exec eslint . in packages/plugin-detail (plain form) ✖ 880 problems (0 errors, 880 warnings), exit 0 — all pre-existing; targeted --format json on the edited file reports errors= 0 warnings= 0
node scripts/check-changeset-presence.mjs ✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)Every one of them has an EMPTY frontmatter — declared as releasing nothing
node scripts/check-changeset-no-major.mjs ✅ No changeset declares a 'major' bump.

The first type-check read RED with Cannot find module '@object-ui/react' and friends — the unbuilt-closure false RED. pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-detail^...' build then re-run gives the green above. The script name is echoed in both readings, so neither is a zero-match silent pass. tsc -p tsconfig.test.json --listFiles lists the edited file (1 hit), so the green is a measurement of it and not a coverage gap.

Scope

Exactly one source file plus its "releases nothing" changeset. recordDetailsInputs.spec-parity.test.ts and recordRelatedListInputs.spec-parity.test.ts are untouched — they belong to #5887, which is in flight in parallel.

Out of scope, filed rather than fixed: #6925 — 11 files still call 17.0.0-rc.6 "the pinned" @objectstack/spec while no manifest in the workspace declares that range and the installed version is 17.2.0. Two of those files are #5887's, so it wants sequencing, not a drive-by here.

⛔ Draft on purpose. The PM lands it: do not mark ready, do not enqueue, do not enable auto-merge.


Generated by Claude Code

…rse mode

`recordHighlightsInputs.spec-parity.test.ts` took the pin-aware disposition in
its body but not in its module header. The header still read:

    `RecordHighlightsProps` is a plain `z.object`, so an unknown top-level key
    is STRIPPED on parse with no error

Measured on this merge-base against the installed `@objectstack/spec` 17.2.0,
with a declared-key control in the same run:

    control(declared keys only).success = true
    probe(+undeclared top-level key).success = false
    MODE = strict; issue codes = ["unrecognized_keys"]
    unrecognized_keys names = ["__objectui_5881_probe__"]

So "STRIPPED on parse with no error" is false as written, and forty lines below
the same file already computes the fact behaviourally as
`specRefusesUnknownTopLevelKeys`.

The verdict the paragraph exists for is unchanged and pin-independent: a
top-level input the spec does not declare is actively misleading. Only the
mechanism it cited was falsified, so the header now states the verdict, notes
that the contract expresses it two ways depending on the installed pin, and
points at the file's own probe instead of asserting either mode as a
present-tense fact -- narrating the other mode as fact would be the same defect
with the sign flipped.

Comment-only. `git diff` on the file carries zero non-comment +/- lines; test
file and test counts are identical before and after (1 file, 5 tests). The
changeset declares empty frontmatter: nothing releases.

Co-authored-by: Claude <noreply@anthropic.com>
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

Metric Value Budget
Eager closure (gzip, 45 chunks) 3178.9 KB 3222.7 KB
Main entry chunk (gzip) 143.6 KB 350 KB
Entry file index-BPHEWE5c.js
Status PASS

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


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 12.46KB 4.71KB
app-shell (runtime-config.js) 20.61KB 7.35KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 512.09KB 116.42KB
core (index.js) 5.30KB 2.13KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 175.69KB 48.80KB
fields (index.js) 243.65KB 61.63KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.95KB 10.97KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.55KB 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.72KB 0.42KB
mobile (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.92KB 12.93KB
plugin-charts (index.js) 64.68KB 18.35KB
plugin-chatbot (index.js) 190.53KB 45.18KB
plugin-dashboard (index.js) 133.48KB 34.51KB
plugin-designer (index.js) 212.87KB 43.19KB
plugin-detail (index.js) 245.40KB 62.44KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 133.32KB 32.69KB
plugin-gantt (index.js) 165.21KB 40.37KB
plugin-grid (index.js) 202.08KB 54.61KB
plugin-kanban (index.js) 53.14KB 14.64KB
plugin-list (index.js) 113.15KB 27.59KB
plugin-map (index.js) 20.20KB 6.66KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.51KB 11.94KB
plugin-timeline (index.js) 29.05KB 8.37KB
plugin-tree (index.js) 8.98KB 3.08KB
plugin-view (index.js) 85.79KB 21.10KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 76.75KB 25.49KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 3.11KB 1.48KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
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) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.72KB 2.24KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 3.40KB 1.71KB
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

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