Skip to content

feat(spec): retire the inert additionalTypes key from MetadataPluginConfig (#8586, ADR-0049) - #8702

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-8586-retire-additionaltypes
Aug 14, 2026
Merged

feat(spec): retire the inert additionalTypes key from MetadataPluginConfig (#8586, ADR-0049)#8702
os-zhuang merged 5 commits into
mainfrom
claude/issue-8586-retire-additionaltypes

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #8586

Implements the maintainer ruling of 2026-08-14 (verbatim 「同意」, joint with #8421): ADR-0049 disposition remove. MetadataPluginConfig.additionalTypes was declared, authorable, documented on four docs pages as THE way a plugin registers a custom metadata type — and read by nothing. Measured basis re-verified on this tree before implementing: every occurrence is a declaration or a mention, the only production writer of the manager's type registry is setTypeRegistry(DEFAULT_METADATA_TYPE_REGISTRY), declared count == live count (27 == 27). Premise still valid.

Note: #8421 is not addressed here — this card lands first; the refuse-by-static-registry work on #8421 remains open and follows it.

Route: retiredKey() tombstone, not strict deletion

The dispatch prompt presumed a strict object ("authoring it becomes a loud unknown-key refusal"). The tree disagrees: MetadataPluginConfigSchema is a plain z.object, not .strict(), so a plain deletion would be a silent strip — the exact trap the playbook forbids (#3726/#3733, ADR-0104). Per the playbook's route table the removal is a retiredKey() tombstone (the kernel/Manifest:loading precedent, #4914): authoring the key is a tsc error (typed never) and a parse refusal — invalid_type at path additionalTypes, message carrying the full prescription (not unrecognized_keys; tombstones raise invalid_type from z.never(), as alias-integrity.test.ts records). The pin tests assert the strongest envelope this surface has: refusal + issue code + path + prescription text. A status field does not exist on a ZodError issue, so it is deliberately not asserted.

What this PR comprises

  • Tombstone at packages/spec/src/kernel/metadata-plugin.zod.ts, guidance following the five house conventions (no os migrate meta sentence — no conversion covers this surface, see below).
  • ADR-0087 registration, protocol-18 step (post-cut: the refusal ships on 17.x, prescription registers at the 18 boundary — the [finding][spec] memory-driver persistence.path / persistence.key still accept unresolved ${…} placeholders — the #8336 shape one surface over, deliberately outside its connection-material class #8495 / PR feat(spec): refuse ${…} placeholder syntax in memory persistence.path / persistence.key at publish (#8495) #8666 precedent):
    • retired-key entry file 18.kernel__MetadataPluginConfig__additionalTypes.ts (kernel/MetadataPluginConfig:additionalTypes); a new retired-key:18 region was added to RETIRED_KEYS_BY_MAJOR (hand-written markers, generator-filled content);
    • D3 semantic entry 18.metadata-plugin-additional-types-retired.ts;
    • no D2 conversion, deliberately: the conversion chain walks a normalized stack and applyConversionsToStoredItem maps types onto stack collections; a metadata-plugin config is neither (PLURAL_TO_SINGULAR has no plugins entry) — a conversion would be a transform with no seam that ever runs. Same rationale as kernel/Manifest:loading.
    • registry.ts regenerated via gen:migration-registry (85 semantic, 30 retired-key, 53 retired-def); step18 rationale extended (hand-written half).
    • spec-changes.json / docs/protocol-upgrade-guide.md are unchanged, correctly: the projections exclude the uncut major 18 (the on-main [finding][spec] memory-driver persistence.path / persistence.key still accept unresolved ${…} placeholders — the #8336 shape one surface over, deliberately outside its connection-material class #8495 semantic entry is absent from them too); check:spec-changes / check:upgrade-guide green.
  • Generated baselines: authorable-surface/kernel.json row becomes kernel/MetadataPluginConfig:additionalTypes [RETIRED] via gen:schema (tombstone route keeps the row — the dispatch card said the baselines "lose the row", which is the strict-removal shape; [RETIRED] is this route's correct reading). authorable-surface.base.json anchor lags legitimately (informational line, per playbook).
  • Reference page content/docs/references/kernel/metadata-plugin.mdx is pipeline-generated — regenerated via gen:docs, never hand-edited. Its diff includes sibling optionality flips (default-bearing fields now render required): explained and verified by ablation — the old additionalTypes embedded MetadataTypeRegistryEntryBaseSchema (pulling ActionSchema), which made output-shape JSON-Schema emission throw and forced the whole def into the input-shape fallback (x-io: input). With the key tombstoned the def emits output shape like the other ~1460 defs. Ablation proof: restoring the old key and regenerating reverts the page byte-identical to origin/main.
  • Docs: content/docs/plugins/adding-a-metadata-type.mdx — all 4 occurrence sites (TL;DR, built-in-vs-plugin section, schema-wiring note, release checklist) rewritten to how a kind actually enters the live set: as a side effect of registering an item of that kind (SchemaRegistry.registerItem / MetadataManager.register), with registerMetadataTypeSchema for the schema half.
  • Source-comment corrections (comments only, cross-package sanctioned by the ruling): packages/metadata/src/metadata-manager.ts (~2470, false "covers plugin-contributed additionalTypes" claim), packages/metadata-protocol/src/protocol.ts (~4376, kept the real artifact-load half, dropped the phantom), packages/spec/src/kernel/metadata-type-schemas.ts ("register the type as well" note now states the real channel). Additionally two comments in metadata-plugin.zod.ts itself (the MetadataType enum docblock and DEFAULT_METADATA_TYPE_REGISTRY) claimed plugins extend the registry via contributes.kinds — verified false for that registry (registerKind stores kind descriptors as items of the kind type; it does not extend the type registry); corrected in place since they advertise the same phantom growth path on the exact surface being retired.
  • Pin tests additional-types-retirement.test.ts: refusal with code/path/prescription (direct and through the manifest config embed) + control that the same config without the key parses and grows no property. The old spec test that authored the key re-judged: it merely exercised the alias-free full-config parse, so it was re-spelled (key removed) rather than replaced.
  • Changeset: minor + BREAKING annotation + FROM/TO + adr-0087: registered marker (launch-window convention, PR feat(spec): refuse ${…} placeholder syntax in memory persistence.path / persistence.key at publish (#8495) #8666 precedent; check-changeset-no-major green).
  • Liveness ledger: no edit, correctly — check:liveness walks metadata type schemas (listMetadataTypeSchemaTypes); kernel/MetadataPluginConfig is not in that walk and has no ledger row to keep or delete. check:liveness green.
  • Forms / i18n: no *.form.ts input ever spelled this key; no i18n change.

Verification (all at HEAD 54ae32c17, post-merge of origin/main, after the final commit)

  • check:generated 13/13 green (migration-registry, spec-changes, upgrade-guide, skill-docs, skill-refs, react-blocks, authorable-surface, api-surface, export-origins, docs, strictness-ledger, liveness, test-typecheck). api-surface/ unchanged — the tombstone is key-level narrowing, invisible to that snapshot by design; no exported value schema was orphaned (MetadataTypeRegistryEntryBaseSchema keeps its consumer and is module-private).
  • The 7 source audits check:generated names as not-run, run as one group: check:empty-state, check:skill-examples, check:template-manifests, check:variant-docs, check:exported-any, check:dual-source-exports, check:scripts-typecheck — all PASS. check:nul-bytes PASS.
  • Derived via node scripts/pm/dispatch-gates.mjs over the actual changed paths — families beyond the prompt's list, all PASS: check:changeset-gate-self-tests, check:cross-package-test-inputs, check:doc-formula-expressions, check:docs-audit-scope, check:durability-log-level, check:filter-alias-parity, check:merge-driver, check:objectui-changeset, check:quick-reference-counts, check:role-word, check:spec-parsed-alias, check:type-source-resolution, check:query-options-erasure, check:type-check-coverage, check:type-check-debt (after full turbo run build of the packages closure, as lint.yml does), check-adr-0087-registration, check-changeset-no-major, check-empty-changeset, check-dev-prereqs.
  • Tests: @objectstack/spec 10572/10572 (399 files); @objectstack/metadata 603/603 (31 files); @objectstack/metadata-protocol 1317/1317 (89 files). Neither metadata package has a typecheck script — their build (tsup + dts) is the type gate, both green. Pin test 3/3.
  • Reverse verification (fix committed first; predicted red, observed red): restoring the pre-removal key with the registration in place turns gen:schema red at gate (b2) with the exact message — 1 RETIRED_KEYS_BY_MAJOR entr(ies) name a key that is still LIVE: kernel/MetadataPluginConfig:additionalTypes (registered at major 18). Restored from the commit; regeneration reproduces the committed artifacts byte-identically (clean git status).
  • Producer sweep of siblings (read-only): zero additionalTypes authors/writers in /home/user/objectui and /home/user/cloud (control probe confirmed the sweep saw both trees).
  • packages/qa/dogfood: no covers entry references this key (no expression surface on it); the dogfood consumption-radius check was a grep plus the cross-package-test-inputs gate, both clean.

Generated by Claude Code


Generated by Claude Code

@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 14, 2026 3:21pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-protocol, @objectstack/metadata, @objectstack/spec.

107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata-protocol, @objectstack/metadata, packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via packages/metadata, @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/metadata-protocol, @objectstack/metadata, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/permissions/system-context.mdx (via packages/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/metadata, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/metadata-protocol, @objectstack/metadata, @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/metadata-service.mdx (via @objectstack/metadata)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

7 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/metadata, @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/metadata-protocol, @objectstack/metadata, @objectstack/spec)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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/m tests tooling

Projects

None yet

2 participants