Found while measuring objectui's metadata-admin preview read points for the framework liveness sweep objectstack-ai/objectstack#7427. Recording the drift; not fixing it there.
What was measured
At objectui origin/main @ e9ab52f9:
packages/app-shell/src/views/metadata-admin/previews/index.ts:45 — registerMetadataPreview('validation', ValidationPreview)packages/app-shell/src/views/metadata-admin/anchors.ts:347-366 — registerMetadataResource({ type: 'validation', … }) with an object-anchored "Validations" group andcreateFields / createSchema, i.e. a create affordance that routes to metadata/validation/new (console/AppContent.tsx:642)anchors.ts:72-84 — the embedded path, __object_validation with editAs: 'validation' and embeddedPath: 'validations'
At framework origin/main @ dadd1ad0, validation is not a registered metadata kind: it appears in neither METADATA_TYPE_SCHEMAS nor UNREGISTERED_KIND_SCHEMAS in packages/spec/src/kernel/metadata-type-schemas.ts. The framework ledger states the retirement outright (packages/spec/liveness/validation.json_note):
> TYPE-LEVEL GAP CLOSED 2026-08-02 (#4509) by RETIRING THE KIND (ADR-0088), not by building a bridge: a STANDALONE validation item (file *.validation.ts or Studio) never reached any object's write path, because the schema has no object-binding key and — every variant being .strict() — an author could not add one; no merge code existed […] A state machine authored through that door saved cleanly and gated nothing.
Why this matters
The console still offers the door the framework closed. An author who uses the "Validations" group's create affordance authors a standalone item that nothing evaluates — the exact outcome ADR-0088 retired the kind to prevent. anchors.ts:345-346 even carries the comment "usually embedded in the object, but standalone variants do exist", which is no longer true framework-side.
Second-order: ValidationPreview is a well-built renderer (it renders label :131, description :136, tags :167-175, plus per-variant bodies) that the governed path never reaches. Embedded rules go through MetadataDetailDrawer.tsx:129 → EmbeddedItemEditor.tsx, which renders a SchemaForm (:22, :54-62) and never mounts ResourceEditPage's preview tab. So the preview only runs on the retired standalone route.
That combination is why objectstack-ai/objectstack#7427 left validation.label / .description / .tags at dead: the render is real but the read point is not reachable on the path the framework evaluates, and granting live on the strength of a retired door would reproduce the "shipped false signpost" pattern the ledger exists to catch.
Suggested disposition (a judgement call, not a prescription)
Two coherent shapes:
- A — follow the framework. Drop the standalone
validation resource registration and its create affordance; keep the __object_validation embedded anchor. Then either retire ValidationPreview with it, or (better) wire the preview into the embedded editor so the drawer gets the renderer it already has. - B — keep the preview, move it. Same as A but treat wiring
ValidationPreview into EmbeddedItemEditor as the point of the change; that would also re-open the framework ledger rows above as genuinely reachable.
B is the more valuable of the two if someone is going to touch this file at all — the renderer already exists and the embedded path is the one authors actually use.
Provenance
Generated by Claude Code
Found while measuring objectui's metadata-admin preview read points for the framework liveness sweep objectstack-ai/objectstack#7427. Recording the drift; not fixing it there.
What was measured
At objectui
origin/main@e9ab52f9:packages/app-shell/src/views/metadata-admin/previews/index.ts:45—registerMetadataPreview('validation', ValidationPreview)packages/app-shell/src/views/metadata-admin/anchors.ts:347-366—registerMetadataResource({ type: 'validation', … })with anobject-anchored "Validations" group andcreateFields/createSchema, i.e. a create affordance that routes tometadata/validation/new(console/AppContent.tsx:642)anchors.ts:72-84— the embedded path,__object_validationwitheditAs: 'validation'andembeddedPath: 'validations'At framework
origin/main@dadd1ad0,validationis not a registered metadata kind: it appears in neitherMETADATA_TYPE_SCHEMASnorUNREGISTERED_KIND_SCHEMASinpackages/spec/src/kernel/metadata-type-schemas.ts. The framework ledger states the retirement outright (packages/spec/liveness/validation.json_note):> TYPE-LEVEL GAP CLOSED 2026-08-02 (#4509) by RETIRING THE KIND (ADR-0088), not by building a bridge: a STANDALONE
validationitem (file*.validation.tsor Studio) never reached any object's write path, because the schema has no object-binding key and — every variant being.strict()— an author could not add one; no merge code existed […] A state machine authored through that door saved cleanly and gated nothing.Why this matters
The console still offers the door the framework closed. An author who uses the "Validations" group's create affordance authors a standalone item that nothing evaluates — the exact outcome ADR-0088 retired the kind to prevent.
anchors.ts:345-346even carries the comment "usually embedded in the object, but standalone variants do exist", which is no longer true framework-side.Second-order:
ValidationPreviewis a well-built renderer (it renderslabel:131,description:136,tags:167-175, plus per-variant bodies) that the governed path never reaches. Embedded rules go throughMetadataDetailDrawer.tsx:129→EmbeddedItemEditor.tsx, which renders aSchemaForm(:22, :54-62) and never mountsResourceEditPage's preview tab. So the preview only runs on the retired standalone route.That combination is why objectstack-ai/objectstack#7427 left
validation.label/.description/.tagsatdead: the render is real but the read point is not reachable on the path the framework evaluates, and grantingliveon the strength of a retired door would reproduce the "shipped false signpost" pattern the ledger exists to catch.Suggested disposition (a judgement call, not a prescription)
Two coherent shapes:
validationresource registration and its create affordance; keep the__object_validationembedded anchor. Then either retireValidationPreviewwith it, or (better) wire the preview into the embedded editor so the drawer gets the renderer it already has.ValidationPreviewintoEmbeddedItemEditoras the point of the change; that would also re-open the framework ledger rows above as genuinely reachable.B is the more valuable of the two if someone is going to touch this file at all — the renderer already exists and the embedded path is the one authors actually use.
Provenance
_note, permissionrowLevelSecurity.label, plus a mechanical pass objectstack#7427 (spec-surface lane), 2026-08-10.e9ab52f9. Framework SHA measured:dadd1ad0.Generated by Claude Code