Skip to content

docs(guides,plugins,tooling): clear three .mdx pages off the doc-snippet ledger (#5174 batch 5) - #7294

Merged
yinlianghui merged 5 commits into
mainfrom
claude/issue-5174-mdx-ledger-batch5
Sep 2, 2026
Merged

yinlianghui merged 5 commits into
mainfrom
claude/issue-5174-mdx-ledger-batch5

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Part of #5174

Batch 5 of the UNGATED_DOCS burn-down — the first batch into the .mdx half. Batches 1-4 (#5341 #5951 #5967 #5983 #5991) cleared every content/docs .md page; this one takes the three highest-density .mdx entries and delivers all three whole.

Per page

page blocks compile declared fragment diagnostics cleared
content/docs/guide/objectos-integration.mdx 21 9 12 54
content/docs/plugins/plugin-chatbot.mdx 18 18 0 21
content/docs/plugins/plugin-map.mdx 16 13 3 42
total 55 40 15 117

Pages were chosen by descending ts/tsx block count over the 12 .mdx ledger entries, re-derived from the script with its own TS_FENCE_LANGUAGES set and fence walk — not from the dispatch's list.

Invariants

reading before after
UNGATED_DOCS entries 43 40
covered documents 181 184 (strictly grows)
covered docs holding a ts/tsx block 80 83
covered blocks 385 440
blocks compiled 272 312
blocks declared fragment 113 128
content/docs .mdx entries remaining 12 9
--build-filter 21 filters / 33 tasks 23 filters / 34 tasks
  • The ledger hunk contains only removals: git diff origin/main -- scripts/check-doc-snippet-types.mjs is 15 deleted lines and 0 added.
  • Gate strictness is byte-identical from the fence-scanning banner to EOF, both sides:
    sha256 b87e347626a6cbab30b904eaf7d3eb72f6804122505bdf9ec8f2f2c8136e95a3

The defects, and where they were

objectos-integration.mdx is a getting-started integration guide, and four of the adapter APIs it documents do not exist. All four were hidden underneath a single unresolved name — the page never imported ObjectStackAdapter, so TS2304 was the only thing the gate could say. Resolving that name is what exposed them:

  1. new ObjectStackAdapter({ headers: ... }) — the whole "Multi-Tenancy Support" section. The constructor config is a sealed object literal type with no index signature; headers is not on it. Repaired to the real route, the fetch hook the adapter uses for every call it makes.
  2. new ObjectStackAdapter({ websocket: ... }) and adapter.subscribe(...) — the "Real-time Updates with WebSockets" section. There is no WebSocket transport and no server-push subscription anywhere in @object-ui/data-objectstack; subscribe is not a member. The real mechanism is onMutation, which notifies of writes this adapter instance performed and returns its own unsubscribe function. Section repaired and retitled "Reacting to Data Changes", and it now says out loud what the adapter does not do.
  3. cache: { enabled, strategies } — cache exists but takes only maxSize and ttl. Repaired to the two real keys.
  4. viewTypes / fieldNames on an object-view node — both have zero read sites in the packages. ObjectView reads defaultViewType (a declared member of ObjectViewSchema) and columns (string[] or ListColumn[]). Corrected to those two. ⚠️ This one the gate cannot catch — see below.

A reader copying any of the first three got a rejected config or a TypeError.

Lid check — POSITIVE on two pages, and reported as measured

The dispatch required a re-run after resolving unresolved names. Results, per page:

  • objectos-integration.mdx — POSITIVE. Adding the missing ObjectStackAdapter import to three blocks turned one TS2304 into TS2353 on headers, TS2353 on websocket, TS2339 on subscribe and TS2353 on cache.enabled. Defects 1-3 above are entirely lid.
  • plugin-chatbot.mdx — POSITIVE. Annotating the schema and message literals surfaced 5 x TS2353 on avatarFallback (see below).
  • plugin-map.mdx — NEGATIVE. After giving the eight unparseable schema literals const bindings and annotating them ObjectMapSchema, nothing new appeared — 0 diagnostics underneath. Reported as a negative result.

What the green does not mean

  • BaseSchema carries [key: string]: any (base.d.ts:357), and ChatbotSchema, ObjectMapSchema and ObjectViewSchema all extend it. A wrong top-level key on any of these literals is structurally invisible — which is exactly why defect 4 above had to be found by grepping read sites rather than by the compiler. The green certifies the types of declared members, never the existence of a key.
  • Unannotated literals are checked against nothing. Three plugin-chatbot example blocks (supportChat, salesBot, multiAgentChat) and two plugin-map static-data blocks are deliberately left unannotated — see the two contract gaps below. Their green says only "this parses and its expressions type".
  • What is sealed and therefore genuinely checked on these pages: ChatbotSchema and ObjectMapSchema member types, ChatMessage (both the authoring and the plugin shape), ChatToolInvocation.state, ObjectViewSchema.defaultViewType, ObjectMapConfig, and the ObjectStackAdapter constructor config, which is a sealed literal type and is where all three repaired defects were caught.

Two contract gaps found, NOT fixed here (outside this PR's surface)

Both are package-type defects, not documentation defects. The documentation is correct in each case and is left as it stands.

  1. Per-message avatar / avatarFallback are honoured but undeclared. Chatbot resolves message.avatarFallback || userAvatarFallback (packages/plugin-chatbot/src/index.tsx:177-178), and authoredToRuntimeMessage carries the keys across the seam via its ...passthrough spread — so authoring them in chatbot metadata works end to end. But no authoring-facing type declares them: @object-ui/types' ChatMessage does not, and neither does SeamChatMessage (its RuntimeOnlyMessageKeys covers only buildProgress, blueprintProgress, charts). Only the plugin's own runtime ChatMessage has them. Annotating the three affected blocks would have meant deleting working, documented behaviour, so they stay unannotated.
  2. ObjectMapSchema.objectName is required but the component treats it as optional. ObjectMap branches on schema.staticData first (ObjectMap.tsx:153) and guards objectName everywhere else, so the documented static-data route needs no objectName — yet the type demands one. The static-data example blocks are therefore left unannotated.

Gate verdicts

Before (pristine origin/main ledger, 43 entries):

Scanned 224 document(s): 181 covered (80 of them hold a ts/tsx block), 43 ungated
Covered blocks: 385 — 272 to compile, 113 declared fragment(s).
Semantic phase: 272 of 272 block(s) judged, 0 failed.

After, at merge commit fe053c7b6:

Scanned 224 document(s): 184 covered (83 of them hold a ts/tsx block), 40 ungated
Covered blocks: 440 — 312 to compile, 128 declared fragment(s).
Syntax phase:   every block parsed, so every one of them reached the semantic phase.
Semantic phase: 312 of 312 block(s) judged, 0 failed.

All run at fe053c7b6, after git merge origin/main (never rebased):

check exit verdict
check:doc-snippets 0 Semantic phase: 312 of 312 block(s) judged, 0 failed.
check:doc-fences 0 every TypeScript block in 224 document(s) correctly fenced
check:doc-types 0 Every documented component type is registered
check:doc-links 0 Links are valid across 17 scan roots
check:control-bytes 0 scanned 6008 tracked text file(s)
check:readme-exports 0 386 self-imports judged, 0 wrong-path, 0 fabricated
check:skills-paths 0 92/93 stated path(s) resolve
check:shell-escape-residue 0 0 occurrence(s) outside a fence
check-changeset-presence 0 no changeset owed (docs + scripts only)
vitest, 7 files from the repo root 0 177 tests passed

The vitest run is the two suites the dispatch named plus the five other files that git grep shows name check-doc-snippet-types — pin suites in examples/schema-catalog, plugin-gantt, react and types that an edit to this script could have hijacked.

Declared narrowing

pnpm lint was not run repo-wide; the narrowing is measured, not assumed. ESLint's own answer for the four changed files (--format json, 4 files returned): the three .mdx files report File ignored because no matching configuration was supplied — they are outside eslint's configured surface entirely, since every files pattern in eslint.config.js is **/*.{ts,tsx}. The one file it does lint, scripts/check-doc-snippet-types.mjs, is clean at 0 errors, 0 warnings. eslint.config.js declares no projectService and no project:, so type-aware linting is not enabled and this diff cannot move the lint verdict on any file it did not touch.

One further note on measurement honesty: check:readme-exports first exited 1 with 45 findings, every one of them the string its type entry ./dist/index.d.ts is not on disk -- run pnpm build first, all in plugin-ai and plugin-gantt — packages outside this gate's build closure. That was an unbuilt tree, not a red gate. Those two closures were built and it is now genuinely green.

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review September 2, 2026 05:07
@yinlianghui
yinlianghui added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit 9bf0abf Sep 2, 2026
29 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-5174-mdx-ledger-batch5 branch September 2, 2026 05:21
os-justin pushed a commit that referenced this pull request Sep 5, 2026
…n both faces

`packages/plugin-chatbot/src/index.tsx:173–178` reads `message.avatar ||
userAvatarUrl` and `message.avatarFallback || userAvatarFallback` (and the
assistant twins), the authoring-to-runtime seam spreads every unlisted key
through (`chatMessageAdapter.ts`, `...passthrough`), and the SDUI renderer
feeds the authored `messages[]` straight in — so a per-message avatar
override renders and is documented, and no authoring-facing type declared
it. objectui#4424's `RuntimeOnlyMessageKeys` named only the three keys API
mode lifts out of the stream.

Measured on 446d93d before the change, through the built types dist:
`ChatMessage` has no index signature (objectui#5155 — none is added), so an
author annotating `ChatbotSchema.messages` got TS2353 on a value that
renders (five on `plugin-chatbot.mdx`); `ChatMessageSchema` is a plain
strip-mode `z.object`, so the value parsed green through
`ChatMessageSchema`, `ChatbotSchema` and `safeValidateSchema` and was
DROPPED from the parsed output, and `avatar: 42` was admitted-and-stripped.
After: the parse keeps the value and refuses a non-string at the key.

Pin: `__tests__/chat-message-avatar-keys-7295.test.ts` — read-site text and
read-set derivation off disk, mirror-shape membership, acceptance with the
value surviving through the mirror, `ChatbotSchema` and the published entry
point, refusal at the key (and at `messages.0.KEY` through the entry point),
invariant type-level pins (string, optional, not any, equal to the
chatbot-level keys they override, no index signature), a control key the
plugin never reads (`avatarUrl`) that stays undeclared on both faces and is
still admitted-and-stripped, and the three doc blocks' annotations.

Docs: the three `plugin-chatbot.mdx` example blocks PR #7294 left
unannotated (`supportChat`, `salesBot`, `multiAgentChat`) are annotated
`ChatbotSchema` again. No `UNGATED_DOCS` row for that page exists on main,
so `scripts/` is untouched. `packages/plugin-chatbot/**` untouched;
`SeamChatMessage` inherits both keys through its `ChatMessage` half.

Changeset: `@object-ui/types` patch — the accept set only widens toward
what already renders.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 9, 2026
…n both faces (objectui#7295) (objectstack-ai#7732)

* fix(types): declare `avatar` and `avatarFallback` on `ChatMessage`, on both faces

`packages/plugin-chatbot/src/index.tsx:173–178` reads `message.avatar ||
userAvatarUrl` and `message.avatarFallback || userAvatarFallback` (and the
assistant twins), the authoring-to-runtime seam spreads every unlisted key
through (`chatMessageAdapter.ts`, `...passthrough`), and the SDUI renderer
feeds the authored `messages[]` straight in — so a per-message avatar
override renders and is documented, and no authoring-facing type declared
it. objectui#4424's `RuntimeOnlyMessageKeys` named only the three keys API
mode lifts out of the stream.

Measured on 446d93d before the change, through the built types dist:
`ChatMessage` has no index signature (objectui#5155 — none is added), so an
author annotating `ChatbotSchema.messages` got TS2353 on a value that
renders (five on `plugin-chatbot.mdx`); `ChatMessageSchema` is a plain
strip-mode `z.object`, so the value parsed green through
`ChatMessageSchema`, `ChatbotSchema` and `safeValidateSchema` and was
DROPPED from the parsed output, and `avatar: 42` was admitted-and-stripped.
After: the parse keeps the value and refuses a non-string at the key.

Pin: `__tests__/chat-message-avatar-keys-7295.test.ts` — read-site text and
read-set derivation off disk, mirror-shape membership, acceptance with the
value surviving through the mirror, `ChatbotSchema` and the published entry
point, refusal at the key (and at `messages.0.KEY` through the entry point),
invariant type-level pins (string, optional, not any, equal to the
chatbot-level keys they override, no index signature), a control key the
plugin never reads (`avatarUrl`) that stays undeclared on both faces and is
still admitted-and-stripped, and the three doc blocks' annotations.

Docs: the three `plugin-chatbot.mdx` example blocks PR objectstack-ai#7294 left
unannotated (`supportChat`, `salesBot`, `multiAgentChat`) are annotated
`ChatbotSchema` again. No `UNGATED_DOCS` row for that page exists on main,
so `scripts/` is untouched. `packages/plugin-chatbot/**` untouched;
`SeamChatMessage` inherits both keys through its `ChatMessage` half.

Changeset: `@object-ui/types` patch — the accept set only widens toward
what already renders.

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

* fix(types): spell the optionality helper without the empty-object type in the objectui#7295 pin

`@typescript-eslint/no-empty-object-type` flags the `{}` in
`IsOptional`: the intent is "an object with no keys is assignable to
`Pick<T, K>` only when `K` is optional", so the helper now says
`Record<string, never>`. Verified to still discriminate: true for
`avatar` / `avatarFallback`, false for the required `id` / `content`.
No other change; `@object-ui/types#lint` is back to 0 errors.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants