Repository navigation
feat(spec): the view display page size defaults to 50 — PaginationConfigSchema.pageSize .default(25) → .default(50) - #20184
Conversation
…hema.pageSize) WIP: default flip and the flipped default pin; ledger, generated artifacts and changeset follow. Claude-Session: https://claude.ai/code/session_01Rjy9MeetSfq34PKn81CRiN Co-authored-by: Claude <noreply@anthropic.com>
… -> 50 check:authorable-surface refuses an undeclared default move; this is the DEFAULT_CHANGES_BY_MAJOR row the gate printed, with its reason. Claude-Session: https://claude.ai/code/session_01Rjy9MeetSfq34PKn81CRiN Co-authored-by: Claude <noreply@anthropic.com>
…us its changeset Semantic migration entry view-pagination-page-size-default-50 (step 18, registry regenerated) and a minor @objectstack/spec changeset naming the behaviour change for authors who omit the page size. Claude-Session: https://claude.ai/code/session_01Rjy9MeetSfq34PKn81CRiN Co-authored-by: Claude <noreply@anthropic.com>
…efaults, view reference) Claude-Session: https://claude.ai/code/session_01Rjy9MeetSfq34PKn81CRiN Co-authored-by: Claude <noreply@anthropic.com>
…ew-page-size-default-50
📓 Docs Drift Check2 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 136 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 d8ad5893cd5bf2fe76471fd3e4affd725405e0ed && git checkout d8ad5893cd5bf2fe76471fd3e4affd725405e0ed
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 836aad2a19bd4639ded6a3a6bf18db8a75d3a2c3 72e9a6a027fe4c3279d67ca1d100a4c95bcceb82 && git checkout -B drift-repro 836aad2a19bd4639ded6a3a6bf18db8a75d3a2c3 && git merge --no-ff 72e9a6a027fe4c3279d67ca1d100a4c95bcceb82
node scripts/docs-audit/affected-docs.mjs --json 836aad2a19bd4639ded6a3a6bf18db8a75d3a2c3 |
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #20050
Clause-②: no
What
The view display page size defaults to 50.
PaginationConfigSchema.pageSizeinpackages/spec/src/ui/view.zod.tsmoves from.default(25)to.default(50). That is the only declaration of the view display default. Maintainer ruling, verbatim (objectui#9853, batch #223 item 4): 「9853 默认页大小改为50」. The change goes into the protocol first: the renderer reads the spec default (objectui#9853 ruling C′ item 1), and no renderer hardcodes 50.Contract face: accept set unchanged, one default moved
Default:
ui/PaginationConfig:pageSizemoves from25to50. This is the only default the build's ratchet saw move (📌 1 declared default change(s) accepted (#4666): - ui/PaginationConfig:pageSize: 25 → 50).Accept set: unchanged. The type is still
z.number().int().positive(). The refusal pinsshould reject negative pageSize,should reject zero pageSizeandshould reject non-integer pageSize(view.test.ts) still pass without edits, and so does the component-arm cross-check (component-object-grid-pagination-accept-set.pin.test.ts). Measured on the built dist:PaginationConfigSchema.safeParse({ pageSize: 0 })is refused withtoo_smallatpageSize.Describe text: unchanged, byte for byte. It still reads: "Number of records per page. On a view with no pager (kanban, gallery, timeline) it is the fetch ceiling, and the renderer owes two things: bound its fetch at this number, and, when the filtered set is larger than it, show a visible truncation signal saying what is on screen is not the whole set". The schema docblock gains one paragraph naming the ruling and stating that the renderer reads this default.
Parse outputs, measured on the rebuilt
packages/spec/dist:paginationListViewSchemawithpagination: {}{ pageSize: 50 }(was25)ListViewSchemawith nopaginationListViewSchemawithpagination: { pageSize: 25 }{ pageSize: 25 }Published JSON Schema:
json-schema/ui/PaginationConfig.jsonnow haspageSize.default: 50.Sweep of every text stating the display default as 25, counted by declaration
The declaration census covers every
pageSize.default(underpackages/spec/src. It finds 3 declarations:ui/view.zod.ts(25, this card),kernel/metadata-plugin.zod.ts(50) andmarketplace/marketplace.zod.ts(20). The last two are out of scope per the card and untouched. Texts restating the view default:view.zod.tsPaginationConfigSchema.pageSize.default(25).default(50)packages/spec/authorable-defaults/ui.json(generated)ui/PaginationConfig:pageSize = 25= 50content/docs/references/ui/view.mdx(generated), 3 rows:ListView.pagination,ObjectListView.pagination,## PaginationConfigoptional (default: 25)gen:docstooptional (default: 50)view.test.tspinshould default pageSize to 25toBe(25)should default pageSize to 50/toBe(50)view.test.tspinshould accept custom page sizepageSize: 5025. With a default of 50 an input of 50 could no longer tell "the authored value survived" from "the default applied", so the pin now uses a non-default valueDeliberately unchanged. None of these states the current default:
component-object-grid-pagination-accept-set.pin.test.tsdocblock table row| view — PaginationConfigSchema | …default(25) | no |. Its column header isdeclaration before #19046, so it is a historical record and still accurate.pagination: { pageSize: 25 }values:plugin-approvalssys-approval-request.object.ts(3 list views) and the CLI view scaffold template (packages/cli/src/commands/generate.ts). These are explicit author choices and still parse to 25.pageSize: 25hits inpackages/spec/src/api/metadata.test.ts,kernel/metadata-plugin.test.ts,benchmark.bench.tsandsdui-parsertests. These are different surfaces or authored inputs.skills/**ordocs/adr/**states the view page-size default (grep for page size / pagination with 25, zero hits).content/docs/**(outsidereferences/) orexamples/**states a page-size default of 25.Surfaces this needed beyond the claim's list (measured, not optional)
packages/spec/scripts/lib/default-changes.tsgains the rowui/PaginationConfig:pageSizefrom '25'to '50'. Without itpnpm --filter @objectstack/spec buildfails with❌ 1 authorable key(s) changed the DEFAULT they apply when the author omits them: - ui/PaginationConfig:pageSize: 25 → 50, and the gate prints this exact row to add. The row'sreasonstates what moves and the one-line way to keep 25.view-pagination-page-size-default-50(src/migrations/entries/semantic/18.…ts, plusregistry.tsregenerated bygen:migration-registry). The ledger header prescribes one for a default move that reaches already-deployed silent documents. Every precedent where deployed behaviour moves has one: the autonumberuniquedefault, the audience posture default and the approval escalation flip. The precedents where nothing deployed moves have none.gen:spec-changesandgen:upgrade-guidewere re-run and produced zero diff, because step 18 is not projected yet. The same holds for the other 170 step-18 entries.Changeset level:
minorThis is a behaviour change for every author who omits the key, with no refusal and no type change. It is not a bug fix, so
patchwould understate it. It is not a narrowing and not a removal, so it is not breaking:Clause-②: no, no ADR-0087 marker owed (check-adr-0087-registration: "this PR adds no declared-breaking changeset"), and amajoris refused by the repo in any case. This matches the level the previous published-default moves shipped at (theenableOnInstalldefault move and the default-flip conversion class both shippedminor). The changeset states the behaviour change for authors who omitpagination.pageSizeand gives a FROM → TO table.Reverse verification (ablation), after the fix was committed
node scripts/ablation-replace.mjsput back.positive().default(25).describe(in place of.default(50)at HEAD eaf5d39. Theview.zod.tsblobc474dcb477c7is identical at 72e9a6a. The anchor hit x1 → x0, and the blob wentc474dcb477c7→c6933f3d2587. Then it ranvitest run src/ui/view.test.ts. The direction observed was the expected one, red:Tests 1 failed | 460 passed (461)withFAIL … PaginationConfigSchema > should default pageSize to 50andAssertionError: expected 25 to be 50. The restore was proven two ways: the blob equals the HEAD blob (c474dcb477c7…) andgit diff HEADis empty. The script also carried an EXIT/INT/TERM trap with an absolute path. The test imports./view.zodfrom source, so no dist leg was needed.Tests and gates (at
72e9a6a0, after mergingorigin/maine2c4e12)@objectstack/specbuild: exit 0 (📌 … ui/PaginationConfig:pageSize: 25 → 50).check:generated: 1 stale artifact (content/docs/references/**), fixed withgen:docs, then green.@objectstack/spectest (--project local):Test Files 540 passed (540),Tests 15820 passed | 2 todo. Test (--project repo):31 passed,579 passed. typecheck: exit 0.Consumer suites (contract-face fixture triage):
@objectstack/platform-objects55 files / 911 tests passed;@objectstack/lint108 files / 4144 tests passed. A repo-wide grep finds no test outsidepackages/specthat asserts a parsed view'spagination.pageSize(no.snap/JSON fixture carries one either).plugin-approvals/clisuites were not run locally; they are declared to CI (their fixtures authorpageSize: 25explicitly).Derived gates:
dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the actual 8 changed paths (merge base e2c4e12) gives 112 commands. Every one was run at 72e9a6a, and its exit code was written to disk before any pipe. 108 exit 0. 4 are NOT MEASURED; each exited 3 with PREREQUISITE NOT MET because it reads BUILT output of packages this diff does not touch:check:skill-examplesneeds@objectstack/client-reactdist;check:lean-entry-closureneeds@objectstack/objectqldist;check:dual-build-cjs-loadsandcheck:type-check-debtneed the whole workspace built.The targeted closure build could not get the shared verify lock (two 9-minute queue timeouts), so this is a declared narrowing, left to CI. This diff adds or changes no export, type or module (
check:api-surface,check:dts-closureandcheck:published-filesare green). The reconciliationdispatch-gates.mjs --ranreads:112 derived famil(ies) accounted for — 108 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3), 0 UNRUN. Three lint-dist gates first exited 3; after the lint closure was built they were re-run green. Also run: the 5 artifact-roster gates whose roster lives in a directory this diff touches (check-changeset-fixed,check:meta-url-spelling,check:authz-resolver,check:error-code-casing,check:filter-alias-parity), all exit 0.Mergeability: a driver-less
merge-treeof this head onto origin/main836aad2a(7 commits newer, one of them touchingregistry.ts) is clean.turbo ls --affectedis not used for any narrowing here.objectui (read-only, at
.objectui-shaf8a9d0fb05)No objectui test pins
25as the spec default. objectui brings the spec schema in asstripImportedDefaults(SpecPaginationConfigSchema)(packages/types/src/zod/objectql.zod.ts), andspec-subschema-parity.test.tsasserts identity against that stripped object, not a value. EverypageSize: 25in objectui tests is an authored input. objectui#9853 is where the renderer starts reading this default. objectui was not edited.Acceptance notes
os generate view) writes an explicitpagination: { pageSize: 25 }, so a newly scaffolded view shows 25 rows, not the platform default. It is an authored value and it validates. It is not a defect under the filing classes; noted only. Carrier: none.view.zod.tsis region-split with seat 2's spec(ui)+metadata save: judge a flattened view overlay's top-leveloptions.KINDwith the strict per-kind schema and persist the PARSED body — the door half of objectui#10380 #20051. This diff touches onlyPaginationConfigSchema(around line 1100). It does not touch the flattened list-overlay region (ListViewShapeSchema.extend(flattenedViewOverlayFields()).strip()/ overlayoptions).Generated by Claude Code