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
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
ObjectFormSchema ↔ @objectstack/spec FormViewSchema alignment (ObjectView form adapter) #2545
Part 2 (form-adapter keys "not in FormViewSchema") turned out to be inaccurate as literally stated — every key buildFormSchema reads is declared on ObjectUI's own ObjectFormSchema. The real, larger gap was the spec-bridge silently dropping spec keys and the legacy groups dead-key, both fixed in fix(spec-bridge/form): stop dropping spec FormViewSchema keys; normalize legacy groups → sections (#2545) #2552; the naming/shape alignment with @objectstack/specFormViewSchema is a protocol matter now carried by framework#2998.
✅ Form bridge no longer drops spec FormViewSchema keys (full passthrough + mapField/mapSection completeness), locked in by the FormViewSpecConformance round-trip test — every spec key must land on the node or be explicitly listed in IGNORED_SPEC_KEYS with a reason.
✅ groups → sections normalized at both consumers (bridge + ObjectForm); ObjectFormSchema.groups is now @deprecated; groups-only metadata renders grouped instead of silently flat.
✅ Key taxonomy ([spec-aligned] / [ObjectUI extension] / [runtime-only]) documented in the type header and in schema-reference.md ("Spec alignment & extension keys").
Remaining (tracked here):
Phase 3 — framework-side spec proposal: structured buttons config (absorbing the showSubmit/submitText family) and defaults/initialValues; bump objectui's @objectstack/spec pin to ^15.0.0 and restore spec installation in CI so tsc catches type drift.
Phase 4 — audit packages/react/components/form/FormRenderer.tsx usage and converge the dual render path onto bridge→ObjectForm (candidate for a separate issue when picked up).
Re-evaluation of the remaining backlog (Phases 3–4)
Evidence: full diff of the published @objectstack/spec 14.6.0 vs 15.0.0, plus two repo-wide audits (dependency state, FormRenderer usage).
Phase 3 — item-by-item verdicts
❌ "Restore spec installation in CI so tsc catches drift" — withdrawn, was based on a wrong premise.@objectstack/spec@^14.6.0 is declared in 14 package.json files, fully pinned in pnpm-lock.yaml (:3993, importer at :1077), and both CI jobs run pnpm install --frozen-lockfile — CI's tsc has always resolved the spec and catches drift. My earlier claim came from inspecting a checkout that had simply never been pnpm installed. Correction noted.
✅ Spec pin bump ^14.6 → ^15.0 — low risk, worth doing. The /ui export-name surface is identical across both versions; exports subpaths unchanged → zero type-level breakage. v15's only major change is ADR-0089 D3a: FormFieldSchema / FormSectionSchema / PageComponentSchema are now .strict() (unknown keys = loud parse error instead of silent strip). When bumping, run example/test metadata through spec validation to catch fixtures carrying undeclared field/section-level keys.
✅ buttons / defaults spec proposal — still needed, now more urgent. In v15, FormViewSchema's top level remains strip-mode, so the showSubmit/submitText family is still silently stripped by spec validation — exactly the "silently inert" shape ADR-0078 forbids. With field/section level now strict, the top level is the last remaining seam for undeclared keys; structuring these into a spec buttons config (and defaults for initialValues) closes it.
New findings from this evaluation
Latent bug — /ui zod schema values are erased at re-export. All ~20 re-export blocks for @objectstack/spec/ui in packages/types/src/index.ts use export type { …Schema } — export type erases values, so importing e.g. DndConfigSchema from @object-ui/types yields undefined at runtime. Only index.ts:948-956 (defineStack etc.) is a real value export. Fix: convert to value exports (the dependency is installed, so this is safe) or drop the schema-name re-exports.
packages/react/src/components/form/FormRenderer.tsx (262 lines) is exported-but-dead public API: zero runtime consumers — the only import in the whole repo is its own test file (27 tests); FieldFactory is captive to it. Functionally it's a degraded duplicate (raw HTML/Tailwind, hard-coded Submit button, no submitBehavior/aria/groups).
Deletion scope: FormRenderer.tsx + FieldFactory.tsx + their tests; two re-exports (components/form/index.ts:9-10, react/src/index.ts:12); docs cleanup (content/docs/core/form-renderer.mdx, schema-renderer.mdx:165 cross-link, components/form/README.md, types/examples/form-renderer-example.ts, three skills guides, two stale app-shell README mentions). Zero consumers → hard delete + CHANGELOG breaking note; no migration needed.
Side finding (separate issue candidate):SpecBridge itself is never instantiated in production — the live form path is app-shell RecordFormPage → ObjectForm directly, and plugin-form registers the bare 'form' type on ComponentRegistry (spec JSON reaches ObjectForm via SchemaRenderer without the bridge). The bridge is currently test-only plumbing; whether to wire it into the runtime path or lean on registry-direct rendering is an architecture question worth its own issue — not mixed into this one.
Suggested implementation split
PR A (objectui): spec pin → ^15.0.0 (14 package.json + lockfile) + fix the /ui schema value-export erasure + validate fixtures under v15 strict mode.
PR B (objectui): delete FormRenderer/FieldFactory + docs cleanup.
framework: proposal issue — structured buttons + defaults on FormViewSchema, and add view to the liveness ledger.
Phase 3 framework proposal filed: objectstack-ai/objectstack#2998 — structured buttons/defaults on FormViewSchema + enrolling view in the liveness ledger.
Two corrections vs. my earlier comment, after auditing the actual framework source:
FormViewSchema is strip-mode, not .strict() — only the leaf FormFieldSchema/FormSectionSchema went strict in v15 (ADR-0089 D3a). So adding buttons/defaults is a clean additive change, but the container won't reject today's invented keys — it silently strips them.
ADR-0078 tension: the framework has no runtime consumer of FormViewSchema (it's purely objectui's protocol contract). Adding an authorable buttons block that nothing reads is itself "parsed-but-inert" — the thing ADR-0078 forbids. So Track A must co-land with the objectui ObjectForm wiring (cross-repo) or be marked [EXPERIMENTAL — not enforced]. Captured in the framework issue.
view-liveness enrollment (Track B) is confirmed applicable — view is a governed-eligible metadata type (view: ViewSchema in BUILTIN_METADATA_TYPE_SCHEMAS) that's simply not yet in the GOVERNED rollout list — but it's a standalone effort classifying the whole ViewSchema surface, not a same-PR adjunct.
Phase 4 landed via #2560 (merged as f94905d): FormRenderer / FieldFactory and their @object-ui/react exports removed, docs + stale app-shell/skills guidance cleaned up. The dual form render path is gone — ObjectForm (plugin-form) is now the single path.
The objectui-side of Phase 3 — bump @objectstack/spec pin to ^15 and the /ui zod-schema re-export question — is deliberately not done yet because it involves a design call, not a mechanical fix:
packages/types/src/index.ts re-exports the whole @objectstack/spec/ui surface with export type { …Schema }, so the zod values are erased — importing a …Schema from @object-ui/types yields undefined at runtime. "Fixing" it by converting to value exports would give @object-ui/types a real runtime dependency on @objectstack/spec (bundle-size / eager-load impact). The alternative — dropping the schema-name re-exports entirely (keep them type-only) — may be the intended design. This is a judgment call for a maintainer rather than something to change unilaterally.
The spec ^15 pin bump is low-risk on the type surface (identical /ui exports) but should ride together with validating fixtures under v15's new field/section .strict() mode.
The objectui-side Phase 3 decision point is now tracked in #2561 (/ui re-export shape + spec ^15 pin bump) — kept out of a mechanical PR because option (a) vs (b) for the value-erased schema re-exports is a maintainer call. That leaves #2545 with only the cross-repo framework work outstanding (framework#2998); the objectui phases (1, 2, 4) are all merged.
Activity
fix(spec-bridge/form): #2545 stop dropping spec FormViewSchema keys; …
os-zhuang commentedon Jul 16, 2026
Phase 1 + 2 landed via #2552 (merged as
ddcc7d6):FormViewSchemakeys (full passthrough +mapField/mapSectioncompleteness), locked in by theFormViewSpecConformanceround-trip test — every spec key must land on the node or be explicitly listed inIGNORED_SPEC_KEYSwith a reason.groups → sectionsnormalized at both consumers (bridge + ObjectForm);ObjectFormSchema.groupsis now@deprecated; groups-only metadata renders grouped instead of silently flat.ObjectView.buildFormSchemaforwardsform.sections.[spec-aligned]/[ObjectUI extension]/[runtime-only]) documented in the type header and inschema-reference.md("Spec alignment & extension keys").Remaining (tracked here):
buttonsconfig (absorbing theshowSubmit/submitTextfamily) anddefaults/initialValues; bump objectui's@objectstack/specpin to ^15.0.0 and restore spec installation in CI so tsc catches type drift.packages/react/components/form/FormRenderer.tsxusage and converge the dual render path onto bridge→ObjectForm (candidate for a separate issue when picked up).Generated by Claude Code
os-zhuang commentedon Jul 16, 2026
Re-evaluation of the remaining backlog (Phases 3–4)
Evidence: full diff of the published
@objectstack/spec14.6.0 vs 15.0.0, plus two repo-wide audits (dependency state, FormRenderer usage).Phase 3 — item-by-item verdicts
❌ "Restore spec installation in CI so tsc catches drift" — withdrawn, was based on a wrong premise.
@objectstack/spec@^14.6.0is declared in 14 package.json files, fully pinned inpnpm-lock.yaml(:3993, importer at :1077), and both CI jobs runpnpm install --frozen-lockfile— CI's tsc has always resolved the spec and catches drift. My earlier claim came from inspecting a checkout that had simply never beenpnpm installed. Correction noted.✅ Spec pin bump ^14.6 → ^15.0 — low risk, worth doing. The
/uiexport-name surface is identical across both versions; exports subpaths unchanged → zero type-level breakage. v15's only major change is ADR-0089 D3a:FormFieldSchema/FormSectionSchema/PageComponentSchemaare now.strict()(unknown keys = loud parse error instead of silent strip). When bumping, run example/test metadata through spec validation to catch fixtures carrying undeclared field/section-level keys.✅
buttons/defaultsspec proposal — still needed, now more urgent. In v15,FormViewSchema's top level remains strip-mode, so theshowSubmit/submitTextfamily is still silently stripped by spec validation — exactly the "silently inert" shape ADR-0078 forbids. With field/section level now strict, the top level is the last remaining seam for undeclared keys; structuring these into a specbuttonsconfig (anddefaultsforinitialValues) closes it.New findings from this evaluation
/uizod schema values are erased at re-export. All ~20 re-export blocks for@objectstack/spec/uiinpackages/types/src/index.tsuseexport type { …Schema }—export typeerases values, so importing e.g.DndConfigSchemafrom@object-ui/typesyieldsundefinedat runtime. Onlyindex.ts:948-956(defineStacketc.) is a real value export. Fix: convert to value exports (the dependency is installed, so this is safe) or drop the schema-name re-exports.liveness/*.json, enforce-or-remove per ADR-0049) — but there is noview.json: view/form properties are entirely outside liveness governance. That's the systemic root cause that let the viewschema key drift: bulkActions/batchActions + ObjectView form-adapter keys not in FormViewSchema #1763 / ObjectFormSchema ↔ @objectstack/spec FormViewSchema alignment (ObjectView form adapter) #2545 class of drift survive. The framework proposal should include bringing views into the ledger.Phase 4 — verdict upgraded: delete, don't converge
packages/react/src/components/form/FormRenderer.tsx(262 lines) is exported-but-dead public API: zero runtime consumers — the only import in the whole repo is its own test file (27 tests);FieldFactoryis captive to it. Functionally it's a degraded duplicate (raw HTML/Tailwind, hard-coded Submit button, nosubmitBehavior/aria/groups).Deletion scope:
FormRenderer.tsx+FieldFactory.tsx+ their tests; two re-exports (components/form/index.ts:9-10,react/src/index.ts:12); docs cleanup (content/docs/core/form-renderer.mdx,schema-renderer.mdx:165cross-link,components/form/README.md,types/examples/form-renderer-example.ts, three skills guides, two stale app-shell README mentions). Zero consumers → hard delete + CHANGELOG breaking note; no migration needed.Side finding (separate issue candidate):
SpecBridgeitself is never instantiated in production — the live form path is app-shellRecordFormPage→ObjectFormdirectly, and plugin-form registers the bare'form'type onComponentRegistry(spec JSON reaches ObjectForm via SchemaRenderer without the bridge). The bridge is currently test-only plumbing; whether to wire it into the runtime path or lean on registry-direct rendering is an architecture question worth its own issue — not mixed into this one.Suggested implementation split
/uischema value-export erasure + validate fixtures under v15 strict mode.buttons+defaultsonFormViewSchema, and addviewto the liveness ledger.Generated by Claude Code
os-zhuang commentedon Jul 16, 2026
Phase 3 framework proposal filed: objectstack-ai/objectstack#2998 — structured
buttons/defaultsonFormViewSchema+ enrollingviewin the liveness ledger.Two corrections vs. my earlier comment, after auditing the actual framework source:
FormViewSchemais strip-mode, not.strict()— only the leafFormFieldSchema/FormSectionSchemawent strict in v15 (ADR-0089 D3a). So addingbuttons/defaultsis a clean additive change, but the container won't reject today's invented keys — it silently strips them.FormViewSchema(it's purely objectui's protocol contract). Adding an authorablebuttonsblock that nothing reads is itself "parsed-but-inert" — the thing ADR-0078 forbids. So Track A must co-land with the objectuiObjectFormwiring (cross-repo) or be marked[EXPERIMENTAL — not enforced]. Captured in the framework issue.view-liveness enrollment (Track B) is confirmed applicable —viewis a governed-eligible metadata type (view: ViewSchemainBUILTIN_METADATA_TYPE_SCHEMAS) that's simply not yet in theGOVERNEDrollout list — but it's a standalone effort classifying the wholeViewSchemasurface, not a same-PR adjunct.Generated by Claude Code
remove(react): #2545 drop unused FormRenderer/FieldFactory duplicate …
os-zhuang commentedon Jul 16, 2026
Phase 4 landed via #2560 (merged as
f94905d):FormRenderer/FieldFactoryand their@object-ui/reactexports removed, docs + stale app-shell/skills guidance cleaned up. The dual form render path is gone —ObjectForm(plugin-form) is now the single path.Status of #2545
groups→sectionsbuttons/defaults+ enrollviewin liveness ledger)Still open (needs a decision, not yet actioned)
The objectui-side of Phase 3 — bump
@objectstack/specpin to ^15 and the/uizod-schema re-export question — is deliberately not done yet because it involves a design call, not a mechanical fix:packages/types/src/index.tsre-exports the whole@objectstack/spec/uisurface withexport type { …Schema }, so the zod values are erased — importing a…Schemafrom@object-ui/typesyieldsundefinedat runtime. "Fixing" it by converting to value exports would give@object-ui/typesa real runtime dependency on@objectstack/spec(bundle-size / eager-load impact). The alternative — dropping the schema-name re-exports entirely (keep them type-only) — may be the intended design. This is a judgment call for a maintainer rather than something to change unilaterally./uiexports) but should ride together with validating fixtures under v15's new field/section.strict()mode.Leaving these for maintainer direction.
Generated by Claude Code
os-zhuang commentedon Jul 16, 2026
The objectui-side Phase 3 decision point is now tracked in #2561 (
/uire-export shape + spec ^15 pin bump) — kept out of a mechanical PR because option (a) vs (b) for the value-erased schema re-exports is a maintainer call. That leaves #2545 with only the cross-repo framework work outstanding (framework#2998); the objectui phases (1, 2, 4) are all merged.Generated by Claude Code
Resolve merge conflicts for #2575 (merge main into claude/github-issu…
fix(react): carry the 18 form-view spec keys the bridge silently dropped
fix(react): carry the 18 form-view spec keys the bridge silently drop…