Skip to content

apps/console FormPage.buildSections renders an EMPTY section for a spec-legal sections[].group — the third form-section consumer, untouched by objectui#7051 #8641

Description

@os-justin

Found while implementing objectui#7051 (the form.sections[].group reference form on @object-ui/plugin-form). Filed rather than fixed there: it is a different package, a different renderer, and a different code path, so it is out of that card's scope.

What was measured

@objectstack/spec 17.3.0 declares group on FormSectionSchema — a section may point at one of the object's declared fieldGroups instead of enumerating fields (objectstack#13855, ADR-0085 §5). Measured against the installed package on origin/main:

FormSectionSchema.safeParse({ group: 'contact_info' })
  -> ACCEPT  { collapsible: false, collapsed: false, columns: 1, group: 'contact_info' }

apps/console/src/components/FormPage.tsx has its own section builder, independent of @object-ui/plugin-form:

export function buildSections(form: FormViewSpec, objectSchema: ObjectSchemaPayload | null): RenderableSection[] {
  const sections = form.sections ?? form.groups ?? [];
  ...
  for (const entry of sec.fields ?? []) { ... }      // a { group } section has no `fields`
  ...
  return { label: sec.label, ..., fields };          // a { group } section has no `label` either
}

So a spec-legal { group: 'contact_info' } section reaches this builder and produces a section with no label and no fields — it renders nothing, reports nothing, and the members the group declares are simply absent from the console's form page. This is the same silent-drop class objectui#7051 fixed on the plugin-form chain, on the third consumer.

⚠️ How this was established, stated honestly: by reading the source (sec.fields ?? [] cannot produce rows for a section that carries no fields), not by a DOM measurement of the console page. Whoever takes this should reproduce it first — that is cheap here and the reproduction is the acceptance evidence.

Why it is not the same fix

FormPage is not a plugin-form container: it does not go through ObjectForm's dispatcher (where objectui#7051 resolves the reference, once, above the routing fork), and the resolver packages/plugin-form/src/sectionGroups.ts is package-internal — it is not exported from @object-ui/plugin-form's public surface. So the options are a deliberate choice, not a mechanical copy:

  • A. Export the resolver from @object-ui/plugin-form and call it from buildSections — one assembler, one behaviour, at the cost of a new published export (and check-readme-exports follows an export).
  • B. Have buildSections call deriveFieldGroupLayout (ADR-0085 §5) itself. Still the single upstream assembler, no new published surface, but a second adapter onto a section shape.
  • C. Leave it, and record the divergence deliberately — FormPage is a reference-app renderer, not the published one.

⛔ Whatever is chosen, no assembly rule (declared order, empty-group drop, ungrouped trailing bucket, collapse/visibleWhen passthrough) may be re-implemented on the objectui side — that is objectui#7051's and objectstack#13855's standing constraint.

Non-regression axis for whoever takes it

⭐ Not "the form renders" and not "the section is non-empty" — both pass on a builder that drops every group-referenced section, which is today's behaviour. The discriminating assertion is that a group-referenced section renders the members that group declares, asserted against concrete field identifiers, with a second section referencing a different group so a constant-resolution caricature cannot satisfy both.

Refs


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

appsbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatchedpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions