Skip to content

fix(deps): triage the 14 rc.6 spec-symbol collisions and refresh the console parity exemptions (#4167) - #4189

Closed
yinlianghui wants to merge 3 commits into
mainfrom
claude/issue-4167-rc6-adaptation-remainder
Closed

fix(deps): triage the 14 rc.6 spec-symbol collisions and refresh the console parity exemptions (#4167)#4189
yinlianghui wants to merge 3 commits into
mainfrom
claude/issue-4167-rc6-adaptation-remainder

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Fixes #4167.

Stacked on #4169 (claude/issue-7100-global-nav-studio-retire), not on main. This card's premise — the @objectstack/spec family resolved at 17.0.0-rc.6 — exists only on that branch, so CI here runs against that base and inherits its state. It retargets automatically if #4169's base evolves.

Both of the card's items are complete and their gates are green:

# Item Bar State
1 13 check:spec-symbols name collisions, per-symbol triage check:spec-symbols green ✅ (14, not 13 — see below)
2 12 stale parity exemptions + 3 record-picker inputs registry-inputs-spec-parity green ✅ 51/51

There is also a third finding that changes how this PR's CI must be read, in §3. It is not mine to fix and it is measured, not assumed.


1. The collisions — 14, and each triaged on its own

The card named 13. The guard reports 14: @object-ui/types:GlobalFilterSchema appeared during the rc.6 bump and is an artifact of it, so it belongs here rather than to a future card. Details in its row.

Verdicts follow the objectstack#4115 method — bind, derive, rename, or ALLOW with a written reason — and the answer genuinely differs per symbol. Nothing was blanket-renamed.

# package symbol what the spec's same-named export is verdict
1 app-shell MetadataState metadata item LIFECYCLE state — 'draft' | 'active' | 'deprecated' | 'archived' renameMetadataCacheState
2 app-shell resolveI18nLabel resolver for the INLINE per-locale map, against a BCP-47 locale renameresolveKeyedI18nLabel
3 core DATE_RANGE_PRESETS the 13-preset dashboard vocabulary, extracted by objectstack#4614 re-export (+ satisfies completeness pin)
4 fields AddressValue z.input< typeof AddressValueSchema > — seven parts derive (import + re-export)
5 layout BreakpointColumnMap identical $strict six-key map re-export
6 layout BreakpointOrderMap identical $strict six-key map re-export
7 react MetadataState as row 1 renameMetadataCacheState
8 react NavigationMode z.input< typeof NavigationModeSchema > — the same 7-member union derive (+ both-directions pin)
9 react resolveI18nLabel as row 2 renameresolveKeyedI18nLabel
10 types DateRangePreset 13 HISTORICAL windows; this one adds 8 FUTURE ones renameFilterBuilderDateRangePreset
11 types KanbanConfig identical $strict 3-key config re-export
12 types CalendarConfig identical $strict 4-key config re-export
13 types GanttConfig 17 keys; the copy declared 6 derive + one declared local key
14 types GlobalFilterSchema the authored global-filter schema ALLOW, with the reason

The three renames, and why each is a rename rather than an ALLOW

The AuthProvider / AuthProviderConfig split from batch 5 is the test applied: a JSX element cannot be mistaken for a zod enum, so it was ALLOWed; AuthProviderConfig names the spec's OAuth registration shape in the same domain and the same words, so it was renamed. All three below fail that test the same way.

  • MetadataState — an object of five arrays vs a string union, mutually unassignable, so nothing would have caught the misreading at the point it was made. Cache because that is what it is: MetadataProvider is a TTL cache and these are its materialized contents. Six references repo-wide.
  • resolveI18nLabel — the one where the collision had already started costing something, and the only one that is dangerous rather than untidy. rc.6 widened I18nLabel from string to string | Record< string, string >, so the same authored value now reaches either resolver, and each answers wrongly and silently for the other's input: the keyed one returns undefined for { en: 'Owner' } (no key, no defaultValue); the spec's reads key / defaultValue / params as locale tags and picks one as display text. retire(studio): drop the global_nav designer surfaces with the rc.6 spec bump (objectstack#7100) #4169 met this and aliased the spec's import as resolveInlineI18nLabel in five files, with hand-written comments at two of them — a review convention, which is exactly what objectstack#4115 exists to replace with a rule. Keyed is now the counterpart of that Inline. A fourth copy in apps/console/src/utils.ts is renamed with them; it is outside the guard's scan surface (packages/*/src only) but plants the identical premise.
  • DateRangePreset — two vocabularies that are not even nested by accident. The spec's 13 are historical windows and its superRefine on GlobalFilterSchema rejects everything else by name; this one adds 8 future windows (tomorrow, next_week, …) for the FilterBuilderConfig surface, where a forward-looking range is the point. So a reader who took the spec's 13 off this name would have been told 8 windows exist that the dashboard schema rejects, and vice versa. FilterBuilderCondition (batch 5) named its sibling the same way. Zero internal consumers outside DateRangeFilter in the same file, so no call-site churn.

No tripwire tests were added for the new names, deliberately. check:spec-symbols already is that tripwire: the day the spec publishes MetadataCacheState, resolveKeyedI18nLabel or FilterBuilderDateRangePreset, the guard reds naming it. The ObjectUiLocal…-plus-tripwire form in #4115 exists for symbols that stay in the spec's own vocabulary; these three left it.

Four copies were losing information, not just duplicating it

  • GanttConfig declared six keys and called itself canonical; rc.6 declares seventeen. The eleven it never mentioned — parentField, typeField, baselineStartField, baselineEndField, groupByField, resourceView, assigneeField, effortField, capacity, quickFilters, autoZoomToFilter — are all read today by plugin-gantt/src/ObjectGantt.tsx, through a local GanttConfigEx intersection that existed only because this type did not carry them. timeSegments (shift segmentation) is the one genuinely local key and stays declared as objectui's; GanttConfigSchema is $loose upstream, so it is legal metadata rather than a second dialect — the spec's decision for this vocabulary, not a widening taken here.
  • GanttConfig.tooltipFields carried the comment "not part of the upstream GanttConfigSchema". It is, as of rc.6.
  • AddressValue declared five of seven parts (countryCode, formatted missing) under a comment already claiming to be "the part names of AddressSchema". The widget still renders five inputs — formatted is derived and countryCode is not a part a human types — but the type no longer asserts the platform cannot store them, and the { ...address } write-through now says so.
  • DATE_RANGE_PRESETS was Object.keys(PRESET_RANGES). The spec's own doc comment names this module as one of the three copies objectstack#4614 extracted the vocabulary to collapse. It is now the spec's array by reference (toBe, not toEqual — a faithful copy passes every value comparison, which is why test(plugin-charts): serve ObjectChart's option-color probe from a double, not the network #4115 makes reference identity the test), and the local date-macro bounds table is pinned complete against it with satisfies.

That satisfies is load-bearing, not decoration. With the list coming from the spec and the bounds staying local, the two can drift in exactly the direction the spec's comment names as the failure mode — a preset the schema knows and the bounds table lacks "validates clean and then resolves to nothing". The annotation form const PRESET_RANGES: Record< DateRangePreset, … > would not catch it: a string index signature satisfies every literal key, so the check passes vacuously.

GlobalFilterSchema — the 14th, and why it is an ALLOW

It collided because of #4169's own forced rewrite. rc.6 put a refinement on the spec's schema, which makes .extend() throw at module load and types every override as never under .safeExtend(); the only remaining spelling is a .shape spread. That moved a derivation the guard could see (a call target) into an object literal it deliberately does not descend into — the guard's header says why: a spread inside z.object({…}) is indistinguishable, to an AST pass, from a hand-typed shape.

So the dialect did not change; its spelling did. The precedent is exact and one entry above it in the same list: SelectOptionSchema composes the identical way (...SpecSelectOptionSchema.shape) and is ALLOWed for the identical reason. Nothing about #4165 is encoded here — the refinement is still not carried, the standstill is still pinned, and the entry says which issue owns the decision.


2. The parity exemptions

registry-inputs-spec-parity: 49 tests, 2 failing → 51 tests, 0 failing.

2a. All twelve off-spec exemptions deleted — the list is now empty

Not eleven or thirteen: the carries no stale exemption test named all twelve at once, and each was verified against the resolved ComponentPropsMap[type].shape at this pin rather than from the issues' wording.

page:tabs is the interesting one: the spec declares both tabStyle and type, so the carrier collision the deleted entry wrote up was resolved upstream by declaring the alias rather than renaming. That is why page:tabs.type stays in UNPUBLISHED_EXEMPTIONS (spec-declared, unpublishable in a flat carrier) while tabStyle needs no cover at all.

The map is kept declared-and-empty rather than removed, with a tombstone test — otherwise "empty because everything resolved" and "deleted by accident along with the divergences it covered" look identical and every forward assertion passes either way. That is the misdiagnosis #4027 records for the SPEC_SHAPE_EMPTY_ON_THE_PIN carve-out, which also left an assertion behind rather than just a comment.

Note that the UNPUBLISHED_EXEMPTIONS entries did not go stale, exactly as their own reasons predicted: ADR-0087 D2 retirement replaces an entry with z.never().optional() rather than deleting it, so displayField / searchFields / multiple / page:card.body are still "declared" to this gate. They resolve via objectui#3809, not via the pin.

2b. Three record-picker inputs declared

sort, limit and emptyText were already read by the renderer and declared by the contract, but absent from inputs — so renderers/layout/page.tsx, which builds the JSX-page compiler's prop whitelist from getKnownTypes() plus these inputs, drew an unknown-prop warning on keys the renderer then honoured. objectui#3407's shape, and the same repair #3808 and #3830 made before it. The red demanding them was predicted in writing by the exemption covering the retired trio, which called it "correct and wanted".

Each description documents renderer behaviour rather than restating the schema, per the #3830 / #4041 shape — because that is the half an author cannot read off the contract:

  • sort'array' is the spec's shape, verified by safeParse: [{ field, order }] parses and the terse "name asc" does not. Overridden outright by a node-level dataSource (dataSource.sort ?? sort), not merged.
  • limit — default 50 comes from the renderer (record-picker.tsx:107), not the schema; a record outside the limit cannot be picked at all, with nothing in the control saying more exist.
  • emptyText — published as string against a contract of string | Record< string, string >. rc.6 widened it to I18nLabel, and this renderer passes the value straight into a text node with no locale resolution, so only the plain-string form renders. The description says so rather than advertising a shape the renderer drops — the narrowed-type treatment objectui#3832 describes, with the render-site gap belonging to §3.

Both sets are pinned by name as DECLARED, not merely "not failing", because the derived assertions would go green just as readily if the keys had been exempted instead — which is the move #3808 exists to rule out.


3. ⚠️ How to read this PR's CI — 13 type errors that are not mine

First, what actually runs here: almost nothing, and that is structural. Every gate workflow in .github/workflows/ filters pull_request to branches: [main, develop]ci.yml, lint.yml, changeset-guard.yml, changeset-presence.yml, control-bytes.yml, skills-paths.yml, docs-links.yml, performance-budget.yml, live-e2e.yml, all of them. This PR's base is a feature branch, so none of them trigger. Its checks converge at two, both success (Auto Label PRs, Vercel Preview Comments), with nothing queued and nothing red. A green tick here is therefore evidence of very little, which is why every gate below was run locally instead and its real output quoted.

Second, what will run when the chain reaches main. check:spec-symbols is green, but the TypeScript Type Check job it lives in will be red on the merged chain, and this card cannot make it green. The issue's premise that this gate is "currently the main red" of that job is accurate about check:spec-symbols and incomplete about the job.

turbo run type-check --continue reports 13 errors in 5 packages, and every one is the same fact: rc.6 widened I18nLabel from string to string | Record< string, string >, and these sites take it into a ReactNode, an input value, or objectui's keyed resolver.

layout           src/AppSchemaRenderer.tsx:169,173      NavigationArea.label
plugin-list      src/components/TabBar.tsx:140,200,216  ViewTab.label
plugin-dashboard src/DashboardGridLayout.tsx:398,399    DashboardWidget.title
plugin-designer  src/DashboardEditor.tsx:143,231,341    widget title editing
app-shell        src/utils/resolveActionParams.test.ts:245,345,358   ActionParam.label

#4169 repaired eight such render sites; these are the ones its pass did not reach, and turbo run build cannot see them — these packages build through vite/rolldown, so only type-check compiles them. That is why a bump reporting a green 44/44 build and 14,609 passing tests still has them.

This is objectui#4163 part 1 verbatim ("the I18nLabel audit"), which my scope guard fences off, and it is not mechanical: @object-ui/layout deliberately has no i18n dependency ("enables convention-based i18n auto-resolution without coupling the layout package to i18n"), so choosing where its locale comes from is a design call in that package, not a find-and-replace. Left alone, with the inventory posted to #4163 so it is a named worklist rather than an open-ended audit.

Measured, not assumed

A second worktree at the untouched base (db9dad961) was type-checked with the identical command:

base db9dad961 this branch
tasks 71 successful / 78 73 successful / 78
failing packages 7 5
type errors 16 13

The 13 are byte-identical to 13 of the base's 16. This branch introduces none and removes three.

The three it removes

All pre-existing, all rc.6 adaptation in this card's own family (not #4163's), and all found only by running type-check — which #4169 did not. Two are one-line re-points; the third is a member-list update. They are included because without the first, turbo stops at @object-ui/types and never reaches a single package this PR touches, so verifying my own work required them.

3b. And one inherited test failure, in a package this PR does not touch

pnpm exec vitest run is 14,618 / 14,620 with one failure:
plugin-detail/src/__tests__/recordDetailsInputs.spec-parity.test.ts"the spec really takes OBJECT sections — the id-list spelling is gone, not unioned in".

Proved to be a pure spec fact, with a probe that runs no objectui code at all:

RecordDetailsProps.safeParse({ layout: 'custom', sections: [{ name: 'contact_info',}] })
// success: false — issue at path ["layout"], code invalid_type, expected "never"
// "`record:details` property `layout` was removed in @objectstack/spec 17.0.0 (#6946, ADR-0087 D2)"

rc.6 turned record:details.layout into a D2 tombstone, and the fixture carries layout: 'custom'. The test's own premise is untouched — the sections object form still parses, member keys name / label / columns / fields.

The interesting half is that the sibling assertion in the same test has gone VACUOUS. It reads expect(idList.success).toBe(false) to prove the retired id-list spelling of sections is rejected — and that is now green because of layout, not because of sections. A rejection assertion passing for the wrong reason is worse than a failing one, so this needs the fixture repaired and the rejection re-pointed at the key it names.

Not fixed here: objectui#3818 already owns record:details.layout (it is the card whose upstream resolution objectstack#6946's tombstone is), the renderer's own layout read point needs the same audit, and none of it is in this card. Posted to #3818 rather than filed as a twin.


Reverse verification

Three, each predicted red before running and each red for the named reason. The second and third are the ones that matter: in both, the repo's own derived assertion and the pin this PR adds fire together, which is what shows the new pins are not vacuous.

1. Un-fix one collisiongit checkout origin/claude/issue-7100-global-nav-studio-retire -- packages/layout/src/ResponsiveGrid.tsx:

❌  a spec-named symbol is hand-written, not derived:
    • @object-ui/layout declares 2 spec-named symbols the spec already owns:
        interface `BreakpointColumnMap`  packages/layout/src/ResponsiveGrid.tsx:16
        interface `BreakpointOrderMap`   packages/layout/src/ResponsiveGrid.tsx:29

2. Restore one deleted exemption (page:header.recordChrome):

× carries no stale exemption — a declared key must lose its entry
× the twelve rc.6-obsoleted off-spec exemptions are gone, and their keys are contract now
  AssertionError: expected [ 'page:header.recordChrome' ] to deeply equal []
  AssertionError: expected [ 'page:header.recordChrome' ] to not include 'page:header.recordChrome'
Tests  2 failed | 49 passed (51)

3. Withdraw one newly-declared input (emptyText):

× element:record_picker publishes every top-level key its spec props schema declares
× the three keys the rc.6 bump added to element:record_picker are discoverable
  AssertionError: expected [ 'emptyText' ] to deeply equal []
  AssertionError: element:record_picker does not publish emptyText: expected [ 'object', 'filter', …(6) ] to include 'emptyText'
Tests  2 failed | 49 passed (51)

Case 3 is the one the pin exists for: the derived assertion alone would have gone green again if emptyText had been added to UNPUBLISHED_EXEMPTIONS instead of declared. The named pin refuses that, which is the move objectui#3808 exists to rule out.


Verification

Run locally, because §3 explains that this PR's own CI runs no gate workflow — its two checks are Auto Label PRs and Vercel Preview Comments, both green, and neither judges any of this.

  • node scripts/check-spec-symbol-derivation.mjs — ✅ 1224 files scanned against 4834 spec export names; 14 declared dialects, 3 untriaged collisions in 1 packages (the 3 are the pre-existing @object-ui/types DEBT ledger, untouched)
  • pnpm exec turbo run build --concurrency=244/44 successful
  • pnpm exec turbo run type-check --concurrency=2 --continue — 73/78, the 5 failures being §3's inherited I18nLabel set
  • pnpm exec vitest run (whole repo) — 14,618 passed / 14,620, 1 skipped, 1 failed: plugin-detail/…/recordDetailsInputs.spec-parity.test.ts, inherited and unrelated — see §3b
  • apps/console/…/registry-inputs-spec-parity.test.ts51 passed (was 49 with 2 failing)
  • check-changeset-fixed ✅ · check-changeset-no-major ✅ · check-changeset-presence ✅ (3 changesets) · check-control-bytes
  • turbo run lint over the 10 touched packages — 10/10 successful, 0 errors (warnings pre-existing)

Changesets: minor for the seven packages with changed public exports (major is banned by check-changeset-no-major — objectui's own breaking changes ship as minor with the break spelled out, since its major is pinned to @objectstack's), plus patch for plugin-designer, which only follows the rename at its call sites.


Generated by Claude Code

claude added 3 commits August 10, 2026 15:17
…pec bump (objectstack#7100)

`global_nav` was an `ACTION_LOCATIONS` member no running-app surface ever
rendered — the console's ⌘K palette reads no action metadata at all — and the
Studio designer previewed a mock command-palette frame for it anyway.
@objectstack/spec 17.0.0-rc.6 retired the member (objectstack#6888, maintainer
ruling 2026-08-09 direction 2); this removes the designer surfaces that outlived
it, plus the bump that makes them stop compiling.

- ActionPreview.tsx: the mock ⌘K placement frame is gone. The metadata strip
  still echoes the declared token, deliberately — reporting what a draft says is
  honest; the frame CLAIMED the platform renders it.
- ActionDefaultInspector.tsx: the `LOCATION_LABELS` entry is gone. The map is
  `Record<ActionLocation, string>`, so the retirement arrived as a compile error
  (objectui#3017's mechanism firing as designed).
- block-config.ts + both locale tables: the palette option and its now-orphaned
  i18n key.
- components' action:bar doc comment aligned (its enum is `[...ACTION_LOCATIONS]`
  and followed on its own).
- ActionEngine.getActionsForLocation is UNCHANGED: narrowing it would be a second
  rejection point beside the schema's. The type and `ActionLocationSchema` are the
  enforcement, both pinned.

The bump (all 37 `@objectstack/*` declarations, rc.5 -> rc.6) rides along because
the two cannot compile apart, and its fallout is repaired here: the `…Input` alias
retirement (types/theme, types/spec-report, core/ActionRunner), the five dead i18n
re-exports, the `I18nLabel` widening at 8 render sites, `.extend` -> `.safeExtend`
on a now-refined `GlobalFilterSchema`, and two parity lists re-pointed.

NOT green: the bump's remaining surface is out of this card's scope and filed —
objectui#4165 (contract conflict, blocks), #4167 (adaptation remainder),
#4163 (I18nLabel consumer story), #4164 (name reclaim available).

Part of objectstack-ai/objectstack#7100

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
… one conflict

Second pass over the @objectstack/spec 17.0.0-rc.6 bump. The first commit fixed
every COMPILE error; a full `vitest run` (14615 tests) then surfaced the runtime
half. All mechanical, each pinned; the one non-mechanical case is left as a
tripwire rather than decided.

- types/zod/complex.zod.ts: `GlobalFilterSchema` composes by spreading the spec's
  `.shape`. rc.6 closed BOTH extension doors on a now-refined schema — `.extend()`
  throws at module load, `.safeExtend()` types the three overridden keys as
  `never` (TS2322, which only `apps/site`'s build caught). The spread preserves
  rc.5 behaviour exactly and decides nothing: the refinement-vs-stored-`{preset}`
  conflict is objectui#4165, pinned by a new tripwire that reds from either side.
  The pin isolates the refinement by widening `defaultValue` first — the bare spec
  schema rejects `{preset}` on the OLD field type and the refinement never runs,
  so the obvious shorter assertion would have pinned the wrong thing.
- core/actionKeys.ts: `description` joins SPEC_ACTION_KEYS (rc.6 added it to
  `ActionSchema`). Inventory only — `ActionDef` is untouched.
- metadata-admin flow tests x2: `FlowNodeSchema` became pipe-wrapped, so `.shape`
  read `undefined`. Access-path repair (walk the wrapper); the blocks themselves
  are unchanged upstream, and a non-vacuity guard now says so.
- clientValidation.optOuts: INVERTED — rc.6 makes `SharingRuleSchema` declare the
  seven ADR-0010 envelope keys, so the create door now ACCEPTS a stamped
  `_packageId`. Upstream convergence, pinned as accept, with a bogus-key case
  proving the door is still a door.
- clientValidation.viewDiagnostics: fixture supplies a `label`; rc.6's widened
  `I18nLabel` made every label a LEAF union, which #3606's root-union expansion
  does not reach. The resulting bare `Invalid input` is recorded as its own pin
  (objectui#4163), not papered over.
- components/record-picker parity: fixture drops `displayField` — an ADR-0087 D2
  tombstone refused by name, which was failing all three `filter` assertions.
- console registry parity: `SPEC_SHAPE_EMPTY_ON_THE_PIN` deleted exactly as its
  own self-clearing test instructed (rc.6 lands `PageContainerProps`), with a
  tombstone assertion so the deletion cannot be silently undone.
- i18n residue ratchet: matches `const { t, … } = useObjectTranslation(` by
  pattern. Both sidebars legitimately also take `language` now, to resolve the
  spec's inline per-locale labels.

Still red, filed, NOT fixed here: 2 console-parity exemption-list entries and
`check:spec-symbols`' 13 name collisions (objectui#4167) — each is per-symbol
triage, not a mechanical edit — and objectui#4165, which blocks ready.

Part of objectstack-ai/objectstack#7100

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
…console parity exemptions (#4167)

objectui#4167, objectstack#4115. `check:spec-symbols` reported 13 collisions on
the @objectstack/spec 17.0.0-rc.6 bump and a 14th (`GlobalFilterSchema`) appeared
during the bump itself; each is triaged on its own rather than blanket-renamed.

Renamed (3) — the spec's same-named export means something else:
  MetadataState -> MetadataCacheState        (react, app-shell)
  resolveI18nLabel -> resolveKeyedI18nLabel  (react, app-shell, + apps/console)
  DateRangePreset -> FilterBuilderDateRangePreset (types)

Bound or derived (10): DATE_RANGE_PRESETS (+ a `satisfies` completeness pin on
the local bounds table), NavigationMode (+ a both-directions type pin),
AddressValue, BreakpointColumnMap, BreakpointOrderMap, KanbanConfig,
CalendarConfig, GanttConfig. Four copies were losing information: GanttConfig
declared 6 of the spec's 17 keys while plugin-gantt reads all of them,
AddressValue 5 of 7 parts, and DATE_RANGE_PRESETS was the third copy
objectstack#4614 extracted the vocabulary to collapse.

ALLOW (1): GlobalFilterSchema, the same `.shape`-spread dialect as
SelectOptionSchema beside it — it collided only because rc.6's refinement forced
`.extend()` to be respelled, moving a derivation the guard could see into an
object literal it deliberately does not descend into. Nothing about #4165 is
encoded.

Console registry-inputs-spec-parity: all 12 off-spec exemptions deleted (rc.6
landed objectstack#6776 and objectstack#5775, verified per key against the
resolved shape), and `element:record_picker` publishes `sort` / `limit` /
`emptyText` — read by the renderer all along, and the red demanding them was
predicted in writing by the exemption it replaces. 49 tests/2 failing -> 51/0.

Also repairs 3 pre-existing type-check errors of this card's own rc.6 family,
found only by running `type-check` (which the bump PR did not): the retired
`ThemeInput` alias re-pointed BY SIDE, and `DroppedFieldsEvent.reason`'s new
`primary_key` arm. The consumer gap that arm exposes is objectui#3935.

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

vercel Bot commented Aug 10, 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 Aug 10, 2026 7:07pm

Request Review

Copy link
Copy Markdown
Collaborator Author

Train note (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3): auto-merge disarmed on purpose. Retargeting this stacked PR to main did not trigger CI (base-edit fires no synchronize), and the merge queue would have bounced it anyway: this tree lacks #4208's resolveActionParams typetest fixes and the post-train quick-reference-current-release-4143 doc test, both red on the combined tree while main is already red from the #4169 landing.

This PR's content lands via PR #4208 instead — that branch is stacked on this one and already contains every commit here; the train-finisher agent is adding the rc.6 residual fixes on top, retargeting #4208 to main, and landing the tail as one squash that closes #4167 (this PR's issue) and #4163 part 1 together. Once it merges, this PR will show an empty diff and will be closed without merge — the work is not lost, it is riding the tail car. Main-health context: fastest single landing back to green.


Generated by Claude Code

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.

Track the @objectstack family at 17.0.0-rc.6 — the adaptation surface beyond what objectstack#7100 could carry

2 participants