You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The objectui work reconciled the renderer-side key drift (bulkActions/batchActions, groups→sections) and classified every ObjectFormSchema key as [spec-aligned] / [ObjectUI extension] / [runtime-only]. That surfaced a residue that can only be closed here, in the spec.
Problem
ObjectView/ObjectForm in objectui read a family of form keys that do not exist in FormViewSchema (packages/spec/src/ui/view.zod.ts, FormViewSchema L832-929): showSubmit, submitText, showCancel, cancelText, showReset, initialValues (plus renderer-only className, fields, customFields). This repo's own audit already diagnosed it verbatim (docs/audits/2026-06-viewschema-property-liveness.md:25). These are renderer-invented surface with no spec backing — serializable form config that belongs in the protocol but isn't in it.
FormViewSchema is strip-mode (not .strict() — unlike the leaf FormFieldSchema/FormSectionSchema which are .strict() per ADR-0089 D3a, view.zod.ts L773/L810). So today these keys are silently stripped by a spec .parse() — the "parsed → silently inert" shape ADR-0078 prohibits.
Because the container is strip-mode, this is purely additive (minor/patch changeset, no tombstone). The wizard nextText/prevText pair and showStepIndicator (already in spec) can be folded into buttons or left as-is — open question.
⚠️ ADR-0078 constraint (must be resolved before merge): the framework itself has no runtime consumer of FormViewSchema — it's the protocol contract objectui renders. Adding an authorable buttons block that no code reads is itself parsed-but-inert, i.e. the exact thing ADR-0078 forbids. So Track A must land in one of two shapes:
(preferred) co-landed with the objectui renderer wiring — objectui's ObjectForm reads schema.buttons.* / schema.defaults instead of its invented showSubmit/submitText/initialValues. Cross-repo, two worktrees.
(fallback) marked [EXPERIMENTAL — not enforced] in the .describe() until the objectui side lands, per ADR-0078's escape hatch.
Note submitBehavior itself is currently classified dead (no renderer consumer) in the audit (L20) — worth wiring alongside, or the new block sits next to already-inert surface.
Track B: enroll view in the liveness ledger (separate, larger)
viewis a governed-eligible metadata type (view: ViewSchema in BUILTIN_METADATA_TYPE_SCHEMAS, packages/spec/src/kernel/metadata-type-schemas.ts:78) — it round-trips through /api/v1/meta/types/:type and Studio admin forms. It is simply not yet in the GOVERNED rollout (packages/spec/scripts/liveness/check-liveness.mts:56; README lists it as rollout-pending, liveness/README.md:208). That rollout gap is the systemic reason the #1763/#2545 class of drift survived undetected.
Enrolling it: add 'view' to GOVERNED, --dump view, and author packages/spec/liveness/view.json classifying every top-level prop of ViewSchema (list/form/listViews/formViews/protection; the gate drills one level via children, so FormViewSchema's props — including a new buttons — classify under form.children.*). The existing audit already pre-computed much of the live/dead split and would seed view.json. This is a standalone effort, not a same-PR adjunct to Track A — flagging so it's scoped as its own PR.
Follow-up to the viewschema property-liveness audit (
docs/audits/2026-06-viewschema-property-liveness.md, theframework#1890line) and its objectui-side resolution (objectstack-ai/objectui#1763 → #2545, PR objectstack-ai/objectui#2552).The objectui work reconciled the renderer-side key drift (
bulkActions/batchActions,groups→sections) and classified everyObjectFormSchemakey as[spec-aligned]/[ObjectUI extension]/[runtime-only]. That surfaced a residue that can only be closed here, in the spec.Problem
ObjectView/ObjectFormin objectui read a family of form keys that do not exist inFormViewSchema(packages/spec/src/ui/view.zod.ts,FormViewSchemaL832-929):showSubmit,submitText,showCancel,cancelText,showReset,initialValues(plus renderer-onlyclassName,fields,customFields). This repo's own audit already diagnosed it verbatim (docs/audits/2026-06-viewschema-property-liveness.md:25). These are renderer-invented surface with no spec backing — serializable form config that belongs in the protocol but isn't in it.FormViewSchemais strip-mode (not.strict()— unlike the leafFormFieldSchema/FormSectionSchemawhich are.strict()per ADR-0089 D3a, view.zod.ts L773/L810). So today these keys are silently stripped by a spec.parse()— the "parsed → silently inert" shape ADR-0078 prohibits.Proposal — two tracks
Track A: add structured
buttons+defaultstoFormViewSchema(additive, non-breaking)A new optional top-level key alongside
submitBehavior(view.zod.ts L912-925). Sketch:Because the container is strip-mode, this is purely additive (minor/patch changeset, no tombstone). The wizard
nextText/prevTextpair andshowStepIndicator(already in spec) can be folded intobuttonsor left as-is — open question.FormViewSchema— it's the protocol contract objectui renders. Adding an authorablebuttonsblock that no code reads is itself parsed-but-inert, i.e. the exact thing ADR-0078 forbids. So Track A must land in one of two shapes:ObjectFormreadsschema.buttons.*/schema.defaultsinstead of its inventedshowSubmit/submitText/initialValues. Cross-repo, two worktrees.[EXPERIMENTAL — not enforced]in the.describe()until the objectui side lands, per ADR-0078's escape hatch.Note
submitBehavioritself is currently classified dead (no renderer consumer) in the audit (L20) — worth wiring alongside, or the new block sits next to already-inert surface.Track B: enroll
viewin the liveness ledger (separate, larger)viewis a governed-eligible metadata type (view: ViewSchemainBUILTIN_METADATA_TYPE_SCHEMAS,packages/spec/src/kernel/metadata-type-schemas.ts:78) — it round-trips through/api/v1/meta/types/:typeand Studio admin forms. It is simply not yet in theGOVERNEDrollout (packages/spec/scripts/liveness/check-liveness.mts:56; README lists it as rollout-pending,liveness/README.md:208). That rollout gap is the systemic reason the #1763/#2545 class of drift survived undetected.Enrolling it: add
'view'toGOVERNED,--dump view, and authorpackages/spec/liveness/view.jsonclassifying every top-level prop ofViewSchema(list/form/listViews/formViews/protection; the gate drills one level viachildren, soFormViewSchema's props — including a newbuttons— classify underform.children.*). The existing audit already pre-computed much of the live/dead split and would seedview.json. This is a standalone effort, not a same-PR adjunct to Track A — flagging so it's scoped as its own PR.Suggested sequencing
@objectstack/specpin to ^15 + fix the/uizod-schema value-export erasure (tracked in ObjectFormSchema ↔ @objectstack/spec FormViewSchema alignment (ObjectView form adapter) objectui#2545).buttons/defaults+ objectuiObjectFormwiring, so neither side is inert.Grounding ADRs:
0078-no-silently-inert-metadata,0049-no-unenforced-security-properties,0050-form-layout-vs-presentation,0089-unify-visibility-predicate-naming. Refs objectstack-ai/objectui#2545, objectstack-ai/objectui#1763.