Repository navigation
feat(types,plugin-form)!: the grid's sort_field is declared, and a detail's sort field is derived only (objectui#11070 round 9) - #11376
Conversation
…tail's sort field is derived only (objectui#11070 round 9) GridFieldMetadata declares sort_field, the child field GridField stamps with each row's index on every change, so GridField reads its config as GridFieldMetadata alone and UndeclaredGridKeys is gone. MasterDetailDetailConfig loses its authored sortField override (0 writers in either repository, no spec carrier). MasterDetailForm hands the grid the sort field deriveDetail picks, carried on the internal per-detail entry; the `?? derived.sortField` bridge is removed. The 11144 "authored sort field wins" row retires with the member; the 8071 members pin is re-counted with a compile-time member list, a refusal line and a runtime absence row. grid.mdx documents sort_field and drops the false "Pagination Preview" Features bullet. Dated notes on the two pending changesets the retirement makes false. Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh Co-authored-by: Claude <noreply@anthropic.com>
Takes c82ff39 (objectui#11347, PR #11360), which touches none of this branch's files. Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ 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
|
Takes 20d23be, which carries PR #11335 (objectui#11168 slice 3), so the object-master-detail-form.details parity row can be patched on this branch (seat answer A). The merge touches none of this branch's files. Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh Co-authored-by: Claude <noreply@anthropic.com>
…what round 9 left (objectui#11070 round 9, seat answer A) The object-master-detail-form.details MEMBER_PINS row's pins prose named `sortField` as a renamed member and counted twelve members. It now says four members reach the grid renamed, beside `columns` and the derived `sort_field`, and counts eleven. Nothing else in the parity file changes. The 8071 pin's fully configured `sortField` check moves from row 2 into row 2c, so row 2 again carries exactly the two off-list members the parity row describes, and the check keeps its coverage. Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh Co-authored-by: Claude <noreply@anthropic.com>
✅ 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
|
Refs #11070
Clause-②: yes (narrowing).
MasterDetailDetailConfig.sortFieldretires, andGridFieldMetadatagainssort_field. It is priced in the changeset.Round 9 of objectui#11070: the seat's answer B on
sort_field(5928627070), plusgrid.mdx's Features prose. Claim5929173058; dev sessionsession_01TdiauJaVCHuj45EzZGUxHh. DRAFT: no ready, no enqueue.What changes
sort_fieldis declared (@object-ui/types).GridFieldMetadata.sort_field?: string. Its JSDoc says what it does (the CHILD field the grid stamps with each row's index on every change, so a drag-reorder persists; not one of the columns) and who produces it (deriveDetailin@object-ui/plugin-form, throughMasterDetailForm).GridFielddropsUndeclaredGridKeysand reads its config asPartialofGridFieldMetadataalone, so every key it reads is declared there (@object-ui/fields, comments and one type annotation; no runtime change).@object-ui/plugin-form).MasterDetailDetailConfighas nosortFieldmember. The derived value travels on the form's internal per-detail record (DetailEntry.sortField, beside the existing internalamountFieldDef), set only fromderived.sortField, and the grid config readssort_field: entry.sortField. Thed.sortField ?? derived.sortFieldbridge is gone from both derive branches. The amount override (amountField) is untouched.DetailEntryand not a second config type: the authored object is spread into the resolved config ({ ...d, … }), and a fully configured detail keeps it as is. A resolved-config type that carriedsortFieldwould therefore still carry a stray authoredsortFieldat runtime on that path, which is the dual read this round removes. OnDetailEntrythe field has one writer, the derivation.grid.mdx. The typed fence writessort_field: 'position', and the field-level key list documents it the way round 8 documentedtotal_fieldandadd_label. The Features list was audited bullet by bullet againstGridField(below).position/ amount rows stay green. The 8071 members pin is re-counted and re-pointed: header prose (eleven members, four renamed on the way,sort_fieldderived), row 2 withsortFieldmoved to the off-list set (not read), a new row 2c (derived pick vs a writtensortField, with a lit control), and a compile-time block (an exactkeyof MasterDetailDetailConfiglist, a@ts-expect-errorrefusal ofsortField, and a lit control).GridField.fieldKeys-11070gains asort_fielddrag-reorder row and its no-key control, and itsdeclaredfixture writessort_field..changeset/11070-grid-sort-field-round9.md:@object-ui/typesminor (one new optional member, a feature),@object-ui/plugin-formminor (a published member retires: breaking, priced minor under the fixed group's policy, stated),@object-ui/fieldspatch (no runtime change). Dated, append-only notes on the two pending changesets this round makes false:11070-grid-field-keys-round8("sort_field… stays read and undeclared") and11144-inline-columns-sort-amount("or a detail's ownamountField/sortFieldstill wins").The
sortFieldcensus (measured first)objectui base
1a88ce22(exact-wordgit grep -w), objectstackorigin/maine952cff5(same query; controlamountFieldhits 12 files there).deriveDetail(plugin-form/src/deriveMasterDetail.ts)position/sort_order/sequence/line_no/line_number/sortfieldos migrate metaconversionssortFieldandsort_fieldboth)attachInlineSubforms(app-shell)subforms[]childObject/relationshipField/inlineMode/title/columns/amountField; nosortFieldsubformstypessortFieldmemberobject-master-detail-formregistrationinputs(plugin-form/src/index.tsx)details: array, no memberssortField: 'line_no'sortField: 'position'as a memberMasterDetailDetailConfig.sortFieldMasterDetailFormresolve effect, both derive branchesd.sortField ?? derived.sortFieldderived.sortField, onDetailEntryMasterDetailFormgrid configsort_field: d.sortFieldsort_field: entry.sortFieldMasterDetailForm, fully configured detail (no derive)sortFieldonlyGridFieldcfg.sort_fieldUndeclaredGridKeysGridFieldMetadata.sort_fieldobjectui#11144's thread names no user of the authored override: the issue body says
attachInlineSubformscarries onlyinlineColumnsandinlineAmountField, and the claim's "an authoredamountField(inlineAmountField) orsortFieldstill wins" states a symmetry, not a writer.grid.mdxFeatures auditGridFieldrows.mapin both the read-only and editable bodies), and no "Showing" text exists in the widgetdate/datetime/time,fileandlookupcells are formatted (probe below)overflow-x-auto, per-type minimum widths)M3 (
scripts/measure-strict-authoring-face.mjs --json, types dist built)1a88ce225376e31a(this diff)Only
rendererMentionsOfUndeclaredKeys(a raw word count over renderer sources:changeandkeyeach one lower,fieldandschemaeach one higher, from this diff's comments) andunloadableModules(environmental: app-shell unbuilt at base) differ. H3 holds.Ablations (predictions written before each run; every mutation through objectstack
scripts/ablation-replace.mjs, anchor hit as declared, blob changed, restored to the HEAD blob withgit diff HEADempty)sort_fieldread (the member deleted fromGridFieldMetadata, types rebuilt; dist marker 1 to 0). Predicted and observed: fieldstsc --noEmitTS2339 oncfg.sort_field; fieldstsc -p tsconfig.test.jsonTS2353 on thedeclaredfixture and ongrid({ sort_field });check:doc-snippets1 failed block,grid.mdxTS2353sort_field. Restore leg: types rebuilt, dist marker back to 1,git status --porcelainempty.sortFieldtype-checking again (sortField?: string;planted back onMasterDetailDetailConfig). Predicted and observed: plugin-formtsc --noEmitgreen;tsc -p tsconfig.test.jsonexactly 2 errors in the 8071 file, TS2322 on the member list and TS2578 on the now-unused@ts-expect-error.??bridge restored (bothsortField: derived.sortField,sites to(d as any).sortField ?? derived.sortField). Predicted and observed over the three touched test files: 1 failed, 24 passed; the failure is row 2c,expected 'line_no' to be 'position'.grid.mdx(the "Showing X of Y" pagination claim). Predicted and observed:check:doc-snippets,check:doc-fences,docs:check-links,check:doc-typesandcheck:doc-example-idsall green. No gate can see a prose bullet; this round's correction is held by review only.Local verification (final head
2c59d3b5, the merge oforigin/mainc82ff391on top of5376e31a)check-doc-snippet-types --build-filterclosure,turbo --concurrency=2, 35 of 35 tasks.type-checkgreen for@object-ui/types,@object-ui/fieldsand@object-ui/plugin-form(eachtsc --noEmitplus its test project;--listFilesshows the touched test files are in those programs). The type-checker set is these three:MasterDetailDetailConfigis referenced only inside plugin-form (a comment in anapps/consoletest names it), andGridFieldMetadatagains one optional member, which no consumer can break.--maxWorkers=2, through the lock):packages/plugin-form/159 files, 1836 passed and 1 skipped;packages/types/plus everyGridField*/LineItems*test, 325 files and 8103 tests passed.check:doc-snippets(768 of 768 blocks),check:doc-fences,docs:check-links,check:control-bytes,check:changeset-claims,check:pending-changeset-literals,check-changeset-presence,changeset:check,check-changeset-overwrite(it reports the two dated notes, its case 2),check:new-line-citations(0 new),check:test-path-roots,check:doc-types,check:doc-example-ids,check:vi-mock-specifiers,check:readme-exports,check-type-check-coverage.check-governed-queue-guard --test: NOT GOVERNED.6357-basechema-bind-declarationongrid.mdx,6625-retire-fieldmeta-decimalsonGridField.tsx). Both paragraphs were read and still hold.eslint --no-inline-config --format json) over the 6 changed ts/tsx files: 0 errors, 68 warnings, the same per-file warning counts as the base blobs. Population: the config's**/*.{ts,tsx}blocks (the.mdxand.mdfiles match none). File count 6, read from the json. Invariance: noparserOptions.projectorprojectService, and no rule ineslint-rules/reads the filesystem, so this diff cannot move a verdict on an untouched file.Hypotheses
deriveDetailand two test fixtures.Stop condition reached: the
object-master-detail-form.detailsparity row (excluded file, PR #11335)apps/console/src/__tests__/registry-inputs-spec-parity.test.tsis not touched. ItsMEMBER_PINS['object-master-detail-form.details']row stays mechanically green (the locator needs only the pin file to exist and to name the block and the key). Itspinsprose, though, is now false in two places: "five members reach the grid through ONE hand-written object and four are RENAMED on the way (sortFieldtosort_field, …)" and "names five of the twelve members the renderer reads". The brief says to stop and report before that row changes, so the row is reported, not edited, and the dev report puts it to the seat with options.Acceptance notes (not this round's scope)
GridFieldformats onlydate/datetime/time,fileandlookupcells. A scratch probe (uncommitted, removed) rendered one row{ amount: 1234.5, status: 'paid', qty: 1234.5 }withcurrency,select(option labelPaid) andnumbercolumns: read-only cells read1234.5,paid,1234.5; the same row in list mode reads1,234.5,Paid,1,234.5. No reach was measured (the docs page's read-only example writes values that read the same either way), so it is noted here and not filed.grid.mdx's "Integration with Advanced Grid" list (outside the Features list) offers add/remove rows, drag-and-drop reordering and formula columns as plugin features, which the basic grid also has. Left as is.docs/adr/0001-master-detail-subform.md(governed) namessort_fieldandrow[sortField] = index. An ADR records the decision taken; left as is.Patch (answer A) — added by the seat
5929940616on objectui#11070) to this PR's open question. After PR feat(plugin-tree,plugin-map,types): object-tree and object-map are judged and publish the keys their renderers honour (objectui#11168 slice 3) #11335 landed,origin/main20d23befwas merged in as36313b7f; the merge touches none of this PR's files.09d3ebf0edits exactly the two clauses of theobject-master-detail-form.detailsrow'spinsprose inapps/console/src/__tests__/registry-inputs-spec-parity.test.ts: "four members … each RENAMED … besidecolumnsand the DERIVEDsort_field", and "five of the eleven members".sortFieldcheck from row 2 into row 2c, so row 2 keeps exactly the two off-list members that the parity row describes.5930257276. The dev's contract forbids a dev PATCH of this body, so the seat wrote this section.Generated by Claude Code