Repository navigation
finding(timeline): dedup ObjectTimeline's useSafeObjectLabel onto the shared useSafeFieldLabel - #5781
Merged
os-zhuang merged 2 commits intoAug 23, 2026
Conversation
.changeset/timeline-shared-safe-field-label-5623.md — empty frontmatter, internal refactor with no exported-symbol or behavior change.
Contributor
✅ Console Performance Budget
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
Size Limits
|
os-zhuang
marked this pull request as ready for review
August 23, 2026 08:35
os-zhuang
deleted the
claude/issue-5623-timeline-shared-safe-field-label
branch
August 23, 2026 08:35
akarma-synetal
pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Sep 28, 2026
…dead issue numbers (objectui#10701) (objectstack-ai#10707) Fixes objectstack-ai#10701 Clause-②: no (wording only; no accept set, type or behaviour moves) Dispatched implementation of the `domain:ui` seat 1 claim (comment `5838463073`) on objectui#10701, session `https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC`. Wording only: no accepted value, type or runtime behaviour changes. ## Premise, re-measured first REST `GET /repos/objectstack-ai/objectui/issues/{n}`, 2026-09-25: | number | objectui | same number in objectstack | |---|---|---| | 5740 | 404 | 200, an unrelated service-analytics PR | | 5784 | 404 | 200, an unrelated stub-driver rename issue | | 5782 | 404 | 200, an unrelated metadata-protocol PR | | 5806 | 404 | 200, an unrelated driver-sql integration-test PR | | controls 5736, 5742, 5778, 5790 | 200 | | None of the four answers 200 in objectui, so the premise holds. The sister-repo numbers resolve, but to unrelated subjects, so a repo-qualified citation would send a reader to the wrong record. This PR cites the landing commits instead. Both are ancestors of `main` (`git merge-base --is-ancestor`, exit 0 for each): - `b55a34647` feat(types): retire 'agenda' from CalendarViewMode and the zod enum - `ed8df3e50` feat(types): retire 'agenda' from defaultView on all three declaration faces ## Citation form, site by site - **The three zod `.describe()` strings** (`CalendarViewSchema.view`, the list-view `calendar` config's `defaultView`, `ObjectCalendarSchema.defaultView`): the pointer is dropped, and they now end `('agenda' was retired)`. That sentence stands alone. These strings ship in `dist` and reach whatever reads the zod `description` at runtime, a reader who has no repository to resolve a bare sha against. No `.describe()` string under `packages/types/src/zod/` carries a commit citation today, so there was no runtime-string precedent to follow. - **Docblocks and the zod line comment**: they cite the landing commit as a backticked 9-character sha. That is the form published docblocks, changesets and docs already use, for example "landed as `89d7b35a7`" in `packages/data-objectstack/src/metadata-client.ts` and "deleted from the repository in `8c5d20455`" in `.changeset/6342-dead-migration-guide-pointers.md`. - **`schema-reference.md`, the `CalendarViewMode` row**: "retired in `b55a34647` and now fails validation". - **The two retirement changesets**: the pointer to themselves is dropped. This repo's `@changesets/cli/changelog` is `@changesets/changelog-git`, which prefixes each CHANGELOG entry with the short hash of the commit that ADDED the file (`git log --diff-filter=A`). That is the landing commit, so the released entry already carries `b55a346` / `ed8df3e`. Where the `defaultView` changeset points at the `CalendarViewMode` retirement, it now cites `b55a34647`. - **The i18n batch changeset** (`4730-retire-dead-locale-key-batch.md`): "labelled a view mode `b55a34647` retired from `CalendarViewMode`". - **Pending changeset frontmatter is byte-identical.** The sha256 of each frontmatter block is equal before and after, and `check-changeset-overwrite` prints `declared at base` equal to `declares now` for all three. The filenames keep their `5740` / `5784` suffixes: a filename is not a citation, and a rename would read as deleting one declaration and adding another. ## Which sites actually publish: the card's two classes, measured against `dist` I built `@object-ui/types` and `@object-ui/plugin-calendar` and grepped `dist`: - **Card's "comment-only" sites that do ship.** The `complex.zod.ts` docblocks on `CalendarViewModeSchema` and `CalendarViewSchema` ship in `dist/zod/complex.zod.d.ts` and `.js`. The `objectql.zod.ts` line comment above the calendar config's `defaultView` ships in `dist/zod/objectql.zod.js`, because tsc emits with `removeComments: false`. This is published text, so this PR repairs it along with the rest. All three are the optional adjacent comments the claim's file surface already lists. - **Card's "published JSDoc" site that does not ship.** Neither the old nor the new pointer in `plugin-calendar/src/index.tsx` appears in `packages/plugin-calendar/dist`. The same docblock's `objectui#8201` is missing too, while a code string from the same file (the `defaultView` input description) is present as the control. The site is repaired anyway because the triage names it, and it is declared comment-only. - **Result.** After this PR, `@object-ui/types` `dist` contains no `objectui#5740` or `objectui#5784`. ## Census `git grep -nE 'objectui#5740|objectui#5784|objectstack-ai#5740|objectstack-ai#5784|objectstack-ai#5782|objectstack-ai#5806'` over `packages/`, `content/` and `.changeset/` at the base finds 26 lines, all in files the card names. Outside those three roots it finds 0 (control: `objectstack-ai#7853` hits 5 files). After this PR there are 0 non-test hits. The 10 lines that remain are docblocks and comments in four test files. Those do not ship and are optional per the triage (see Acceptance notes). ## Changeset `.changeset/10701-agenda-retirement-citations.md` declares `@object-ui/types: patch` for the `.describe()` wording (precedent: `10084-grid-ceiling-describe.md`). The `plugin-calendar` edit is comment-only, as measured above. This repo's precedent for comment-only `src/` edits is an empty declaration (for example `10159-action-preview-reference-citation.md`). Instead of adding a second file, the new changeset's body says `plugin-calendar` declares no release. `check-changeset-presence` requires one added declaration, and this one satisfies it. ## Pins `grep -rln "agenda' was retired" packages/` returns only the two zod source files. No test snapshots or reads the old `describe` text, so no pin changed. No ablation was run, because nothing executable changes. ## Verification, all on `045a05c26` (the patch round's re-runs at `f730dc423` are under Acceptance notes) - `pnpm exec vitest run packages/types/src/__tests__/`: `Test Files 240 passed (240)`, `Tests 5276 passed (5276)`. - `pnpm exec vitest run packages/plugin-calendar/`: `Test Files 46 passed (46)`, `Tests 328 passed (328)`. - Suites that read the changed markdown as data, taken from `node scripts/markdown-test-inputs.mjs --list` (classes `.changeset/**`, `content/docs/**` and `content/docs/api/schema-reference.md`): the 15 readers under `scripts/__tests__/` give `Test Files 15 passed (15)`, `Tests 682 passed (682)`. The readers under `packages/types` ran in the 240 above. - `type-check`: `@object-ui/types` (tsc on the main, examples and test configs) and `@object-ui/plugin-calendar` (after building its dependency closure). Both exit 0. - Doc gates: `pnpm docs:check-links` prints "Links are valid across 17 scan roots."; `pnpm check:doc-types` prints "Every documented component type is registered."; `pnpm check:doc-fences`, `check-doc-example-ids`, `check-doc-expression-carriage` and `pnpm check:doc-example-readers` exit 0. - `pnpm check:control-bytes` is OK. `pnpm check:new-line-citations` prints `VERDICT new-cross-file-line-citations: 0 new citation(s)`. `node scripts/check-changeset-presence.mjs` prints "5 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)". `pnpm changeset:check` exits 0. `pnpm check:pending-changeset-literals` prints "No test source names a pending changeset." - `pnpm check:changeset-claims` (report-only): 50 pending changesets name a file this PR touches (the shared `complex.ts` / `objectql.ts` / zod files and `schema-reference.md`). I read them against the diff. No pending changeset quotes the changed text, and the two retirement changesets' closing sentences about the `describe` strings stay true. - `check-changeset-overwrite` (report-only): 3 files modified, each its case 2 (a deliberate prose correction), with declarations unchanged. - eslint (`--no-inline-config --format json`) over the five touched source files: 5 files, 0 errors, 49 pre-existing warnings, none on an edited line. `eslint.config.js` enables no type-aware linting, so a comment or string diff cannot change another file's result. - NOT MEASURED: `check-doc-snippet-types` and `check-doc-example-types`. Reason: both exit 2 with PREREQUISITE NOT MET (they need a 34-package scoped build). They type-check code fences, and the only doc edit here is a table cell. ## Acceptance notes - **`objectui#5783`, folded in the PM patch round (head `f730dc423`).** It also answers 404 (control: `objectstack-ai#5781` answers 200), and it was in a changeset this PR already edits, so the seat extended the claim's surface to that one pointer. `.changeset/4730-retire-dead-locale-key-batch.md` line 7 now reads `` `calendar.agenda` included). `` with no replacement citation, as a single hunk `@@ -7 +7 @@`. The frontmatter sha256 is unchanged (`57e32eec…`). The patch round re-ran control bytes, changeset presence / `changeset:check` / claims / overwrite / pending literals, and the two `scripts/__tests__` suites that read `.changeset/**` (2 files / 44 tests): all exit 0. The one residual is the header docblock of `dead-key-batch-retired-4730.test.ts`, which does not ship and sits with the other comment-only test sites below. - The docblocks and comments in `calendar-view-mode-agenda-retired.test.ts`, `default-view-agenda-retired.test.ts`, `dead-key-batch-retired-4730.test.ts` and `scalarKeysAreDeclaredAndHonoured-8201.test.ts` still cite the dead numbers. They do not ship and are optional per the triage. - The card's published/comment-only split was wrong in both directions (see above). A `dist` grep settles that classification for future cards of this class. --- _Generated by [Claude Code](https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5623
What
ObjectTimeline.tsxhand-rolled its ownuseSafeObjectLabelwrapper: adocstring near-verbatim from the shared hook, a 3-member
OBJECT_LABEL_FALLBACKcast
as any, anduseSafeObjectLabel() { return useObjectLabel() ?? OBJECT_LABEL_FALLBACK; }.Its single consumer (
const { fieldOptionLabel } = useSafeObjectLabel();) isreplaced with the shared
useSafeFieldLabelfrom@object-ui/react(re-exported from
@object-ui/i18n), and the local docstring/const/function(21 lines) are deleted.
packages/plugin-timeline/src/ObjectTimeline.tsx— swap the import(
useObjectLabel→useSafeFieldLabel), delete the local wrapper, updatethe call site.
packages/plugin-timeline/src/ObjectTimeline.test.tsx— its@object-ui/reactmock replaces the whole module (no
...actualspread), so it neededuseSafeFieldLabeladded in place of the now-unuseduseObjectLabelentryor the destructure would throw on
undefined.packages/plugin-timeline/src/__tests__/timeline-shared-safe-field-label-5623.test.tsx—pins the triage-named acceptance check directly against the REAL
@object-ui/react/@object-ui/i18nexports (nouseSafeFieldLabelmock):the timeline's one call site (
fieldOptionLabel, used to resolve thestatus/prioritymeta-chip labels) resolves to the same raw metadatalabel with no
I18nProvidermounted (unbound) and with one mounted butcarrying no matching translation (bound) — and a third case confirms a real
translation resolves when one is bound, so the equivalence isn't just
because the resolver is inert.
Why this is safe (the
as anycast erased a real disagreement)The local fallback was 3 members (
fieldOptionLabel,translateOptions,fieldLabel); the sharedSAFE_FIELD_LABEL_FALLBACKinpackages/i18n/src/useObjectLabel.tsis 5 (addssectionLabel,actionLabel). Per PR #5585,useObjectLabel()never actually returnsnullish any more (its memo holds on both the bound and no-instance paths), so
in both the old and new code the
?? FALLBACKbranch is dead in practice —which is exactly why swapping the fallback SHAPE underneath it is safe for
this one call site. Confirmed directly (see Testing) rather than asserted.
Testing
Reverse-verification, run while writing this: restored
ObjectTimeline.tsxto its pre-fix state (
git checkout HEAD~1 -- packages/plugin-timeline/src/ObjectTimeline.tsx,i.e. the local
useSafeObjectLabel/OBJECT_LABEL_FALLBACK) with the NEW testfile in place, and re-ran it — same 3/3 pass, which is the direct proof of
the equivalence claim (not merely "didn't regress"): the call site behaves
identically whether reached through the local 3-member fallback or the shared
5-member one. Then restored the fix by checking out
claude/issue-5623-timeline-shared-safe-field-label's version of the file(
git statusclean afterward).Targeted
eslint --no-inline-configon the touched files: 0 errors, 41warnings — all pre-existing (
@typescript-eslint/no-explicit-anyonlong-standing
anyprops typing,react-hooks/exhaustive-deps), confirmedby linting the pre-fix
ObjectTimeline.tsxfor comparison: 32 warnings therevs 31 on the fixed file — one FEWER, the
as anycast this PR removes.Dependency closure built first (
pnpm --filter '@object-ui/plugin-timeline^...' build),exit 0.
node scripts/check-changeset-presence.mjs/check-changeset-no-major.mjs/check-control-bytes.mjs: all pass; changeset has empty frontmatter per.changeset/README.md's own "DON'T create a changeset for internalrefactoring with no API changes" — the removed symbols
(
useSafeObjectLabel,OBJECT_LABEL_FALLBACK) were never exported.Neither
useSafeObjectLabelnorOBJECT_LABEL_FALLBACKhad any otherreference anywhere in the repo (grepped
packages/).Scope
Per triage (2026-08-22) and the claim comment: mechanical dedup only. #5625
(the pivot-table ref workaround) shares the #5587 lineage but has its own
behaviour surface and stays a separate card, out of scope here.
Generated by Claude Code