spec: name the live ui plugin type in the PluginSchema describe strings - #15639
Conversation
`PluginSchema.type` is `z.enum(['standard', ...CORE_PLUGIN_TYPES])` and
`CORE_PLUGIN_TYPES` spells the frontend member `ui`. The `staticPath`,
`slug` and `default` describe strings still named `ui-plugin`, a value the
same schema refuses two lines above — and they read as instructions
("Required for type=..."), so an author or agent following them writes a
value that is rejected.
Also updates the two `content/docs/plugins/anatomy.mdx` prose sites that
used the retired spelling; the page's own section heading already reads
`### 2. UI Plugin (\`ui\`)`.
No accept/reject behaviour changes: `type: 'ui-plugin'` is refused before
and after, `type: 'ui'` accepted before and after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4
`content/docs/references/kernel/plugin.mdx` is auto-generated from `packages/spec/src/kernel/plugin.zod.ts` (banner: "AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate"), so the three table rows follow the describe strings. Regenerated with `pnpm --filter @objectstack/spec gen:schema && gen:docs` — never hand-edited. `authorable-surface.base.json` was deliberately NOT re-anchored: the build prints re-anchoring as its own reviewed act (`gen:authorable-surface-base`), not a side effect of this run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 129 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3fc1e452eeaa5097a3c203601bd22ce44f79f061 && git checkout 3fc1e452eeaa5097a3c203601bd22ce44f79f061
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d30ccb9bd963942d33072443f680a32664087346 6fd7128575e748bb6fe1e1bfdbdabbe422a02c1e && git checkout -B drift-repro d30ccb9bd963942d33072443f680a32664087346 && git merge --no-ff 6fd7128575e748bb6fe1e1bfdbdabbe422a02c1e
node scripts/docs-audit/affected-docs.mjs --json d30ccb9bd963942d33072443f680a32664087346
|
Fixes #14609
PluginSchema.typeisz.enum(['standard', ...CORE_PLUGIN_TYPES]), andCORE_PLUGIN_TYPESspells the frontend memberui. ThestaticPath,sluganddefaultdescribe strings two lines below it still namedui-plugin— a value the same schema refuses. They are not merely stale: they read as instructions ("Required fortype="ui-plugin""), so an author or an agent following the field's own documentation writes a value that is then rejected, with the correct spelling nowhere in the sentence that sent them there.What changed
packages/spec/src/kernel/plugin.zod.ts:126-:128(Required for type="ui"),(Required for type="ui"),(Only one "ui" plugin can be default)content/docs/plugins/anatomy.mdx:80,:96uiplugin references" and "uiplugins"; the page's own heading already read### 2. UI Plugin (\ui`)`content/docs/references/kernel/plugin.mdxpnpm --filter @objectstack/spec gen:schema && gen:docs. Its banner reads "AUTO-GENERATED — DO NOT EDIT".changeset/plugin-describe-ui-type-spelling.md@objectstack/specOn the
defaultstring,ui-pluginwas doing duty as a noun ("only one ui-plugin"), so a bare substitution would have left "Only one "ui" can be default". It is spelledOnly one "ui" plugin can be default— the quoted token is still exactly the enum member an author must type.The correction reaches the published surface, not just the source file. These describes compile into the shipped Zod schema, the generated JSON Schema and the reference page. After a full rebuild: zero occurrences of
ui-plugininpackages/spec/dist/, zero in the bundledjson-schema/objectstack.json(1,589 definitions), and the reference table now agrees with thetyperow printed directly above it — that row already listed'ui'among the accepted members while the three rows underneath told the reader to writeui-plugin.Census — every
ui-pluginoccurrence was disambiguated, not sweptui-pluginoccurs in 17 files. Each was read to its declaring meaning before anything was touched.Deliberately unchanged, and why:
packages/core/src/plugin-type-closed-set.test.tsandpackages/rest/src/plugin-type-closed-set.pin.test.tsnameui-pluginas a non-member on purpose. They are the reason this correction is provable, and both stay green (3 + 4 tests).packages/spec/src/system/core-services.zod.ts:71,packages/metadata-protocol/src/protocol.ts:3574andscripts/check-service-providers.mjs:12— not the same drift. All three carry one copied incident narrative about a hand-written remedy table in which ten of fifteen entries named a package that does not exist;ui-pluginthere is one of those fabricated package names, not aPluginSchema.typemember. Rewriting it would make the sentence false — it would claim the old table saidui, which it did not. (Triage readcore-services.zod.tsas "a secondpackages/specinstance, same drift" and scoped it in; that reading does not survive reading the surrounding docblock. The third copy inscripts/check-service-providers.mjswas in neither the card nor triage's census and corroborates the narrative reading.)docs/adr/**,docs/design/**and theCHANGELOG.mdfiles — historical records. Several are just links to0026-client-ui-plugin-distribution.md, an ADR filename.packages/plugins/plugin-hono-server/src/hono-plugin.ts:507-508— a runtime arm that still accepts the value. Out of scope for this lane; filed separately as [finding]plugin-hono-serverstill accepts the legacyui-plugintype thatPluginSchemarefuses — an unreachable arm under ADR-0049 #15638 and not edited here.Verification
All at
6fd712857, the pushed HEAD, with a clean tree.pnpm --filter '@objectstack/spec^...' build && pnpm --filter @objectstack/spec build— exit 0,check-dts-emitted: 34/34 declaration file(s) present.pnpm --filter @objectstack/spec test— 472 test files, 12,686 tests passed.pnpm --filter @objectstack/spec typecheck— exit 0.@objectstack/coreplugin-type-closed-set.test.ts3/3,@objectstack/restplugin-type-closed-set.pin.test.ts4/4.type: 'ui-plugin'is refused before and after;type: 'ui'is accepted before and after. No accept/reject behaviour moves, and no key is added, renamed or removed.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(exit 0; it read the merge base itself rather than a hand-built list) — all exit 0, each captured before any pipe. Notablycheck:generated,spec check:docs,check:authorable-surface,check:merge-driver,check:docs-audit-scope,check:corpus-claim-drift, the three changeset gates, andcheck:nul-bytes(OK (scanned 7572 text files ... no raw ASCII control bytes)).pnpm lint(eslint . --no-inline-config, whole repo) — exit 0. Run in full, so this is a measurement and not a narrowing.authorable-surface.base.jsonwas deliberately not re-anchored: the build prints re-anchoring as its own reviewed act (gen:authorable-surface-base), never a side effect of a regeneration run.node scripts/pm/check-governed-merges.mjs --test ...→ exit 0, "NOT governed". Ordinary queue landing applies. Opened as a draft; not flipped ready, not enqueued, no auto-merge.One thing left open for the PM
The
packages/corepin's comment reads "'ui-plugin'is the spelling a stale describe() string still uses" — present tense, and this PR makes it false. The pinned value must not change, but that sentence now points a reader at a stale describe that no longer exists. Those exact lines were fenced must-not-change in dispatch, so I did not touch them; a one-line tense correction is the obvious follow-up if the fence lifts.🤖 Generated with Claude Code
https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4
Generated by Claude Code