From 153092c3a5d21dd2f6de02715910b47899751064 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 18 Sep 2026 07:25:53 +0000 Subject: [PATCH 1/2] docs(plugin-detail): the Activity tab example names the registered `record:activity` block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "With Tabs" example taught a detail tab whose `content.type` was `activity-timeline`. `DetailTabs` renders a tab's `content` through ``, so `content.type` is an SDUI node position judged by the component registry — and nothing registers `activity-timeline`. A reader copying the example got the registry's `Unknown component type` panel (OBJUI-001) where the timeline should be. Measured with the repository's own derivation rather than by reading the register calls: `deriveRegistryKeys()` from `scripts/check-doc-component-types.mjs` builds the 649-key universe that gate judges against, and it answers record:activity REGISTERED <- packages/plugin-detail/src/index.tsx:673 activity-timeline absent activity absent (the `skipFallback: true` half) against lit controls (`related-list`, `detail-section`, `record:details` all REGISTERED; a nonsense key absent), so the reading is the gate's, not a transcription of the source. Two corrections, because naming the type alone would leave the block fed by a key it never reads: - `type: 'record:activity'`, namespace spelled out. The registration passes the bare name under `{ namespace: 'record', skipFallback: true }`, and `skipFallback` is what keeps the bare name unclaimed — so `record:activity` resolves and `activity` resolves to nothing. That `activity` is also the tab's own `key` is a coincidence of spelling. - `items`, not `data`. `RecordActivityRenderer` takes its feed from `items` on the node, a mounted discussion context, or a self-fetch from `sys_activity` scoped off `useRecordContext`. The last two need a record host and a bare `` mounts neither, so the example's own intent — a caller handing over a feed it already owns — is source one. `data` is read on no path. `activityData` is retyped from `Record[]` to the exported `FeedItem`, which puts the block under `check:doc-snippets`: that gate compiles every ts/tsx block in `packages/**/README.md` against the built `dist/*.d.ts`, so the import is now held there. What is NOT held, stated so it is not mistaken for coverage: `check:doc-types` is the gate that judges `type` literals, and it deliberately does not walk `packages/NAME/README.md` — that widening is objectui#7896's, and it is blocked by this card. The corrected type therefore lands as a diff for the next reader, not as a gate failure. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq --- packages/plugin-detail/README.md | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/plugin-detail/README.md b/packages/plugin-detail/README.md index d61358d79a..e9ce4218d2 100644 --- a/packages/plugin-detail/README.md +++ b/packages/plugin-detail/README.md @@ -134,8 +134,9 @@ const accountDetail = []; +declare const activityData: FeedItem[]; declare const navigate: (url: string) => void; declare const deleteAccount: (id: string) => void; @@ -166,9 +167,11 @@ const accountDetail = ; ``` +A tab's `content` is an **SDUI node**, not a private vocabulary: `DetailTabs` +renders it with ``, +so `content.type` is resolved by the component registry and an unregistered +name paints the `Unknown component type` panel (**OBJUI-001**) instead of a +component. Author only types this repository registers. + +Two things about the Activity tab above are worth copying rather than guessing +(objectui#8114 — it previously taught `type: 'activity-timeline'`, which +nothing registers): + +- **The key is `record:activity`, with the namespace spelled out.** The + registration in `src/index.tsx` passes the bare name under + `{ namespace: 'record', skipFallback: true }`, and `skipFallback` is what + stops the bare name from also being claimed globally — so `record:activity` + resolves and `activity` resolves to nothing. `activity` is additionally a tab + **key** in the example above; the two are unrelated. +- **The feed arrives as `items`, not `data`.** `record:activity` takes its feed + from three sources, in precedence order: `items` on the node, a mounted + discussion context, or a self-fetch from `sys_activity` scoped off + `useRecordContext`. The last two need a record host; a bare `` + like the one above mounts neither, so a caller that already owns the feed + passes it in as `items` (the convention `record:history` uses for `entries`). + `data` is not a key this block reads. + +See **The `record:activity` block** in the plugin-detail guide for its declared +inputs (`types`, `limit`, `filterMode`, `showCompleted`, …). + ## Schema The DetailView component accepts a `DetailViewSchema`, declared in From e9c4cc8336c1ab74a319ca5931a732ca711922f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 18 Sep 2026 07:29:17 +0000 Subject: [PATCH 2/2] docs(plugin-detail): changeset for the Activity tab example correction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `README.md` ships in `@object-ui/plugin-detail`'s `files`, so the broken example went out in every tarball and the correction reaches npm readers only through a release — the same reasoning objectui#7989 used for the i18n README's locale count, which is why this is a `patch` rather than an empty declaration. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq --- .../8114-detail-tab-activity-timeline.md | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .changeset/8114-detail-tab-activity-timeline.md diff --git a/.changeset/8114-detail-tab-activity-timeline.md b/.changeset/8114-detail-tab-activity-timeline.md new file mode 100644 index 0000000000..7b059643bf --- /dev/null +++ b/.changeset/8114-detail-tab-activity-timeline.md @@ -0,0 +1,54 @@ +--- +'@object-ui/plugin-detail': patch +--- + +The README's Activity tab example names `record:activity`, a block this package +registers, instead of `activity-timeline`, which nothing registers +(objectui#8114). + +`README.md` ships in this package's `files`, so the example went out in every +tarball. `DetailTabs` renders a tab's `content` through +``, which makes +`content.type` an SDUI node position judged by the component registry — so a +reader copying the tab got the registry's `Unknown component type` panel +(OBJUI-001) where the timeline should be. Same shape as the `line-chart` widget +in `plugin-dashboard/README.md` (objectui#7896's census; fixed by objectui#7951) +and the fourth known instance. + +Which type replaces it was read off the registry rather than guessed, using the +repository's own derivation — `deriveRegistryKeys()` from +`scripts/check-doc-component-types.mjs`, the 649-key universe that gate judges +against: + +| key | reading | +|---|---| +| `record:activity` | REGISTERED — `packages/plugin-detail/src/index.tsx:673` | +| `activity-timeline` | absent | +| `activity` (bare) | absent — the `skipFallback: true` half | +| `related-list`, `detail-section`, `record:details` | REGISTERED (lit controls) | + +Two keys move, because naming the type alone would leave the block fed through a +key it never reads: + +- **`type: 'record:activity'`**, namespace spelled out. The registration passes + the bare name under `{ namespace: 'record', skipFallback: true }`, and + `skipFallback` is what keeps the bare name unclaimed — `record:activity` + resolves, `activity` does not. That `activity` is also the tab's own `key` is + a coincidence of spelling, and the card that filed this read the key as + evidence there was no such component type. +- **`items`, not `data`.** `RecordActivityRenderer` takes its feed from `items` + on the node, a mounted discussion context, or a self-fetch from `sys_activity` + scoped off `useRecordContext`. The last two need a record host and a bare + `` mounts neither, so the example's own intent — a caller handing + over a feed it already owns — is the first source. `data` is read on no path. + +`activityData` is retyped from `Record[]` to the exported +`FeedItem`, which puts the block under `check:doc-snippets`. No package source +and no runtime behaviour changes. + +**Still ungated, stated so this is not mistaken for coverage.** +`check:doc-types` is the gate that judges `type` literals and it deliberately +does not walk `packages/NAME/README.md` — that widening is objectui#7896's, and +objectui#7896 is blocked by this card. Measured rather than assumed: with an +unregistered type substituted back into this very block, `check:doc-snippets` +and `check:doc-types` both still exit 0.