Uh oh!
There was an error while loading. Please reload this page.
fix(app-shell, console): one derived declaration for FormSectionSpec / FormViewSpec - #5653
Merged
Merged
Conversation
The file header promised `FormSpec.contract.test.ts`. No such file exists — the pins live in `form-spec.containers.test.tsx` (it renders, so it is `.tsx`) and, on the console side, `FormPage.viewSpec.test.ts`. A cross-reference to a file that is not there is the same unverifiable-claim shape this file exists to close, one level up. Also adds the changeset this change owed: `check-changeset-presence.mjs` named both `@object-ui/app-shell` and `@object-ui/console` as released packages with changed source and no declaration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012u2pRjcqAYtoEjgr3wwhnK
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-sales
marked this pull request as ready for review
August 22, 2026 01:13
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#5596
The two form container contracts now have ONE declaration each, derived from
@objectstack/spec, andapps/consolereads them instead of its own copies.#5542 converged the leaf of this contract (
FormFieldSpec) and deliberately left the twocontainers above it.
FormSectionSpecandFormViewSpecwere each hand-declared twice underthe same names — once in
packages/app-shell'sSchemaForm.tsx, once inapps/console'sFormPage.tsx. Unlike the leaf, whose console copy was a clean subset, these two had alreadydrifted in both directions, so neither was a subset of the other and there were two live
answers to "what may an author write".
The drift is decided by the contract, not by picking a side
FormSectionSpec.columns'1'|'2'|'3'|'4'; app-shell took numbers onlyFormSectionSchema.columnsunionsz.enum(['1','2','3','4'])with the four numeric literals, folded to a number by its own transform. app-shell's copy was rejecting metadata the platform accepts — #5040's symptom, not a deliberate narrowing.FormViewSpec.labelFormViewSchemarejects it (unrecognized_keys, measured against the installed@objectstack/spec17.0.0) — a form config is titled, not labelled.description/visibleWhen/visibleOn/name/panelabel's answer is the interesting one: the value that read actually finds is the view'sidentity label, which arrives on the
ExpandedViewItemenvelope (#2208) or beside the configon a flattened runtime overlay (
VIEW_METADATA_MEMBERS.formOverlay). So it is declared onFormPage.tsx's ownFormViewBody, next to the body it unwraps — not smuggled onto the formcontract.
Derived with named narrowings, not restated
Both types are
Omit<…>narrowings of the spec's ownFormSection/FormView— the repo'ssanctioned form for a spec-shaped local type (
scripts/check-spec-symbol-derivation.mjs).Every key the two layers agree on comes from the spec and cannot fall behind it; the four
deliberately-narrower positions are each named in an
Omitlist and restated once next to itsreason:
fieldskeeps the converged 26-key leaf (deriving it would silently re-open #5542),and
label/description/visibleWhen/visibleOnkeep the shapes this repo's renderersand evaluators actually consume rather than the spec's
I18nLabelandExpressionInput.apps/console'ssubmitBehaviorunion — previously hand-written under the comment "Mirrorsthe spec FormView.submitBehavior union" — is now read back off the shared type, making the
mirror structural. The import is
import type, soform-spec.tsstill pulls in nothing atruntime.
Verification
All of the below on
a2664404c, the branch head.Both halves are pinned, on both sides.
form-spec.containers.test.tsx(app-shell) andFormPage.viewSpec.test.ts(console) each pin (a) that the non-narrowed half really is thespec's symbol, and (b) that every narrowing still refuses the arm it means to refuse. The
console pins read both types back out of the exported
buildSectionssignature rather thannaming them, so a re-inlined local copy fails even if it agrees on every key the day it is
written. Liveness controls: the removed copies are pinned NOT equal to the shared types (so the
Equalhelper is proven to still discriminate),RenderableSectionis pinned not equal either,and an undeclared key is still rejected (so the derivation smuggled in no index signature).
Each pin was measured capable of failing — a green type-check is otherwise
indistinguishable from one that never saw the file. Both probes restored via
trap:'label'fromSectionNarrowed(mutation confirmed on disk bygrep -cxF, 1→0 old / 0→1 new):type-checkwent red,form-spec.containers.test.tsx(75,5): error TS2344: Type 'false' does not satisfy the constraint 'true'.buildSections' parameter from the shared type:type-checkwent red,FormPage.viewSpec.test.ts(78,35): error TS2344: Type 'false' does not satisfy the constraint 'true'.Runs (
distrebuilt first — the stalediststill carried the old hand-writteninterfaces, so nothing could be judged before
pnpm --filter '@object-ui/app-shell...' build,and the new derived types were confirmed present in
dist/index.d.tsafterwards):pnpm --filter @object-ui/app-shell type-check→ exit 0 (tsc --noEmit && tsc -p tsconfig.test.json)pnpm --filter @object-ui/console type-check→ exit 015 passed (15)/166 passed (166)(SchemaForm + form-spec set),and
9 passed (9)/120 passed (120)(console FormPage suite).check:spec-symbols✅,check:control-bytes✅,check:self-import✅,check:esm-specifiers✅,check:phantom-deps✅,check:published-dist✅,check-changeset-presence✅,check-changeset-no-major✅ (each quoting its own verdictline, not a bare
$?).--no-inline-configon all 7 changed source files: 0 errors. Warning count wentdown 36 → 35 against the
origin/mainbaseline of the same two files (the removedas any).Declared narrowing. The derived superset for app-shell is a 94-file reverse-import closure
seeded at the four changed modules; that run was killed by the container's 10-minute foreground
cap under load average 10.87 from concurrent work, and produced no verdict. It was narrowed by
derivation, not by dropping files: every one of the 215 changed lines in
packages/app-shell/srcis a comment, an
import type/export type, or an interface/type declaration — mechanicallyclassified, with the only 6 residual lines being
export type {}members and& Omit<…>continuations. TypeScript erases all of them, so no app-shell runtime bytes change and the
tests that reach a changed module only through a barrel cannot observe this diff. The 15-file
run above is the subject-scoped remainder. CI runs the full farm regardless.
Scope
packages/react's spec bridge holds a third hand-written mirror of this sameFormViewSchemacontract, already drifted oncolumns,dependsOnandvisibleWhen. It wasoutside this card's fence and is filed unassigned as #5652 — not fixed here.
Generated by Claude Code