Repository navigation
chore(objectui): bump the console pin to 9dfaca654311 (carries objectui#11611, #11614 and #11619) - #21800
Conversation
Written by scripts/bump-objectui.sh 9dfaca654311cddd81714153c4f82c241d7cdc54 --no-commit. objectui@9dfaca654311cddd81714153c4f82c241d7cdc54 Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
…at pin 9dfaca654311 Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
… re-measure pin citations (part) Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
…aca654311 Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
…54311 Every anchor in each asserting record was mapped through the objectui diff 2e818d0b51ec..9dfaca654311 and re-read; moved anchors are re-pointed with their text byte-identical, and each record gains a dated hop sentence. Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
…clared-breaking entries Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
….span describe Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 139 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 1daaae3700752d9aeb2c9cbbdcba31be63a5a6d7 && git checkout 1daaae3700752d9aeb2c9cbbdcba31be63a5a6d7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e27a7c0c9e55db06a1d40912f89a0cce4cedfdd8 4b9519ea23d31a3b7eb688f32bb52a895f8f7533 && git checkout -B drift-repro e27a7c0c9e55db06a1d40912f89a0cce4cedfdd8 && git merge --no-ff 4b9519ea23d31a3b7eb688f32bb52a895f8f7533
node scripts/docs-audit/affected-docs.mjs --json e27a7c0c9e55db06a1d40912f89a0cce4cedfdd8
|
Fixes #21772
Clause-②: no
This moves the bundled Console's objectui pin from
2e818d0b51ec(#21710) to objectuimainas of the write time,9dfaca654311cddd81714153c4f82c241d7cdc54, which is pastc096f03. The Console now carries objectui#11611 (theref:datasetspec-form widget), objectui#11614 (the grid widget's camelCase keys) and objectui#11619 (the record chrome's picture). Those are the three merges #21714, #21768 and #21765 wait on.⛔ This is not a release act. Version PR #21352 is untouched, and no tag, publish or Release was made. The card's "release first" hold is lifted by the maintainer's order recorded in the claim: 「浏览器测试已经在运行,还有很多问题在处理,服务端开发不应该被阻塞」.
Range
git ls-remote origin refs/heads/mainread9dfaca654311cddd81714153c4f82c241d7cdc54at 2026-10-05T00:51:29Z, just before the bump, and the same sha again before this PR was opened.git merge-base --is-ancestorexits 0 against9dfaca654311for all three carried merges:b508ac50d9(objectui#11611),2abec3a96c(objectui#11614) andc096f03279(objectui#11619). The objectui clone is shallow, but exit 0 proves itself there.2e818d0b51ec..9dfaca654311has 17 commits and 0 merges.major. Four carry the author's breaking annotation, and the highest declared level isminor, so the console changeset isminor. These counts come fromscripts/objectui-range.mjs --from 2e818d0b51ec --to 9dfaca654311 --jsonand from the bump's own digest. They were measured, not copied from the card.!.git log --format='%h %s' 2e818d0b5..9dfaca654 | grep -E '^[0-9a-f]+ [a-z]+(\([^)]*\))?!:'gives9db9ff3f9,8b14aecbd,2abec3a96andb403bb36f.9dfaca654simpleform draws a self-describing inline section entry;ObjectFormSection.fieldsgains the form view's{ field }arm15f67025bderiveInlineGridColumns4c127cdefrecord:related_liststops requiringcolumnsc096f0327imageField6e9090c269db9ff3f9!subforms[].columnsentry is the spec'sInlineGridColumnSchema, by reference7c9a6b1948b14aecbd!PartialSchemais retired from@object-ui/types2abec3a96!b403bb36f!BaseSchemaloses its index signatureClause-②: yes (narrowing), no BREAKING word)!, answered belowfd060f076objectName, and a node with neither shows a no-object hintb508ac50dref:datasetspec-form widget, fed by the report inspector's dataset catalogd2e859936GET /usage/storageonly when the runtime servesfeatures.storageUsageb92329c89902ebab63record:line_itemsstops requiringchildObject278d2444eb61c116b2record:detailsread mode keeps a textarea's line breaksDeclared-breaking changes, and how this repo answers each
The ADR-0087 disposition is
not-required (no-migration-prescription). It replaces the bump'sadr-0087: TODOplaceholder in.changeset/console-9dfaca654311.md, and it covers all five entries below.check-adr-0087-registration --base origin/maingives "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition".check-changeset-no-major --base origin/maingives "This diff introduces nomajorbump".2abec3a96): the grid widget's eight keys.min_rows,max_rows,allow_add,allow_delete,allow_reorder,total_field,add_labelandsort_fieldbecomeminRows…sortField. objectui has no dual read: its zod faces refuse a snake_case key by name, and itsGridFielddraws an inline alert instead of the grid.@objectstack/spec's runtime form field (buildObjectFormRuntimeField,packages/spec/src/ui/component.zod.ts) already refuses the eight snake_case keys by name, with guidance that names objectui#11610. The camelCase keys are not declared there yet.object-formruntime form field declares the grid widget's eight camelCase keys once.objectui-shacarries objectstack-ai/objectui#11614 (#21704 fork 2 follow-up) #21768, an ObjectStack-authoredgridform field can spell the keys neither way. Measured on this head's built spec:object-formwithcustomFields: [{ name: 'items', type: 'grid', min_rows: 1 }]is refused withunrecognized_keysatcustomFields.0and the grid-key guidance. The same field withminRows: 1is refused withunrecognized_keysatcustomFields.0, as an undeclared key. So agridfield takes itscolumnsand the widget's own defaults. The refusal's prescription says these keys "come in once the widget reads a camelCase spelling". At this pin the widget does, and spec(ui): theobject-formruntime form field declares the grid widget's eight camelCase keys once.objectui-shacarries objectstack-ai/objectui#11614 (#21704 fork 2 follow-up) #21768 declares the keys and retargets that prescription.git grepoverexamples/andpackages/finds no authored snake_case grid key. The only hits are the spec's own refusal list and its pin test, migration prose, and one historical note about objectui's internal master-detail adapter.9dfaca654): thesimpleform's inline section entries. For TypeScript readers ofObjectFormSection.fields, the type gains the spec'sFormFieldInputarm. No code in this repo imports@object-ui/types; the only@object-ui/*import isscripts/gen-sdui-manifest-node.mjsreading@object-ui/corefrom the built tree. The behaviour change is that the defaultsimpleform now draws an inline{ name, … }entry, as the other five form types already did. The showcase'sobject-formnodes arewizard,drawerandmodalforms whose sections list field names, so none of them draws differently.9db9ff3f9):subforms[].columns. objectui's validator now judges a column by@objectstack/spec's ownInlineGridColumnSchema. This repo has enforced that closed shape since feat(spec)!: a form view's subform columns are the inline grid column contract, and an identity-only column is judged as the type it renders (#20901) #20927. objectui's verdict now matchesos validate, and the ObjectStack accept set does not move.8b14aecbd):PartialSchema. It leaves@object-ui/types. Nothing in this repo names it (git grep PartialSchema: 0).b403bb36f):BaseSchemaloses its index signature. This narrows the TypeScript face of objectui's node types, and nothing here compiles against them. objectui's zod faces keep their accept sets for every key exceptvisibleWhen. That key widens to the{ dialect, source }envelope this repo's own parse writes.The three cards this unblocks
reportForm's "Joined blocks" row offers a block'sdatasetas free text with norequired, so Studio saves the block #21702 now refuses #21714: objectui#11601'sref:datasetwidget (PR objectui#11611,b508ac50d) is now in the pinned build, soreport.form.ts's joined-blockdatasetrow can declarewidget: 'ref:dataset'.object-formruntime form field declares the grid widget's eight camelCase keys once.objectui-shacarries objectstack-ai/objectui#11614 (#21704 fork 2 follow-up) #21768: objectui#11610's camelCase keys (PR objectui#11614,2abec3a96) are now what the pinned widget reads, so the spec's runtime form field can declare them.object.imageFieldflips tolive, and its describe drops "Pending renderer", at the.objectui-shabump that carries objectui#11383 #21765: objectui#11383's record picture (PR objectui#11619,c096f0327) is now in the pinned build, soobject.imageField's liveness row can move tolive. The smoke below observes that read in the browser. The reader ispackages/components/src/renderers/layout/containers.tsx, in thepage:headerrecord chrome.What changed here
.objectui-shaand.changeset/console-9dfaca654311.md.scripts/bump-objectui.sh 9dfaca654311cddd81714153c4f82c241d7cdc54 --no-commitwrote both, withOBJECTUI_ROOTset to the container's objectui clone aftergit fetch origin main. The range walked completely without a deepen, and the level was auto-set tominor.sdui.manifest.jsonandscripts/sdui-manifest.record.json.node scripts/gen-sdui-manifest-node.mjsregenerated them over the tree thatpnpm objectui:buildbuilt at the pin. There are 107 components at both pins, and the sha256 moves from0ead67c1111d…to6f921896ffac…. This time the manifest moves:required: trueand gain a description. Nine areobjectName, onobject-grid,list-view,object-form,embeddable-form,object-master-detail-form,object-kanban,object-metric,object-chartandobject-pivot(objectui#11605). The other two arerecord:related_listcolumns(objectui#11613) andrecord:line_itemschildObject(objectui#11569).object-master-detail-form'sfieldsdescription is rewritten for objectui#11615's inline entries.ComponentPropsMaprow, these inputs are already optional there. Measured on the built spec:object-grid,object-form,object-kanban,object-metricandobject-master-detail-formobjectName,record:related_listcolumnsandrecord:line_itemschildObject. So the manifest now agrees with the spec rows. The JSX page compile reads the manifest, and it stops refusing a node whosedataSourcebinding names the object.modulesRoot. objectui's workspace version stays 17.7.0.packages/sdui-parser/objectui-lockstep.json.pnpm gen:sdui-lockstepre-recorded it againstOBJECTUI_ROOT=.cache/objectui-9dfaca654311. It records 214 grammar lines (blob0131f27cf86d), 25 codes and containment predicate76c18fb95d1f. All are unchanged, and objectui'spackages/sdui-parserhas no diff over the range, so no port is owed.packages/spec/src. They were re-measured at the new pin, not restamped:2e818d0b5, mapped throughgit diff -U0 2e818d0b5 9dfaca654, and re-read at the new pin. Each record gains a dated 2026-10-05 hop sentence and keeps its earlier history.ObjectGrid.tsx,ObjectTree.tsx,ObjectGantt.tsx,ObjectCalendar.tsx,SchemaRenderer.tsx,plugin-view/src/ObjectView.tsx,plugin-map/src/index.tsxandplugin-gantt/src/index.tsx.ObjectKanban.tsx, objectui#8347 added a privateGateBoundKanbanSchemaread type, so its fetch, navigation reads and spread moved +30.plugin-kanban/src/index.tsx,plugin-dashboard/src/index.tsxandElementDataSourceGate.tsx. Theobject-metricicon input moved281→299and is still{ name: 'icon', type: 'string' }.page:tabsandpage:accordionicon anchors incontainers.tsxby +3.ObjectKanbanSchema.limit,ObjectMapConfigSchemaandLIST_VIEW_LOCAL_OVERRIDESinobjectql.tsandobjectql.zod.ts.view.noObjectto theen,zhanddelocale packs. Their citedcalendar.configRequiredstrings did not change or move.ObjectKanban.tsx:10, the type import, gainedSortConfigbeside theObjectKanbanSchemathe record cites.keyboardNavigationhit lines (15, against theschema.editablecontrol's 3) and theElementDataSourceGateoccurrences in fivesrc/index.tsxshells (0, 3, 3, 3 and 4).ui/view.zod.ts's map record redded at this pin, and each was re-read and re-pointed:case 'map':moved2299→2300,ObjectMapConfigSchema2370→2388, andLIST_VIEW_LOCAL_OVERRIDES1419→1437.git grep -o -F. That method first reproduced every2e818d0b5number: 7579 files,objectstack17227,@objectstack/spec7134,timeout1351,useState2477,TTL182,tenant1317 andSpan505.RuntimeConfig276 → 293,resourceLimits2 → 2,window4175 → 4193,period238,interval195 andmetrics374 → 401.Span(508) andSpanSchema(57). The three newSpanhits arecolSpanin objectui'sobject-form-section-field-entry-11615.test.ts. BothresourceLimitshits are still prose inpackages/app-shell.packages/spec/src/migrations/registry.tswas regenerated withgen:migration-registry..changeset/objectui-pin-citations-9dfaca654311.mdis a@objectstack/specpatch, because theFormField.spandescribe and six migration descriptions name the pin.content/docs/references/ui/view.mdxwas regenerated bycheck:generated --fix.No example, test or gate needed adapting, and no code changed outside generated records, citations and changesets.
Console build and canaries
build-console.shran locally under the verify lock, afterturbo run build --filter=@objectstack/client..., the same two steps theConsole Pin Gatejob runs. Exit 0, 9m02s on a shared four-core box. The build log reports:check:console-shaandcheck:console-injectionexit 0 against that dist.Browser smoke:
examples/app-showcasewith the Console built at9dfaca654311The server ran
pnpm dev -- --fresh --ui --no-watch --compile -p 41877withOS_PORT=41877, on its own ephemeral DB with the seeded admin. Headless Chromium (/opt/pw-browsers/chromium) drove it, signing in through the console's own login form, with console messages, page errors and every 4xx/5xx response captured. Only the PIDs this run started were stopped.No showcase object declares
imageField, so the record picture needs one to exist.git grep imageField examplesgives 0 hits. To exercise objectui#11619's read, the smoke made a temporary local edit:imageField: 'f_image'toshowcase_field_zoo, throughnode scripts/ablation-replace.mjs --hold.--restore. The tool reports the blob back to HEAD's4130858b8f8bandgit diff HEADempty, andgit status --porcelainis empty.dist/was restored from turbo's cache for the clean source: sha256cc1034dd9d23…, as before the smoke. The stray runtime bundle of the edited compile was deleted.Nothing of the edit is in this diff. A real
sys_filewas uploaded through/api/v1/storage/upload/presigned→PUT→/upload/complete(a 64×64 red PNG) and written to "Specimen — Full"'sf_image.[data-record-picture]f_imageset)rounded-md(animagefield, notavatar)src="/api/v1/storage/files/b1f4e384-…",alt="", loaded,naturalWidth64f_imageempty)Verdict: at this pin the record header draws the record's picture from the object's
imageField, drawing the stored file through/api/v1/storage/files/:id, and draws nothing when the value is empty.showcase_task's record page is the customtask-detailpage, which has nopage:header, so it draws no record chrome to put a picture in. That page was smoked too: it renders its path bar, highlights and sections with 0 page errors.Console messages across the run: 0 page errors. The only failed loads are a 401 on
GET /api/v1/auth/get-session(the pre-login probe) and a 404 for/favicon.ico. There is no/api/v1/usage/storage404. #21625's and #21710's smokes both recorded one, and objectui#11002 (d2e859936) stopped the request on a runtime that does not serve it.Gates and tests (head
4b9519ea23)node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 127 commands from the 22-path diff, and all were run at4b9519ea23.--ranreports "127 derived, 127 run, 0 NOT-MEASURED, 0 UNRUN", with every exit code recorded.PREREQUISITE NOT MET) on the first pass:check:skill-examples(noclient-reactdist) andcheck:dual-build-cjs-loads(no dist for 34 packages).turbo run build --filter=!@objectstack/docs(71 of 72 tasks were cache hits), and those are the codes recorded.check:objectui-pin-citations --verify-anchorswith objectui at the pin: 54 asserting citations match9dfaca654, and 7 anchor content assertions are verified.check:objectui-bump(20 assertions across 5 cases),check:sdui-lockstep,check-sdui-manifest,check:console-sha,check:console-injection,check:migration-registry.@objectstack/spec check:generated: all 15 artifacts current after the--fix.pnpm --filter @objectstack/spec exec vitest run(both projects,localandrepo): 668 files, 19259 passed, 1 todo.pnpm --filter @objectstack/spec typecheck: exit 0.@objectstack/sdui-parsertest (14 files, 225 passed) and typecheck: exit 0.@objectstack/linttest: 119 files, 5627 passed. It declaressdui.manifest.jsonas a test input.@objectstack/metadata-protocolsrc/protocol.runtime-authoring-gate.test.ts: 70 passed.@objectstack/cliunit tiersrc/utils/sdui-manifest.test.tsandtest/validate-build-gate-parity.test.ts: 2 files, 79 passed.test/jsx-gate-manifest-notice.e2e.test.tsbelongs to neither CLI tier; it runs nightly, so it is NOT MEASURED here and is left to CI.eslint --no-inline-config --format jsonon the 15 changed TS files: 15 files, 0 errors and 0 warnings. The lint population is**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}(eslint.config.mjs:971). The config enables no type-aware linting (:327-328), so this diff cannot move a verdict on an untouched file. Repo-widepnpm lintis left to CI.Acceptance notes
mainmoved two commits past this branch's base (docs(pm-dispatch): say how the claim reads the Clause-② public surface #21783, fix(cloud-connection): refuse install-local sample data for a session with no active organization (ADR-0123 D2/D4) #21780). Neither touches a path this diff touches, so no merge was made. The merge queue rebuilds on the currentmain.containers.tsxanchors inui/component.zod.tsdocblocks with no sha, andcomponent.test.ts'splugin-dashboard/src/index.tsx:204(theObjectMetricPropsSchema icon livenesstest, already reading an unrelated line atab1879721595, as chore(objectui): bump the console pin to 2e818d0b51ec (carries objectui#11466, #11574, #11578, #11581 and #11583) #21710 noted).object-formruntime form field declares the grid widget's eight camelCase keys once.objectui-shacarries objectstack-ai/objectui#11614 (#21704 fork 2 follow-up) #21768 retargets it when it declares the camelCase keys. It is left as is here, because the pin bump changes no accept set.Generated by Claude Code