Skip to content

docs(protocol): drop the phantom configSchema manifest file-map row from plugin-spec - #13697

Merged
os-project-manager merged 2 commits into
mainfrom
claude/issue-12690-plugin-spec-phantom-configschema-row
Aug 31, 2026
Merged

docs(protocol): drop the phantom configSchema manifest file-map row from plugin-spec#13697
os-project-manager merged 2 commits into
mainfrom
claude/issue-12690-plugin-spec-phantom-configschema-row

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #12690

What changed

Removed the phantom configSchema row from the manifest file-map in the
objectstack.config.ts example on content/docs/protocol/kernel/plugin-spec.mdx.

     translations: [
       'i18n/**/*.json',
     ],
-    
-    // Configuration schema
-    configSchema: 'src/config.schema.ts',
   },

Three lines, one file, no other change in the diff.

Why the row is phantom, not merely undocumented

packages/spec/src/kernel/manifest.zod.ts declares no configSchema key —
git grep configSchema packages/spec/src/kernel returns nothing at all.

The sharper half: ManifestSchema is not .strict() (the schema says so in
four places, on the tombstoned keys). So an author who copies this example gets
no error whatsoever — the key is silently stripped and src/config.schema.ts
is never loaded by the manifest. A phantom row on a not-strict schema fails
silently by construction, which is why nothing has ever caught it.

The manifest example block carries no os:check marker, so no gate validates its
snippet against the live schema. That is why this survived while the neighbouring
lifecycle and permissions shapes each acquired an explicit note.

Per the triage ruling the row is dropped, not annotated as proposed-shape:
permissions is annotated as proposed because someone intends to build it, and
lifecycle as removed because it once existed. Neither is true here, and the
direction of travel is the opposite of proposed — #11982 ruled the kernel
configSchema retirement.

The real configSchema content survives — proof

The identifier appears on this page meaning two different things. Only the
manifest file-map row was removed. Everything describing the plugin-owned
self-parse pattern is untouched:

Line Surviving content Role
227 config.schema.ts # Configuration schema (Zod) source-tree listing
374 ### Configuration Schema section heading
380 // src/config.schema.ts the file the plugin itself owns
383 export const configSchema = z.object({ the Zod schema
413 export type PluginConfig = z.infer<typeof configSchema>; inferred type
938 configSchema.parse(this.options) best-practice 4, parse in init

configSchema mentions went 4 to 3 on the page; the one that left is the file-map
row. The edit was anchored on the row's position in the file-map — asserted to
be the final entry before that block's closing brace — never on the identifier,
because a grep-and-delete here removes true documentation.

Scope note

The surrounding example keys that ManifestSchema also does not declare
(metadata, config, marketplace, optionalDependencies, peerDependencies,
definePlugin itself) are deliberately disclaimed by the page's top
Callout type="warn" as target/design intent, and by the inline comment on the
snippet. They are documented-as-proposed on purpose, so they are out of scope and
were left alone — no finding filed for them.

Verification

Gate family derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
(the script reads its own change set from the merge base; no hand-rolled path list).
26 families derived. Run on 1515f0a8f, the branch head after syncing main:

  • 25 of 26 green, exit codes captured before any pipe.
  • scripts/check-test-completeness.mjsNOT MEASURED, exit 3
    PREREQUISITE NOT MET. It grades a saved turbo run test log and the family
    list names it with no argument; its own output says this branch is unreachable
    in CI and is "not a red, and there is nothing here to fix".
  • pnpm check:nul-bytes green (7561 files); the edited file self-scanned clean
    for raw control bytes.

Three gates first read NOT MEASURED against missing dist/ output, were rebuilt
(@objectstack/lint, @objectstack/client-react, @objectstack/spec), and then
produced real green measurements: check:doc-formula-expressions,
check:doc-security-posture, check:skill-examples (260 prose examples
type-check across 3 surfaces).

Repo-wide pnpm lint narrowed, and the narrowing is measured rather than
assumed:
eslint's own config restricts every files glob to
{ts,tsx,mts,cts,js,jsx,mjs,cjs}, so .mdx is in no population it lints. Running
eslint content/docs/protocol/kernel/plugin-spec.mdx --no-inline-config --format json
returns 1 result entry, 0 errors, with eslint's own message
File ignored because no matching configuration was supplied. Since the diff
changes exactly one .mdx file and no eslint config, no tsconfig, and no .ts
source, no untouched file's lint verdict can move.

Changeset

No changeset, and the PR carries skip-changeset. The card is docs-only: one file
under content/docs/**, publishing nothing from any package.
scripts/pm/dispatch-gates.mjs states the rule directly — "write one unless this
card is docs-only
" — and scripts/check-empty-changeset.mjs rejects a newly added
empty-frontmatter changeset, so there is no package-less form to write; naming a
package here would emit a release-note row for code that did not change. Precedent
for this exact shape: PR #13337, a docs-only phantom-shape removal under
content/docs/**, carries skip-changeset and added no changeset.

⚠️ Flagging one conflict for the reviewing seat rather than silently choosing: the
dispatch prompt's skip-changeset closed list enumerates docs/adr/**, .claude/**,
scripts/pm/**, tests/workflow and comments — it does not list content/docs/**,
though the criterion stated with it ("publishes nothing from any package") is met.
Reversing this is a one-line change if the seat reads the enumerated list as binding.


Generated by Claude Code

claude added 2 commits August 31, 2026 06:47
… from plugin-spec

The `objectstack.config.ts` example on content/docs/protocol/kernel/plugin-spec.mdx
carried a `configSchema: 'src/config.schema.ts'` row at the tail of its `metadata:`
file-map. `packages/spec/src/kernel/manifest.zod.ts` declares no such key -- and
because `ManifestSchema` is not `.strict()`, an author who copies the example gets
no error at all: the key is silently stripped and the file is never loaded.

Only the manifest file-map row is removed. The page's "Configuration Schema"
section and best-practice 4 (`configSchema.parse(this.options)` in `init`) describe
the plugin-owned self-parse pattern, which is real and is untouched -- the same
identifier means two different things on this page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

content/docs/protocol/kernel/plugin-spec.mdx documents a manifest configSchema file-map key that ManifestSchema never declared

2 participants