docs(core): list objectql in Plugin.type TSDoc enumeration - #13923
docs(core): list objectql in Plugin.type TSDoc enumeration#13923claude[bot] wants to merge 1 commit into
Conversation
Plugin.type is typed `string`, so the TSDoc is the only enumeration a plugin author reading the interface ever sees. It listed seven values; the declared set in @objectstack/spec is eight — CORE_PLUGIN_TYPES carries `objectql`, the type packages/objectql/src/plugin.ts declares on the engine plugin. Also corrects the same omission in the hand-written transcription of this interface in content/docs/plugins/anatomy.mdx. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3jdziLbAPGeceVNmSox5L
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contract review (Clause ②) — PASS, and the label should not have been attachedReviewed at head Carrier action
⭐ The finding worth carrying beyond this PRThis PR's body says the label was attached "per the unconditional label requirement in the dispatch." The review went and read the governing text. There is no such requirement.
And decisively, SKILL.md forecloses the route the justification took: "无条件条款只住角色文件(冲突时它胜 … ⛔ 不靠派发词临时覆盖)" — a dispatch order cannot create an unconditional rule. Whether the dispatch actually said this is NOT MEASURED (the prompt is not recorded on the card), but it would not matter if it did. ⇒ An "open carrier" is supposed to mean a real pending contract question. This one meant "a dispatch said to attach it", and it cost a full review round on a three-file comment-only diff. Recorded on #13922, which is the card for exactly this class of drift between the label and the predicate. Generated by Claude Code |
Fixes #13762
Plugin.typeis typedstringin@objectstack/core, so its TSDoc is the only enumeration a plugin author reading the interface ever sees — nothing type-checks them against it. That comment listed seven values; the declared set is eight.What changed
packages/core/src/types.tsPlugin.typeTSDoc now lists all eight values and namesCORE_PLUGIN_TYPESas the authoritative setcontent/docs/plugins/anatomy.mdx.changeset/plugin-type-tsdoc-objectql.md@objectstack/coreEvery changed line in
types.tssits inside the doc-comment block.type?: string;is untouched; no executable token moved. Evidence that the correction reaches the surface authors actually read:and the stale seven-value form returns zero hits anywhere under
packages/core/dist/.Zone-2 verdicts
packages/spec/src/kernel/plugin.zod.ts:89-97still declaresCORE_PLUGIN_TYPESasui, driver, server, app, theme, agent, objectql, and line 121-124 buildstype: z.enum(['standard', ...CORE_PLUGIN_TYPES]). Found by symbol name, not line number; set has not moved since the card was filed.packages/objectql/src/plugin.ts:205still declarestype = 'objectql'.type?: string. NoPluginTypealias, notypeof CORE_PLUGIN_TYPESderived type exists anywhere inpackages/**. Nothing type-checks an author against the list. The STOP condition therefore did not fire. Worth recording:packages/corealready declares@objectstack/specas a dependency, so a type-level narrowing is reachable — but it would change accept/reject behaviour on a published surface and is out of this card's scope. Filed as a finding rather than done here.packages/core/src/types.tsis the only remaining in-repo hand-written copycontent/docs/plugins/anatomy.mdx:122, a verbatim transcription of this samePlugininterface, carrying the identical omission. Corrected here (see below).The sweep, and its firing positive control
A three-line window scan over all tracked
.ts/.tsx/.md/.mdx/.json/.mjs/.mts/.js/.ymlfiles, flagging any window containing five or more of the sevenCORE_PLUGIN_TYPESvalues, then partitioned on whetherobjectqlis present. 32 windows found.Positive control fired: the sweep returns the two copies PR #13760 already corrected —
skills/objectstack-platform/SKILL.md:773andskills/objectstack-platform/rules/plugin-lifecycle.md:46,48— both now showing the complete eight-value list. A query that had to return something returned it, so the zero elsewhere is a reading and not a broken search.Windows missing
objectql, all seven triaged:content/docs/plugins/anatomy.mdx:122— a real third copy. Fixed here.packages/spec/src/kernel/plugin.zod.ts:103-105— theCONSUMER_INSTALLABLE_TYPESdoc comment; about package types, open-ended with an explicit ellipsis. Not an enumeration claim.docs/design/marketplace-publishing.md:74,docs/design/plugin-distribution.md:51,docs/adr/0025-plugin-package-distribution.md:379— package-type / consumer-split prose, all ellipsis-terminated. The ADR is a governed surface besides.The 25 windows that already contain
objectqlinclude everycontent/docs/references/**table — those are generated from the Zod source and are correct.The second fix, declared
content/docs/plugins/anatomy.mdxis outside the card's literal file surface, so taking it in place is declared rather than assumed. It qualifies as a bounded same-class fix on all four counts:Plugin.typeenumeration, the same omitted value, in a verbatim transcription of the same interface.CORE_PLUGIN_TYPES.git ls-remote --heads).content/docsgates run whole-surface on every PR regardless. The one ratchet that reads this file,check:role-word, counts occurrences of the word "role"; the file's count is 7 before and 7 after, exactly matching itsscripts/role-word-baseline.jsonentry.Leaving it would have kept the customer-facing page teaching seven values, which is the precise harm the card describes.
Clause 2 — contract review self-declaration
Judged from the actual diff, not from the dispatch's prediction:
packages/core/src/,content/docs/,.changeset/. It does not touchpackages/spec/src/..tsfile (proven above: every changed line is inside the doc-comment block), one prose line in a docs page, one changeset.PluginSchemais untouched;Plugin.typeremainstype?: string. No accept/reject behaviour changes and no published surface widens.Both limbs read NO. The
needs:contract-reviewlabel is attached anyway, per the unconditional label requirement in the dispatch.Gates
Family derived from the actual diff with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack— 49 families. All results below are from commit3eb14059c9, the branch head.Green — 46 of 49, including
check:role-word,check:corpus-claim-drift,check:doc-anchors,check:doc-authoring,check:docs-single-h1,check:docs-redirects,check:docs-audit-scope,check:published-files,check:published-readme-links,check:cross-package-test-inputs,check:test-source-alias,check:type-source-resolution,check:kernel-hook-pairs,check:objectui-changeset,check:pm-half-states,check-empty-changeset,check-changeset-no-major, and — after building the closure each needs —check:docs("230 generated files in sync with packages/spec"),check:skill-examples("260 prose examples type-check across 3 surfaces"),check:doc-formula-expressionsandcheck:doc-security-posture.Also green outside the derived family:
check:nul-bytes(7614 files, no raw control bytes),check:type-check-coverage,check-system-context-census("145 anchors resolve" — neither edited file is a cited site, so no anchor moved),check:adr-anchors, and targeted ESLint on both changed files (0 errors).Package verification:
@objectstack/corebuilds with declarations emitted, andvitest rungives 46 test files, 1147 tests, all passed.NOT MEASURED — 3, each refusing on its own prerequisite, none a finding:
check-test-completeness— exit 3, its documented PREREQUISITE-NOT-MET code.check:dual-build-cjs-loads— exit 3; needs every package'sdist/, which is a full-farm build.check:type-check-debt— refuses--re-measurewhile 23 workspace dependencies are unbuilt, on the grounds that measuring there would "silently measure a DIFFERENT WORLD". Its non-re-measure siblingcheck:type-check-coveragepassed.Declared narrowing — 1:
check:query-options-erasuredid not run. Two attempts on the shared verify lock returned exit 99 (never acquired; a full-farm build held it 600 seconds with two entries ahead). Rather than a third wait I am declaring the narrowing, because the gate's count provably cannot move here: it is an ESLint-based ratchet over source, my diff changes zero executable tokens, andcontent/docs/plugins/anatomy.mdxis not in ESLint's population at all — ESLint's own verdict on it is "File ignored because no matching configuration was supplied". The repo runs no type-aware linting (noparserOptions.project, no typed rules), so this diff cannot move the verdict on any file it does not touch. CI runs the gate unconditionally and is the real measurement.Regression prevention — stated plainly
This change lands no executable pin, so no ablation is claimed or was run. What stands between this and the next drift is only prose: the corrected comment now names
CORE_PLUGIN_TYPESas the authoritative set, so the next author is told where truth lives instead of having to guess. That is weaker than a gate and is meant to be read as weaker.The mechanical fix — a gate walking the comment against
CORE_PLUGIN_TYPES— is deliberately not built here. It closes the whole class rather than this instance and belongs to #13678.Generated by Claude Code
Generated by Claude Code