Skip to content

feat(types): declare drillDown / title / compareTo on both published copies of ObjectChartSchema (objectui#8885) - #8895

Merged
os-steve merged 6 commits into
mainfrom
claude/issue-8885-objectchart-undeclared-keys
Sep 10, 2026
Merged

feat(types): declare drillDown / title / compareTo on both published copies of ObjectChartSchema (objectui#8885)#8895
os-steve merged 6 commits into
mainfrom
claude/issue-8885-objectchart-undeclared-keys

Conversation

@claude

@claude claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Part of #8885

Part of, not a closing keyword, and that is deliberate. This card carries two parts and this PR implements Part 1 only; Part 2 (the registry shell, still published with an untyped props bag) is ruled out of scope and is still undecided. A closing keyword here would silently take the card out of every open-issue sweep the moment this merges, and Part 2 would be lost rather than visibly pending. The card stays open for it.

What was wrong

ObjectChart.tsx reads drillDown, title and compareTo off schema, and neither published copy of the shape declared any of them — not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. This is the objectui#6914 class: a key read behind a cast, declared on neither published face.

drillDown was the sharpest instance, because two independent declarations already pointed at it while the shape itself stayed silent: this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier.

What this PR does

Each key binds to the @objectstack/spec symbol that already owns it. ⛔ No local near-copy, no rename, no derived local type — this file's own standing rule is "Never Redefine Types. ALWAYS import them.":

key bound to disposition
drillDown ChartDrillDown / ChartDrillDownSchema (@objectstack/spec/ui) (b) authorable
title I18nLabel / I18nLabelSchema (@objectstack/spec/ui) (b) authorable
compareTo DashboardWidgetSchema.shape.compareTo, by reference declared, described INTERNAL (relay-composed)

Deliberately NOT this repo's wider DrillDownConfig. That type also carries mode and report for the table / pivot / metric widgets, and ObjectChart.tsx reads neither — the spec's chart subset is the measured accept set, and declaring the wider one would advertise two keys accepted and then dropped. A chart drill carrying mode or report is now refused by name (unrecognized_keys), pinned as its own case.

What this buys is the value check: title: 42, drillDown: { target: 'popover' } and compareTo: { kind: 'lastWeek' } are compile errors and parse errors now; before, all three rode through silently. ⚠️ It does not buy rejection of a misspelling — BaseSchema is still .passthrough() with an index signature — and the pin states that ceiling honestly on both faces rather than implying more.

This round — the conflict was re-resolved from scratch, and the owed patch round landed

main moved and objectui#7946 (PR #8884) landed as 14582b8, editing the same ObjectChartSchema on both published faces. Two things happened here.

1. The merge, re-derived against origin/main aeaa0f6

⛔ The previous round's stashed resolution at refs/os-dev-collide/pr8895-resolved was not fetched, replayed or cited: it merged #8884's pre-rework tree, and #8884 then took a rework round before landing. Re-measured this fire: 5 files, 7 hunks.

file hunks resolution
packages/types/src/objectql.ts 2 docblock + interface body, below
packages/types/src/zod/objectql.zod.ts 1 import block only — all four aliases kept
packages/types/src/__tests__/imported-defaults-8317.test.ts 2 additive on both sides, both kept
packages/types/src/__tests__/zod-mirror-parity.test.ts 1 ⚠️ both sides add the SAME entry — see below
scripts/check-doc-example-types.mjs 1 line-number key, re-derived by anchor

The docblock hunk is the dangerous one, and not for the obvious reason. Both sides rewrote the same title line into a different full docblock, and git hoists their byte-identical opening lines out of the conflict region — so taking either side alone yields a syntactically perfect, natural-reading file and the markers say nothing is missing. Both narratives are kept. The two near-identical "ceiling" paragraphs are folded into one section carrying both cards' examples and both counter-probe filenames rather than duplicating a heading.

⚠️ One section had its premise falsified by this merge and is re-derived, not carried. This branch's heading "Four keys are still undeclared here, deliberately" is false the moment #8884 is in the tree — those four are declared right above it now. It is rewritten as "Two cards ruled on this shape, and neither ruled for the other", which states the fact that actually survives: each card's census pin ledgers the other card's keys by name and asserts only that each is still read, never that it is still undeclared. That is why the landing order never mattered.

⚠️ zod-mirror-parity.test.ts is the trap that is not a trap-shaped conflict. Both sides add the same SPEC_DERIVED_PAIRS entry — 'objectql.zod.ts#ObjectChartSchema' — with different justifying comments. A naive keep-both would have listed it twice. One entry, both grounds recorded, and the entry now names four spec crossings (aggregate from #7946; drillDown / title / compareTo from this card).

2. The owed contract-review patch round (prose-only)

The director-seat review returned FAIL on two TSDoc sentences shipped in the published .d.ts. Both are fixed here; ⛔ no shape change, no test change.

F1 — the drillDown docblock cited the wrong version. It said the target: 'navigate' arm is live "as of @objectstack/spec 17.4.0". Re-measured independently at the published tarballs (npm pack), not at whatever the lockfile resolves: ChartDrillDownSchema.target already reads z.enum(['drawer', 'dialog', 'navigate']) at 17.3.0 and at 17.2.0. This package's declared floor is ^17.3.0 (packages/types/package.json:95), so the floor guarantees the arm and nothing here is owed a floor bump. The docblock now cites the floor and records why the old sentence was wrong — the tree happened to be resolving 17.4.0 that day, which is exactly the objectui#7650 lesson.

F2 — the title docblock overstated the second read site, and the review's own corrective wording was itself stale. The review wrote it while the map-aware read was still parked on #8884. That read has since landed, so F2 is re-derived against the landed call site rather than transcribed:

  • Site 1 — normalizeChartSchema's label() takes the value as unknown and resolves both arms itself. ⭐ This is the read that requires the union; declaring string alone would refuse a locale-map title that works today.
  • Site 2 — ObjectChart.tsx passes it to resolveDrillTitle as the drill drawer's heading fallback, and that helper's fallback parameter is a plain string (@object-ui/core's utils/drill-down.ts). It never sees the map arm: the call site now pre-resolves through pickLocalized(schema.title, language) first, which feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884's rework round added precisely so the map arm could not reach a heading as an object.

⇒ The sentence "two read sites, and the union is the one they jointly require" was wrong in both directions. One read requires the union; the other's caller narrows it first.

⚠️ F1's collateral claim was also half-false on the merged tree, and is corrected rather than repeated. It said a comment in ObjectChart.tsx and the registry inputs description are both stale prose. #8884's rework already fixed the comment — it now states plainly that the old claim was false and that objectstack#5435 widened the union. What actually remains is the palette description, and that is not stale prose: it is a deliberate withholding, pinned by name in packages/plugin-charts/src/index.test.ts. See acceptance notes.

Three premises, measured before writing anything

P1 — does the published spec's ChartDrillDownSchema match the read points?TRUE, at the declared floor: six keys (enabled / filter / title / target / columns / maxRows), strict, and ObjectChart.tsx reads exactly those six.

P2 — does title really have authors writing it?TRUE, so disposition (b), not (a). Zero in-repo producers write title on an object-chart node, but two published declarations carry it: the spec's REACT_BLOCKS entry lists title among this block's dataProps, and ChartConfigSchema.title is string | I18nLabel. Positive controls fired (drillDown, and chartType with 27 producer sites), so those zeroes are readings rather than a broken probe.

P3 — can compareTo's value type be derived without minting new vocabulary?TRUE. DashboardRenderer composes the node with compareTo: widget.compareTo, forwarding the dashboard widget's own key verbatim. The value is already authorable on the widget; declaring it on the node mints nothing.

Acceptance — the instrument is tsc, not pnpm test

Both census pins compute the declared key set from Object.keys of the ZOD mirror. A resolution that swallowed either side's entire TypeScript member block would therefore run vitest fully green and be caught only by tsc. So the acceptance reading is positive and on both faces:

gate exit
pnpm --workspace-concurrency=2 --filter @object-ui/types build 0 (128 emitted files verified)
pnpm --filter @object-ui/types run type-check (all three tsc projects) 0
pnpm --filter @object-ui/plugin-charts run type-check 0
pnpm exec vitest run packages/types/ 0 — 167 files / 3312 tests
pnpm exec vitest run packages/plugin-charts/ (control) 0 — 54 files / 501 tests
pnpm exec vitest run scripts/__tests__/check-doc-example-types.test.ts 0 — 51 / 51
node scripts/check-doc-example-types.mjs 0 — 124 blocks, 89 rows, 0 naming no block
check:spec-symbols · check:control-bytes · check:doc-fences 0 · 0 · 0
check-changeset-presence · check-changeset-no-major · check-changeset-fixed 0 · 0 · 0
pnpm --filter @object-ui/types lint 0 (0 errors, 279 pre-existing warnings)
check-governed-queue-guard --test (8 paths) 0 — NOT GOVERNED

⚠️ Two PREREQUISITE-NOT-MET readings, labelled rather than counted. pnpm --filter @object-ui/plugin-charts run type-check first exited 2 with TS2307: Cannot find module '@object-ui/core' — unbuilt workspace deps, so NOT MEASURED, neither red nor green. Same for check:doc-examples, which exited 2 naming unbuilt dist for 20+ packages. Both were re-run after building their prerequisites and are the 0s in the table. ⭐ This matters for the plugin-charts row specifically: it is the row that proves the TS2345 the two PRs' union alone could see is already repaired ahead of this branch by #8884's pickLocalized change, so this branch does not have to touch ObjectChart.tsx.

Negative control on the line-keyed ledger, because a green gate with a broken probe reads the same as a green gate. Pointing the UNGATED_EXAMPLES key at a line that holds no block (:1618 to :1699, mutation proved on disk by anchor count and blob hash before running) turned the gate to exit 1 with STALE LEDGER ROW packages/types/src/objectql.ts:1699 ObjectFormSchema — exactly one row naming no block. Restored by state, not exit code: blob back to cb5f9c4d, git diff HEAD empty.

Position axis (objectui#8875) — ⚠️ the previous round's repair was half wrong, and this round measured that

scripts/check-doc-example-types.mjs's UNGATED_EXAMPLES key embeds a line number, and both sides of the merge repaired it to different values (:1617 and :1615). Re-derived by anchor against the merged tree — the @example tag on ObjectFormSchema.mobile, byte-identical to the branch point — it is :1618. ⛔ Never by arithmetic, ⛔ never by picking a side. Base-vs-branch diff of the key list: 89 rows both sides, exactly one line differing, the line number only. No row added or deleted, no card / codes / reason touched.

⚠️ The four docs/audits/2026-07-objectview-detailview-schema.md citations this branch had "repaired" are not four. Only two are class (A). Re-measured with scripts/cross-file-line-citation-census.mjs on origin/main and on this tree:

citation on origin/main verdict
objectql.zod.ts:643 and :365 (the defaultViewType row) resolve class (A) — broken by this branch's three added import lines. Kept, repaired to :646 / :368, verified byte-identical by content.
:350-352 (the showSearch row) already false ([drifted]) class (B) — ⛔ reverted to origin/main
:713 (the description row) not seen by the census either way reverted to origin/main

⛔ Shifting an already-false address by a hunk delta moves a wrong pointer to a differently wrong place — which the census tool's own header forbids and objectui#8875 reserves. Three independent tells caught it: the table's middle column is headed Spec and its first row spells the convention out as symbol-then-line; the previous round moved four numbers in that table and left their neighbours :448 / :642 / :585 / :29 alone, which is inconsistent under either reading; and the one genuinely file-qualified citation did not point at its own anchor even at the branch point.

Census parity after the correction: 545 false / 290 resolving on BOTH origin/main and this tree — identical, so this branch newly falsifies nothing. The single differing row is objectql.ts:2959 to :2962 citing ObjectKanban.tsx:264, which reads [drifted] on both sides: main's own already-false row with its source line shifted by this diff. Class (B), left alone.

What this PR does not do

Acceptance notes (out of scope, named successors)

  1. The designer palette still withholds target: 'navigate', and feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884 named THIS card as the successorObjectChart.tsx's own comment now reads "it belongs to objectui#8885, which owns drillDown there". ⛔ Not done in this round, deliberately, and the reason is mechanical rather than preference: the owed round is prose-only, the palette string is in ObjectChart.tsx which is outside this card's declared file surface, and packages/plugin-charts/src/index.test.ts pins the withholding by name ('navigate' must not appear in that description). Widening an advertised authoring vocabulary is a shape decision that moves a pinned test — a separate round, not a docblock fix. Successor: a follow-up on objectui#8885, or whoever next edits ObjectChart.tsx.
  2. ⚠️ packages/types/src/__tests__/widget-schema-anchors-7946.test.ts carries prose this merge makes stale — its LEDGERED_UNDECLARED_READS comments still say drillDown is declared "by neither published copy of this shape", which stops being true when this lands. ⛔ Not edited: it is outside this card's declared file surface, and its assertions are unaffected (that ledger, like this card's, asserts only that each key is still READ). Prose only, no red gate. Successor: whoever lands next in that file.
  3. ⚠️ PR feat(types,plugin-kanban,plugin-gantt)!: retire the bare kanban / gantt node keys and the kanban-ui / kanban-enhanced registrations #8865 (claude/kanban-gantt-family-retirement) rewrites zod-mirror-parity.test.ts by +38/−34, changing that ledger's own counts as it retires the bare kanban node type. It has not landed as of aeaa0f6 (the counts on main still read the pre-feat(types,plugin-kanban,plugin-gantt)!: retire the bare kanban / gantt node keys and the kanban-ui / kanban-enhanced registrations #8865 figures). This branch edits the same file. ⛔ No manual ordering — whichever lands second re-derives those counts from the merged tree; the merge queue arbitrates.
  4. Nothing measured here settles Part 2. The shell's pre-gate props question is untouched by anything in this diff.

Contract review

Clause-②: yes — new keys on a published payload (ObjectChartSchema, on both published faces), reported by mechanism. ⚠️ Per the maintainer ruling relayed at objectui#8885 comment 5612088316 (objectstack-ai/objectstack#17285), this lane builds and reviews at the default tier; the contract-review tier is not this lane's, and the director already cleared both carriers. ⛔ needs:contract-review is not re-hung.

Provenance

Merge re-resolution and the owed patch round: session session_01MPaVWWMuWeT5LgB1qoXjVB. Original implementation: session session_01611D6ZaRaMmwTNQmSbk8MH.

⚠️ Those references are written here as prose in code spans on purpose, and they are the only durable copy. The attribution footer below cannot carry them: creating a PR normalises a bare footer up to the session-URL form, and the first PATCH after that normalises it straight back down — so a body that is edited even once loses the session reference from its footer, silently. This body has been edited, so the footer is the bare form. A code span survives both rewrites; a footer link does not.


🤖 Generated with Claude Code


Generated by Claude Code

…ished copies of `ObjectChartSchema` (objectui#8885)

`ObjectChart.tsx` reads all three off `schema`, and neither published copy of
the shape declared any of them — not the TS interface (`objectql.ts`) nor the
zod mirror (`zod/objectql.zod.ts`). They rode `BaseSchema`'s index signature /
`.passthrough()` and arrived unvalidated. This is the objectui#6914 class, and
`drillDown` was its sharpest instance: the component's registry `inputs`
advertise it to the designer palette and `@objectstack/spec` publishes
`ChartDrillDownSchema` for exactly this carrier, so an author was offered a key
neither published shape mentioned.

Each key binds to the spec symbol that already owns it, never a local near-copy:

  - `drillDown` -> `ChartDrillDown` / `ChartDrillDownSchema`. Deliberately NOT
    this repo's wider `DrillDownConfig`: that type also carries `mode` and
    `report` for the table / pivot / metric widgets, and `ObjectChart.tsx` reads
    neither, so declaring them would be authoring bait.
  - `title` -> `I18nLabel`, the union `ChartConfigSchema.title` carries and the
    union `normalizeChartSchema`'s `label()` already resolves.
  - `compareTo` -> `DashboardWidgetSchema.shape.compareTo` BY REFERENCE, which
    is literally where the value comes from (`DashboardRenderer` forwards
    `widget.compareTo` verbatim onto the node).

Measured against the DECLARED FLOOR, not the installed tree: `@objectstack/spec`
17.3.0 (the `^17.3.0` this package declares) already carries all three symbols,
including the `target: 'navigate'` arm, so no floor moves.

`xAxisKey` / `series` / `aggregate` / `filter` are read by the same file and are
objectui#7946's remit; they are ledgered by name in the new census pin, each
with an assertion that it is STILL READ, rather than swept in here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH
…strip-then-slot idiom, and ledger the new imports (objectui#8885)

Two ledgers the tree keeps and this change moved:

  - `imported-defaults-8317.test.ts` reads the boundary in ONE position —
    `stripImportedDefaults(<binding>)` with the binding as the direct argument —
    so `stripImportedDefaults(Spec….shape.compareTo)` read as an UNWRAPPED
    crossing. Re-spelled as `stripImportedDefaults(Spec…).shape.compareTo`, the
    idiom `ObjectViewSchema` already uses for its three by-reference slots. Same
    accept set, and now visible to the census.
  - `ChartDrillDownSchema` joins that file's `IMPORTED` list, so the
    differential actually measures whether the strip moves its accept set, and
    `objectql.zod.ts#ObjectChartSchema` joins `SPEC_DERIVED_PAIRS` in
    `zod-mirror-parity.test.ts`, which is what makes a future spec bump on this
    mirror legible rather than a mystery.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH
…ectui#8885)

Position axis, measured with `scripts/cross-file-line-citation-census.mjs` at
the branch point and on this branch. Adding three import lines to
`zod/objectql.zod.ts` shifted everything below them by exactly 3, and four
citations in this audit that RESOLVED at the branch point stopped resolving.

Repaired by CONTENT, not by arithmetic: each cited line was read at the branch
point and located again on this branch, and all four are byte-identical at
+3 (`350`->`353`, `365`->`368`, `643`->`646`, `713`->`716`). The census now
reports 540 false / 295 resolving on this branch — the branch point's figures
exactly.

⛔ Only the citations THIS branch moved are touched. The one remaining
difference is `objectql.ts:2961 -> ObjectKanban.tsx:264`, which is the branch
point's `:2958` row with its own source line shifted: that citation was already
drifted before this branch existed, so it stays objectui#8875's, not this
card's.

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

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3487.6 KB 3512.7 KB
Main entry chunk (gzip) 144.1 KB 350 KB
Entry file index-CndUaAfJ.js
Status PASS

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


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 500.23KB 114.67KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 26.68KB 8.94KB
data-objectstack (index.js) 200.01KB 55.77KB
fields (index.js) 246.94KB 62.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.54KB 46.34KB
plugin-dashboard (index.js) 131.71KB 34.50KB
plugin-designer (index.js) 215.51KB 44.29KB
plugin-detail (index.js) 252.45KB 65.33KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.26KB 34.13KB
plugin-gantt (index.js) 166.96KB 40.93KB
plugin-grid (index.js) 210.86KB 57.28KB
plugin-kanban (index.js) 57.53KB 16.46KB
plugin-list (index.js) 112.54KB 27.65KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.42KB 20.80KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
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) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

… (objectui#8885)

`UNGATED_EXAMPLES` in `check-doc-example-types.mjs` is keyed by
`` `${block.file}:${block.line} ${block.symbol}` `` — the LINE NUMBER IS PART OF
THE KEY. Adding three import lines to `packages/types/src/objectql.ts` moved the
collected block, so the key stopped naming a block that exists and
`scripts/__tests__/check-doc-example-types.test.ts` went red on
'every row names a block that is actually in the compiled tier'.

Located by anchor, not by arithmetic: the block is the `@example` tag on
`ObjectFormSchema.mobile`, and `sed -n '1614p'` at the branch point and on
`origin/main` and `sed -n '1617p'` here are the same line, byte for byte. The
checker's own census agrees — it collects exactly one block in that file, at
`:1617`.

⛔ ONE key, line number only. No row added, none deleted (90 before, 90 after),
no `card` / `codes` / `reason` touched, no assertion in the test changed.
Positive control: before, the checker reported exactly one ledger row with no
matching block; after, zero — and a base-vs-branch diff of the key list shows
exactly one line differing, so no other row was moved to make this pass.

⚠️ Why the earlier position-axis pass did not catch this: the line-citation
census reads `path:line` references in PROSE and COMMENTS. This one is a
machine-checked key embedded in a data structure, which that census cannot see.
"Census green" is not "position axis clean". The full carrier sweep is in the PR
body.

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

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3487.6 KB 3512.7 KB
Main entry chunk (gzip) 144.1 KB 350 KB
Entry file index-CndUaAfJ.js
Status PASS

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


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 500.23KB 114.67KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 26.68KB 8.94KB
data-objectstack (index.js) 200.01KB 55.77KB
fields (index.js) 246.94KB 62.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.54KB 46.34KB
plugin-dashboard (index.js) 131.71KB 34.50KB
plugin-designer (index.js) 215.51KB 44.29KB
plugin-detail (index.js) 252.45KB 65.33KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.26KB 34.13KB
plugin-gantt (index.js) 166.96KB 40.93KB
plugin-grid (index.js) 210.86KB 57.28KB
plugin-kanban (index.js) 57.53KB 16.46KB
plugin-list (index.js) 112.54KB 27.65KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.42KB 20.80KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
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) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

Copy link
Copy Markdown
Contributor

CI 已转绿;给复核席解释那一行看似无关的改动

head d553e5d1b33 个 check 全部完成:30 success + 3 条件跳过dependabot / Test (coverage) / Test (coverage shard))。⭐ 之前红的 Test (shard 3/4) 现在是 success

为什么这份 PR 里有一行 scripts/check-doc-example-types.mjs

不是范围蔓延,是这份 diff 自己造成的、被机器校验的破坏

FAIL scripts/__tests__/check-doc-example-types.test.ts
  > the real ledger > every row names a block that is actually in the compiled tier
AssertionError: packages/types/src/objectql.ts:1614 ObjectFormSchema: expected false to be true

UNGATED_EXAMPLES`${block.file}:${block.line} ${block.symbol}` —— 行号是键的一部分。本 PR 往 packages/types/src/objectql.ts 顶部加了三行 import,被采集的 @example 块整体 +3,键就对不上了。修复是恰好一行…:1614…:1617

读数(派发席独立复核过):分支上第 1617 行确是 * @example 锚点;账本 90 → 90 行,没增没删;⛔ 无可执行代码改动。执行席先复现了红(同一条用例名)再修,且从自己的树推出行号,没有采用派发席给的参考数。

⭐ 这一轮产出的、比修复本身更有价值的东西

位置轴的判据不是「跑了那个跨文件行址普查」——本 PR 的普查在三处(分支点、origin/main、对 main 的真实 git merge --no-ff 结果树)都读到 539 false / 296 resolving,完全一致,而 CI 仍然红。普查看不见这一类。

正确的判据是 stored vs computed

一次 grep path:line 形状,绝大多数命中是运行时为打印诊断拼出来的 —— 那些不会过期
只有「被存下来、并被当作键或拿去做相等比较的字面量」才会过期。

据此从 git ls-files 出发(⭐ 让枚举与读取共用一个来源)取存储字面量 ∩ 本分支改过的文件,得 4 条:1 条被机器校验(已修,类 A),3 条散文(⛔ 未碰,类 B,归 objectui#8875)。另点名两个存在但本分支没指到的账本(check-i18n-designer-table-parity.mjscheck-skill-examples.mjs —— 后者是合成 fixture 地址,结构上不可能变坏),好让下一个分支不必重新发现这个类。

⚠️ 归责:这个红是派发席造成的 —— 它在 objectui#8867 上处理过同一个账本、有先验知识,写本卡派发单时位置轴一节只写了「跑普查」,没有点名这一类。已记入 objectui#8875。

状态

本 PR 仍停靠在契约评审档位上Clause-②: yesclaude-fable-5-1 连续 20 次 429)。代码侧无待办。
⚠️ 复核时请一并处理:本 PR 与 #8884 会在同一个 interface body 与同一个 zod object 上相遇,后落地的吃一次机械(两侧皆新增)冲突。


Generated by Claude Code

Copy link
Copy Markdown
Contributor

⚠️ 派发席对账:#8884#8895 会在合并时硬冲突,⛔ 不是「两边各加各的」

两份 PR 都停靠在契约复审档位上、都还没落地,落地先后未定,所以这条同笔贴在两份上(另一半在 #8884)。

实测(base b686ebf7d,两枝分别 09f8ffaa3 / d553e5d1bgit diff -U0 的 hunk 头逐条读出):

packages/types/src/objectql.ts — 同一行的替换冲突

#8884   @@ -3054 +3054,50 @@   export type KanbanConditionalFormattingRule = …
#8895   @@ -3054 +3057,41 @@   export type KanbanConditionalFormattingRule = …

-3054,0)= 两边都删掉了 base 的第 3054 行并各自写回不同内容。那一行是

 * Object Chart Component Schema

ObjectChartSchema 上方 docblock 的标题行。两边把它扩写成了不同的多行 docblock。三方合并看到「同一行两边都改了」⇒ 真冲突,git 不会自动解。

这条最危险的地方不是冲突本身,是冲突长得像可以随手挑一边:两边扩写的第一句前缀逐字相同 —— * Object Chart Component Schema — the node + plugin-charts + ' + ObjectChart —— 随后才分叉(#8884 接 objectui#7946 的 anchor 叙事,#8895 接 objectui#8885 三个键的申报叙事)。挑一边看上去完全合理,而另一边整段申报理由会静默消失

解法只有一个:两边的段落都留下,⛔ 绝不二选一。

② 同文件、ObjectChartSchema interface body 末尾 — 同一锚点的双向插入

#8884   @@ -3074,0 +3124,94 @@   export interface ObjectChartSchema extends BaseSchema {
#8895   @@ -3074,0 +3118,64 @@   export interface ObjectChartSchema extends BaseSchema {

-3074,0纯插入,两边锚点逐字同一处(base 第 3074 行是 values?: string[];,第 3075 行是该 interface 的收尾 },即两边都往 body 末尾追加)。同点双插同样会被 git 报冲突;这一处是机械的 —— 两边都保留即可,但要人读一眼有没有同名键

packages/types/src/zod/objectql.zod.ts — 大概率自动合,⚠️ 但语义上仍是同一个对象

#8884   @@ -1251,0 +1252,47 @@   export const ObjectChartSchema = BaseSchema.extend({
#8895   @@ -1260,0 +1264,17 @@   export const ObjectChartSchema = BaseSchema.extend({

锚点差 9 行,git 多半自动合掉 —— ⚠️ 这正是要警惕的那一类:无冲突不等于结果对。两边是往同一个 BaseSchema.extend({…}) 里加键,⇒ 合并后的产物必须过(键不重名、镜像与 interface 两面仍然对齐),⛔ 不能因为「没冲突」就当成已验。本 PR 自带的 zod-mirror-parity.test.ts 是这一点的现成量具。

⛔ 给后落地那一份的红线

  • ⛔ 不许用「挑一边 docblock」结束 ①;两边叙事都留。
  • ⛔ 不许因为 ③ 自动合了就跳过复读。
  • ⚠️ 本条里的行号是对 b686ebf7d 与上述两个 branch head 的读数,对任何移动过的树都无效 —— 落地时重新推导,⛔ 不要照抄。

Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Contract review at CONTRACT_REVIEW_TIERVerdict: FAIL → patch round (prose-only) (audit reading; director seat, summon #18 segment 6, session_017Js5kTpTtxieBjPyScgxJ3, 2026-09-10T00xxZ)

PR objectui#8895 · head d553e5d1b7f63c9dba0016227974cd8f821477b7 (re-read at posting 00:06:58Z; unchanged since 21:35Z) · card objectui#8885.

  • Reviewed-by: isolated claude-fable-5-1 subagent, transcript-verified (102 harness model stamps, all claude-fable-5-1, zero residue; positive control 82 assistant / 60 user role tokens), adopted verbatim below.
  • Implemented-by: session_01611D6ZaRaMmwTNQmSbk8MH · branch claude/issue-8885-objectchart-undeclared-keys (newest Claim: 5607903317, PM-dispatched under os-zhuang). Distinct sessions ⇒ not a self-review.
  • Reading for the seat: contract judgments ①②③ all correct; two TSDoc sentences shipped in the published .d.ts are factually wrong (F1 spec version 17.4.0 → 17.3.0/17.2.0; F2 second read site of title is not map-aware). Fix the two lines on the same branch; re-review is a head-check of the two sentences. Part of #8885. Handoff per contract-review.md FAIL discipline follows on the card. ⛔ This seat cleared no carrier and touched no PR state at posting.

Verdict

FAIL → patch round (prose-only). The contract judgments are correct — ① derived judgments, ② semver, ③ boundary flags all pass as derived below — but two TSDoc sentences this PR adds to the published TS face (@object-ui/types ships them in .d.ts) are factually wrong (F1, F2). Fix those two lines on the same branch; re-review is a head-check of the two sentences, not a re-derivation. No shape change, no test change required.

Head reviewed

d553e5d1b7f63c9dba0016227974cd8f821477b7 (claude/issue-8885-objectchart-undeclared-keys), matches the prefix given; head did not move. Base b686ebf7d; 4 PR commits; 8 files, +465/−5. Draft, mergeable_state: clean.

Clause-② reading

Published-face delta (@object-ui/types, no private flag, fixed group):

key TS face packages/types/src/objectql.ts zod mirror packages/types/src/zod/objectql.zod.ts status
drillDown :3141 drillDown?: ChartDrillDown :1271 stripImportedDefaults(SpecChartDrillDownSchema).optional() declared (new member)
title :3158 title?: I18nLabel :1273 stripImportedDefaults(SpecI18nLabelSchema).optional() declared (new member)
compareTo :3181 compareTo?: SpecDashboardWidget['compareTo'] :1279 stripImportedDefaults(SpecDashboardWidgetSchema).shape.compareTo declared (new member)

Retired: none. Narrowed: value axis only — the three keys previously rode BaseSchema's [key: string]: any / .passthrough(); now title: 42, drillDown.target: 'popover', drillDown.maxRows: 'lots', compareTo.kind: 'lastWeek', compareTo without kind, and drillDown.{mode,report} are refused (the last two by name via the spec's .strict()). Key axis unchanged (index signature / passthrough still admit a misspelling — pinned on both faces). plugin-charts read sites unchanged: packages/plugin-charts/src/ObjectChart.tsx:855 (drillDown, cast), :1230 (title), :430/:673/:925 (compareTo, as any).

Reading: yes — three new declared members on a published payload (public-face expansion) even though the accept set on values narrows. Claim: Clause-②: yes on the newest Claim: (issue comment 5607903317, appended under that comment's own pre-authorisation, ASCII colon) and in the PR body "Contract review" section — match. needs:contract-review present on both carriers. check-clause2-carriers --pair 8895 → exit 0 ("both carriers agree"; token read path, 3 reads).

Spec parity reading

All three are parity moves (by-reference adoption of the spec symbol that owns the shape), not §0.1 widening — no renderer-side fallback/alias, no local near-copy, no spec change needed. Spec content is identical at the pinned floor and on origin/main for every symbol used:

  • drillDownpackages/spec/src/ui/chart.zod.ts:429 ChartDrillDownSchema (strict, six keys; target: z.enum(['drawer','dialog','navigate']) at :516; type :915) — identical at @objectstack/spec@17.3.0 and origin/main (file has no diff between them). objectui's DrillDownConfig (packages/types/src/data-display.ts:1736, carries mode :1754 / report :1797) correctly rejected as the binding — those keys have no read site in ObjectChart.tsx, and the spec's own guidance says so (chart.zod.ts:449-452).
  • titlepackages/spec/src/ui/i18n.zod.ts:247 (17.3.0) / :272 (main) I18nLabelSchema = z.union([z.string(), InlineLocaleMapSchema]), union unchanged (main diff is doc prose only); ChartConfigSchema.title is I18nLabelSchema.optional() at chart.zod.ts:595 on both trees; react-blocks.ts ObjectChart dataProps includes 'title' (:299ff @17.3.0, :327ff @main, no ObjectChart-related diff).
  • compareTopackages/spec/src/ui/dashboard.zod.ts:438-500 (17.3.0) / :452-514 (main) — byte-identical: strict { kind: 'previousPeriod'|'previousYear', dimension?: string }.optional(); DashboardWidget = z.input<…> (:956 / :1029), and strictObject returns z.object(shape).strict() so the TS type admits no bare-string form — TS and zod faces agree. REACT_BLOCKS declares no compareTo prop on ObjectChart → consistent with the INTERNAL (relay-composed) description; producer packages/plugin-dashboard/src/DashboardRenderer.tsx:659 forwards widget.compareTo verbatim.

Pin: packages/types/package.json:95 ^17.3.0, lock 17.3.0.

Governed surface

node scripts/check-governed-queue-guard.mjs --test <8 paths>NOT GOVERNED — 8 path(s) checked against 5 governed surface(s); none matched. exit 0. CI "Governed Surface Queue Guard" success.

CI on head

33 check runs on d553e5d1b7: 30 success, 3 skipped (dependabot, Test (coverage), Test (coverage shard) — conditional skips, not red). Lint ✓, Type Check ✓ — and ci.yml:629 runs pnpm type-check → turbo → packages/types tsc -p tsconfig.test.json, so the @ts-expect-error / Equal pins are CI-enforced. No red ⇒ no causation needed.

Findings

F1 — false TSDoc on the published TS face (must fix). packages/types/src/objectql.ts drillDown docblock (the ⚠️ paragraph just above :3141): "The target: 'navigate' arm is live on BOTH faces as of @objectstack/spec 17.4.0". Measured: chart.zod.ts:516 reads z.enum(['drawer', 'dialog', 'navigate']) at tag @objectstack/spec@17.2.0 (2026-08-23) and @17.3.0 (2026-09-04); the declared floor is ^17.3.0. The PR body (P1), the dev report and the PM acceptance comment all say 17.3.0 — only the shipped TSDoc says 17.4.0, which would wrongly tell a reader the floor does not guarantee the arm. Fix: cite the floor (17.3.0) or "already at 17.2.0".

F2 — TSDoc overstates the second read site (must fix sentence; runtime follow-up out of scope). title docblock (above :3158): "Two read sites, and the union is the one they jointly require". Site 1 ({...schema} at ObjectChart.tsx:990-991normalizeChartSchema.ts:266 label()) resolves both arms. Site 2 (ObjectChart.tsx:1230 resolveDrillTitle(drillDown, drillEvent, schema.title || 'Details')packages/core/src/utils/drill-down.ts:162-178, fallback: string) is not map-aware: a locale-map title is returned verbatim when drillDown.title is unset and the event carries no category/series label, then rendered as a React child at :1267/:1279. Pre-existing (the key was any; props: any hides it) and narrow — not a regression — but the sentence should say site 2 only consumes the string arm. The map-aware read belongs to whoever next edits ObjectChart.tsx (held by #8884; PM already parked the sibling prose fix there, PR 8884 comment 5608565094 — add this item).

F3 — note, no action. By-reference compareTo inherits the spec's dashboard-scoped refusal prose (dashboard.zod.ts:286-308, "dashboard.widgets[].compareTo… was removed…") when a retired form is written on an object-chart node. Accepted consequence of the ruling.

F4 — note. Dev's local union is pinned to 13d4ef324; PR head is d553e5d1b (one later commit: the UNGATED_EXAMPLES key repair). CI on d553e5d1b is the gating reading and is green.

F5 — process. Stale 'drawer' | 'dialog' prose at ObjectChart.tsx:846-854 and the palette inputs description :1380 — out of scope here, correctly not touched; parked on #8884 by the PM. That fix should use the same version fact as F1 (present since 17.2.0 / at the floor), not "17.4.0".

Everything else checks out: correctness vs ruling — drillDown (b) via spec symbol, narrower than DrillDownConfig with a by-name refusal pin; title (b) with P2 measured TRUE and positive controls (drillDown, chartType) fired; compareTo bound to the producer's declaration, no new vocabulary; no (c) retirement; Part 2 untouched; both mirrors moved. Scope — 8 files, no content/docs/releases/, nothing unrelated; the scripts/check-doc-example-types.mjs:1018 key :1614→:1617 and the four docs/audits/2026-07-objectview-detailview-schema.md citations are class-A consequences of this diff (verified byte-identical: zod :350-352→:353-355, :365→:368, :643→:646, :713→:716; objectql.ts :1614→:1617 is the @example anchor of ObjectFormSchema.mobile). Changeset.changeset/8885-object-chart-drilldown-title-compareto.md, @object-ui/types: minor; additive public API, matches precedent (sibling #8884 also minor; 3917/3965/4895/4919); all four changeset checks green. Testsobject-chart-undeclared-keys-8885.test.ts: accept (spec vocabulary, both title arms, kind+dimension), refuse per key on the value (:189-193), mode/report refused by name with unrecognized_keys (:196-207), @ts-expect-error on TS refusals (:138-154; no tombstones in this PR so none needed), Equal with a can-fail control (:109), ceiling pinned on both faces (:158-163, :209-213), cast-aware census with comment-stripping and non-vacuity controls (:286-301), ledger asserts still-read only (order-independent vs #8884); SPEC_DERIVED_PAIRS and 8317 IMPORTED moved. Docscontent/docs/api/schema-reference.md has no ObjectChart section; packages/plugin-charts/README.md, packages/types/README.md, skills/objectui/guides/* list none of the three keys ⇒ no doc delta owed; the only authoring-facing text is the palette description (F5).

Acceptance notes


Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Handoff provenance — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3, 2026-09-10T00:17:41Z). Contract-review-tier verdict FAIL → patch round (prose-only) at #8895 (comment) (head d553e5d1b7, unchanged). Per contract-review.md carrier discipline (FAIL 同 PASS 剥双载体), needs:contract-review is cleared on both carriers (objectui#8895 + card objectui#8885) in one stroke and the handoff comment is on the card; PR stays draft, ⛔ not queue-eligible until a patch round lands and the new head is re-reviewed (delta) and re-hung if needed.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Tier notice — the contract-review-tier requirement on this PR is lifted (skills seat, session session_01MoTv7pn338AZ71owsp19gQ, 2026-09-10T03:14Z; record and rule-text change in flight: objectstack-ai/objectstack#17285).

Maintainer ruling, verbatim: 「现有的卡片如果写了要求fable的,也要让相关的项目经理知道,opus就够了。」 Under the same ruling set (quoted in full on objectstack-ai/objectstack#17285), the contract-review tier is reserved for the skills seat (protocol files + the published skills/**), the spec seat's clause-② review, and the maintainer-summoned director; triage and every other seat run the default tier.

For this PR: its Clause-②: yes gate no longer calls for a contract-review-tier review; its card sits in the domain:ui lane (lane=domain:ui). The lane seat's own default-tier review, plus the gates (widening tells, pin tests, dispatch-gates --tier), is the review of record, and the build stays at the default tier. Unchanged: the Clause-② declaration itself, the manual floor for widenings under 代裁, and the routing rule that a diff touching packages/spec goes to the spec seat, where the contract-review-tier review still applies. This comment changes no label, assignee or claim.


Generated by Claude Code

Copy link
Copy Markdown
Contributor

os-dev-report

{
  "issue": 8885,
  "status": "blocked",
  "branch": "claude/issue-8885-objectchart-undeclared-keys",
  "pr": "https://github.com/objectstack-ai/objectui/pull/8895",
  "premise_still_valid": true,
  "summary": "Re-derived the collision on origin/main bbe285ee7 (main moved 33 commits since PR objectui#8884's base and 26 since PR objectui#8895's, and touched NEITHER shared file, so the collision is purely between the two branches). Landing order chosen: objectui#8884 first. Its branch is synced to current main and pushed (09f8ffaa3 to 7e7134160), fully green. The resolution for objectui#8895 is BUILT AND VERIFIED but NOT pushed: measured, pushing it would make PR objectui#8895's diff carry 13 of PR objectui#8884's files, i.e. objectui#8895 would swallow objectui#8884's whole change. It is preserved at git ref refs/os-dev-collide/pr8895-resolved (commit 11ddbab62). Two things only the PM/maintainer can clear: (1) objectui#8884 is not landable by this seat - BOTH PRs are draft and BOTH are deliberately parked pending Clause-2 contract review, and this seat never merges; (2) the union of the two PRs exposes a real latent defect whose repair is a design choice, see open_questions.",
  "tests": "All from the resolved merge commit 11ddbab62. ACCEPTANCE (two faces, probe-shape proved first with a known positive `dimensions`=1 and a known negative =0 on each face): all 8 keys declared exactly once on BOTH published faces - filter/aggregate/xAxisKey/series/colors from objectui#8884, drillDown/title/compareTo from objectui#8895; all 10 spec bindings and imports of objectui#8895 present exactly once. GREEN: pnpm --filter @object-ui/types build EXIT 0 (128 files); pnpm --filter @object-ui/types run type-check EXIT 0 (all three tsc projects, so both cards' compile-time pins are real enforcement); pnpm exec vitest run packages/types/ = 166 files / 3234 tests EXIT 0; pnpm exec vitest run packages/plugin-charts/ = 53 files / 496 tests EXIT 0; the 4 ratchet files = 166/166 EXIT 0; scripts/__tests__/check-doc-example-types.test.ts = 51/51 EXIT 0 and the line-KEYED ledger row objectql.ts:1617 still names the real block after BOTH inserts; check:spec-symbols / check:control-bytes / check:doc-fences EXIT 0. check:doc-examples EXIT 2 = PREREQUISITE NOT MET (unbuilt dist) = NOT MEASURED, not a red. RED: pnpm --filter @object-ui/plugin-charts run type-check EXIT 2, exactly one error, ObjectChart.tsx:1326 TS2345 - see open_questions. RATCHET CONTROL, four half-repairs, each with on-disk proof (marker count AND blob hash) and restore proved by state (git diff HEAD empty, blob back to 7258bdaf): H1 drop drillDown from the zod mirror only = vitest RED 5 cases + tsc RED; H2 drop xAxisKey from the zod mirror only = vitest RED 3 cases + tsc RED; H3 swallow objectui#8895's ENTIRE TS member block (the exact failure mode this brief names) = vitest GREEN 166/166, tsc RED 7 errors; H4 swallow objectui#8884's ENTIRE TS member block = vitest GREEN 61/61, types tsc RED 5 errors AND plugin-charts tsc RED 3 errors. ATTRIBUTION ABLATION for the TS2345, both legs with on-disk proof and dist proof: leg0 both PRs = tsc EXIT 1 with the error; leg1 simulate objectui#8884 alone by dropping objectui#8895's title declaration = tsc EXIT 0, error gone, dist member count 0; leg2 simulate objectui#8895 alone by reverting objectui#8884's props anchor to props-any = tsc EXIT 0, error gone; restore git diff HEAD empty and dist member back to 1.",
  "mcp_calls": "4",
  "open_questions": [
    {
      "question": "The union of the two PRs turns ObjectChart.tsx:1326 into a compile error, and it is a REAL latent bug rather than a typing nuisance. That line is `resolveDrillTitle(drillDown, drillEvent, schema.title || 'Details')`, and resolveDrillTitle's third parameter is typed string. objectui#8895 declares title as I18nLabel - a plain string OR an inline locale map - which objectui#8895 measured and pinned as authorable. So an author who writes the locale-map arm gets an OBJECT as the drill drawer's heading fallback. Neither PR can see this alone (proved by ablation): with props-any the read is any, and without objectui#8895's declaration title rides BaseSchema's index signature as any. This is NOT a semantic incompatibility - the two PRs do not disagree about what the schema should say; objectui#8884 declares nothing about title at all and merely ledgers it. What is missing is the READ SITE's repair, which belongs to neither card's ruling and lands in ObjectChart.tsx, a file objectui#8895 explicitly refused to touch because objectui#8884 holds it. Which resolver is the authority for a chart's title?",
      "options": [
        "A - pickLocalized from @object-ui/i18n, the repo's PUBLISHED authority, already exported and pinned as the twin of @objectstack/spec's resolveI18nLabel, whose own docblock names avoiding the object-stringification as its purpose. Cost: it needs a current-locale argument, and ObjectChart.tsx has no language in scope today (it holds useSafeTranslate only), so this pulls in a locale source - useDisplayLocale or useObjectTranslation - and makes the drill heading locale-aware where the chart heading beside it is not.",
        "B - the private label() helper already inside plugin-charts' normalizeChartSchema.ts, which is what the CHART heading path already uses. It is NOT locale-aware (it takes the first string value in the map). Cost: it is module-private, so this either exports a new published name from plugin-charts or copies it, and it entrenches a second dialect that disagrees with pickLocalized.",
        "C - narrow ObjectChartSchema.title to plain string on this node. Cost: contradicts objectui#8895's measured ruling and @objectstack/spec's own ChartConfigSchema.title, and would delete the locale-map arm objectui#8895 pinned as accepted. Listed for completeness; I do not recommend it.",
        "D - land the merge with the error and file the repair as a successor card. Cost: main goes red at the moment the second PR lands, so this is only viable if the repair lands in the same queue batch."
      ],
      "recommendation": "A, with the locale taken from the same source the rest of this file's label net already uses, because it is the only option that does not mint a second dialect for a union @objectstack/spec already owns. But the divergence between the two existing resolvers is itself a contract fact this seat should not settle: the chart heading path currently uses the non-locale-aware one, so choosing A makes the drill heading and the chart heading disagree until someone converges them. That is the escalation."
    },
    {
      "question": "How should PR objectui#8895 receive the resolution, given it cannot be pushed before objectui#8884 lands?",
      "options": [
        "A - land objectui#8884 first (it is synced, pushed and green), then this seat or another merges origin/main into objectui#8895 and replays the identical resolution, which is deterministic and preserved at refs/os-dev-collide/pr8895-resolved.",
        "B - push the resolution to objectui#8895 now. MEASURED CONSEQUENCE, not a guess: its PR diff becomes 21 files, 13 of them objectui#8884's, including ObjectChart.tsx and objectui#8884's changeset - and if objectui#8895 landed first it would carry objectui#8884's entire change into main under the wrong card. I did not do this."
      ],
      "recommendation": "A. Both PRs are draft and parked pending Clause-2 contract review, so nothing lands tonight regardless; the ordering dependency is structural, not a preference."
    }
  ],
  "out_of_scope_findings": [
    "noted, not filed: the TS face of ObjectChartSchema has NO runtime ratchet. Both census pins compute their declared set from Object.keys of the ZOD mirror, so a resolution that swallows either PR's whole TypeScript member block runs vitest fully GREEN (H3 166/166, H4 61/61) and is caught ONLY by tsc -p tsconfig.test.json. Successor: whoever accepts these merges must run pnpm --filter @object-ui/types run type-check; pnpm test alone is not an acceptance instrument here.",
    "noted, not filed: git hoists the shared opening lines of BOTH conflict hunks OUT of the conflict region - the docblock's first 91 bytes are byte-identical on the two sides, and so is the interface body's leading two-space comment opener - so taking either side alone yields syntactically perfect, natural-reading output in both places. This is the mechanism behind the hazard the brief named, measured with cmp.",
    "noted, not filed: the zod mirror auto-merged with no conflict because objectui#8884 inserts before the colors block and objectui#8895 after it. Verified rather than trusted - all 8 keys present exactly once. A reviewer who only inspects the conflicted file would not look at it. Successor: none; recorded so the next merger does not skip it.",
    "noted, not filed: objectui#8895's docblock section headed 'Four keys are still undeclared here, deliberately' has its PREMISE falsified by this merge. Rewritten in the resolution as 'Two cards ruled on this shape, and neither took the other's ruling', keeping its substance. The two cards' census pins were both written order-agnostically (each ledgers the other's keys by name and asserts only that they are STILL READ), so no test needed changing - only that one prose claim.",
    "noted, not filed: the two ceiling paragraphs are near-identical prose with different examples. Folded into ONE section rather than duplicating a heading; every distinct claim from both sides was asserted present afterwards - both refusal examples, both misspelling examples, both counter-probe filenames."
  ]
}

Generated by Claude Code

Copy link
Copy Markdown
Contributor

Correction to my report above (comment 5613422935) — two premises in it are stale. The measurements are unaffected; the landing story changes.

I read the two comments above mine only after posting. Correcting my own record rather than leaving it to be discovered:

1. "Both PRs are parked pending Clause-2 contract review" is no longer true. The tier notice (comment 5612090076 here, and its twin 5612089561 on objectui#8884) lifted the contract-review-tier requirement on both, 2026-09-10T03:14Z. My report used that parking as a reason nothing lands tonight. Withdraw that reason — it is not the operative one.

2. The operative reason is stronger, and it confirms rather than weakens the landing order I chose. objectui#8884 carries a director-seat contract-review verdict of REWORK, anchored at head 09f8ffaa33 (comment 5610718292 on that PR), which states it is ⛔ not queue-eligible until a patch round lands and the new head is re-reviewed. So objectui#8884 cannot land yet — and since the resolution here can only be pushed after objectui#8884 is on main (measured in my report: pushing it now would put 13 of objectui#8884's files into this PR's diff), this PR's resolution waits on that rework round, not on a review tier.

3. Disclosure. I pushed a sync merge to objectui#8884's branch (09f8ffaa3 to 7e7134160) before reading that handoff, so the head a delta re-review anchors on has moved. The PR's file diff is provably unchanged — still its own 15 files — and the new head is green (218 files / 3712 tests, all type-checks EXIT 0). Detail on that PR: #8884 (comment)

Everything else in the report stands unchanged — the collision re-derivation, the landing order and its reasoning, the verified resolution at refs/os-dev-collide/pr8895-resolved, the four-leg ratchet control, and the union-only ObjectChart.tsx:1326 defect with its attribution ablation. ⭐ One consequence worth naming: because objectui#8884 now owes a new head anyway, its rework round is the natural home for that read-site repair, which lives in its file. ⛔ I did not choose between the resolver options.


Generated by Claude Code

@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

排序裁定:#8884 先落地,本卡的解决方案暂存不推 —— 并更正我自己派发单里的两条错误指令

派发席(domain:ui @ objectui)。执行席把三个问题上报而不是自行选择,三条我都作答,⭐ 其中一条是我的单子写错了

⭐ 我的派发单有两条指令无法照做,执行席拒绝执行是对的

我写了「Land the first」和「Push both」。两条都错:

⇒ 它推了 #8884 的同步合并(diff 中性,本席已复核:#8884 仍是它自己的 15 个文件,CI 零红),并扣住了本卡的推送。这个拆分是对的,维持。

裁定

① 顺序:#8884 先。 它锚定 props 类型,本卡只是往那个 schema 上加键;且本卡的产物本来就是顺序无关写的,而 #8884 的散文假定本卡尚未落地。

② 本卡的解决方案不推,暂存等待。 已保存在容器内 refs/os-dev-collide/pr8895-resolved(commit 11ddbab62),验证过:两卡共 8 个键在两个已发布面上各自恰好声明一次,本卡的 10 处 spec 绑定与导入也各恰好一次。#8884 落地后重放即可,是确定性动作。

③ 联合体暴露出的那个真实缺陷,归入 #8884 的返工轮。 两卡合并后 ObjectChart.tsx 编译失败:抽屉标题的读点把 schema 的 title 传进一个声明为 string 的形参,而本卡把 title 声明为可为纯字符串、也可为内联 locale 映射的类型。⇒ 作者若写 locale 映射那一支,抽屉标题会拿到一个对象

⭐ 消融证明两卡各自都看不见它——只在联合体里出现。而读点在 ObjectChart.tsx,那是 #8884 持有的文件,且 #8884 本来就欠一个新头(它带着 REWORK 裁定)。⇒ 修复归它,路线取 pickLocalized(本仓已发布的权威解析器,且已作为 spec 自身解析器的孪生被钉住),⛔ 不用 plugin-charts 里那个模块私有、不感知 locale 的助手——那会再铸一种方言

⚠️ 三方独立确认了同一幅图

执行席在 bbe285ee7 上重推的冲突读数,与 #8884 的契约复核席独立测出的完全一致:一个冲突文件(objectql.ts)、两个块、objectql.zod.ts 零标记自动合并、两卡无同名键

⚠️ 一条给后继的硬提醒:验收工具不是显而易见的那个

两卡的普查 pin 都从 zod 镜像的 Object.keys 计算已声明键集。⇒ 一个吞掉任一方整个 TypeScript 成员块的解决方案,会让 vitest 全绿(实测 166/166 与 61/61),只有 tsc -p tsconfig.test.json 抓得住

⭐ 而 git 会把两个 hunk 逐字节相同的开头都提到冲突区之外(cmp 确认,docblock 首 91 字节相同),所以只取一侧会产出语法完好、读起来自然的文件。⇒ pnpm test 单独不构成本文件的验收工具,⛔ 也不能靠冲突标记提示缺失。


Generated by Claude Code

os-zhuang pushed a commit that referenced this pull request Sep 10, 2026
…er's declaration

Second union-only defect with objectui#8895, measured on the merge of the two
heads and NOT previously reported: `renderChart(compareTo: unknown, …)` stops
compiling once #8895 declares `ObjectChartSchema.compareTo` as
`DashboardWidget['compareTo']`, because on this branch the key still rides
`BaseSchema`'s index signature.

It was masked rather than absent: `type-check` is
`tsc --noEmit && tsc -p tsconfig.test.json`, so the drill-title error in
`ObjectChart.tsx` short-circuited the test project and hid every error it would
have reported. Running the test project alone on the pre-rework union shows both.

Typed at `DashboardWidget['compareTo']` — the symbol #8895 binds to and the
declaration the value actually comes from (`DashboardRenderer` forwards
`widget.compareTo` verbatim). All four call sites already pass that shape.

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

`main` moved and objectui#7946 (PR #8884) landed, editing the same
`ObjectChartSchema` on both published faces. The previous round's stashed
resolution was built on #8884's PRE-REWORK tree and is not replayed.

5 files, 7 hunks, re-derived against origin/main aeaa0f6:

- `objectql.ts` docblock: both sides rewrote the same title line into
  different full docblocks. BOTH narratives kept; the two near-identical
  "ceiling" paragraphs folded into ONE section carrying both cards'
  examples and both counter-probe filenames; this branch's section
  "Four keys are still undeclared here, deliberately" had its premise
  falsified by the merge and is re-derived.
- `objectql.ts` interface body: double insertion at one anchor, both kept.
  All 8 keys now declared exactly once on both faces.
- `objectql.zod.ts` / `imported-defaults-8317.test.ts`: additive on both
  sides, both kept.
- `zod-mirror-parity.test.ts`: BOTH sides add the SAME
  `SPEC_DERIVED_PAIRS` entry with different grounds. One entry, both
  grounds recorded.
- `check-doc-example-types.mjs`: the `UNGATED_EXAMPLES` key embeds a line
  number and each side repaired it to a different one. Re-derived BY
  ANCHOR against the merged tree (the `@example` tag on
  `ObjectFormSchema.mobile`, byte-identical to the branch point): :1618.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MPaVWWMuWeT5LgB1qoXjVB
…n repair

Re-measured with `scripts/cross-file-line-citation-census.mjs` on
`origin/main` and on this tree. The previous round repaired FOUR citations
in the 2026-07 audit as class (A). Only TWO of them are.

Class (A), kept — both on the `defaultViewType` row, both RESOLVE on
`origin/main` and are broken by this branch's three added import lines in
`objectql.zod.ts`. Repaired by content, not arithmetic: `:365` and `:643`
on main read ` *     STRICT \`ObjectListViewSchema\`,` and
`    // objectui-only object binding (...)`, and both are byte-identical
at `:368` / `:646` here.

Class (B), reverted to `origin/main` — `:350-352` and `:713`. Measured
ALREADY FALSE on `origin/main` before this branch existed (`:350` reads
`[drifted]` there). Shifting an already-false address by a hunk delta
moves a wrong pointer to a differently wrong place, which the census
tool's own header forbids and objectui#8875 reserves.

Census parity after this commit: 545 false / 290 resolving on BOTH
`origin/main` and this tree — this branch newly falsifies nothing.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3491.0 KB 3512.7 KB
Main entry chunk (gzip) 144.2 KB 350 KB
Entry file index-DWiHYNKq.js
Status PASS

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


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 500.20KB 114.67KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 28.04KB 9.46KB
data-objectstack (index.js) 205.46KB 56.78KB
fields (index.js) 246.97KB 62.30KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.63KB 19.99KB
plugin-chatbot (index.js) 195.32KB 46.51KB
plugin-dashboard (index.js) 132.41KB 34.84KB
plugin-designer (index.js) 215.68KB 44.27KB
plugin-detail (index.js) 253.19KB 65.62KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.79KB 34.19KB
plugin-gantt (index.js) 166.96KB 40.93KB
plugin-grid (index.js) 210.86KB 57.28KB
plugin-kanban (index.js) 57.58KB 16.47KB
plugin-list (index.js) 112.54KB 27.65KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.42KB 20.80KB
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) 83.34KB 27.61KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 2.71KB 1.35KB
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) 14.82KB 4.99KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@os-steve
os-steve marked this pull request as ready for review September 10, 2026 09:11
@os-steve
os-steve added this pull request to the merge queue Sep 10, 2026
Merged via the queue into main with commit 63601ab Sep 10, 2026
35 checks passed
@os-steve
os-steve deleted the claude/issue-8885-objectchart-undeclared-keys branch September 10, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: types tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants