Repository navigation
fix(spec): the object-grid page-size migration entry states that a stored page still saves, with an advisory CLI finding - #20884
Conversation
…ill saves, with an advisory CLI finding The acceptance criterion of `ui-object-grid-page-size-positive-integer-refused` said a stored page whose `object-grid` node carries `pageSize: 0` is refused on its next authoring-path save. Nothing on the metadata save path parses a page component's `properties`; the component-props gate is an advisory, CLI-only rule. The criterion now states the measured outcome: the page saves and loads, and `os validate` / `os build` / `os lint` report an advisory `component-props-invalid` finding at `pagination.pageSize`. Text only. The registry is regenerated with gen:migration-registry. Claude-Session: https://claude.ai/code/session_018fxqvRJW12TaHC7DUQ89Y6 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 137 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 6a6b641a4b9dc447ed8f5facaa02a1d35ec7f179 && git checkout 6a6b641a4b9dc447ed8f5facaa02a1d35ec7f179
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9905e61ca2fddb43d266c23cdb12ced5019c1a74 a3fd6c8aef0f9696f736ad32fa1d516f6c900a1b && git checkout -B drift-repro 9905e61ca2fddb43d266c23cdb12ced5019c1a74 && git merge --no-ff a3fd6c8aef0f9696f736ad32fa1d516f6c900a1b
node scripts/docs-audit/affected-docs.mjs --json 9905e61ca2fddb43d266c23cdb12ced5019c1a74 |
Contract reviewPR #20884 (card #20860) — Served-tier: Inputs: the card body and its three comments (triage 5912835288, the dispatch claim 5913355847, the ① Derived judgmentsThe diff. Three files, 39/6. (1)
The corrected sentence, claim by claim, against
Scope held. Triage's direction was the sentence and nothing on the save path; the diff changes no judgment. Generated copy against a moved Governance and shape. No path in the file list is a register row ( Check-runs on the head, read at 2026-09-30T15:18Z — 33 runs: 20 success, 3 skipped (Build Docs, Console Pin Gate, Packed-tarball smoke — opt-in), 10 in progress, none failed. Required-set readings: Build Core success; Dogfood Regression Gate success (all three shards); Governed Surface Queue Guard success; Lint & Repo Gates in progress; Temporal Conformance (live PG + MySQL) in progress; Test Core (1/6 through 6/6) in progress; Type Check · source gates and · debt ledger success, · workspace and · consumer gates in progress. Also success: Check Changeset, Check PR Size, Spec property liveness, the claim/branch/single-writer guards. These conclusions are the gate verdicts; this record judges the diff, and enqueue still waits on every required check reaching success. ② Semver level
Clause-②: no — right, and consistent across the dispatch claim, the PR body and the changeset. Not breaking, so no ADR-0087 disposition marker is owed; the dev's ③ Boundary flagsDev
Dev The card's own ⛔ "not measured" (a save through the route) is discharged by the two measurements in the PR body; triage's ⛔ "not a change to what the save path judges" holds — the diff changes no judgment. The PR body's "owed before enqueue" flag is this record. Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #20860
Clause-②: no
The ADR-0087 D3 entry
ui-object-grid-page-size-positive-integer-refused(protocol 18) said, in itsacceptanceCriteria, that a stored page whoseobject-gridnode carriespageSize: 0"is refused on its next authoring-path save with a per-key issue atpagination.pageSize". The save path does not do that. This PR corrects the sentence to the measured behaviour. It is a text-only change: no entry id, conversion, schema or matching logic moves.The two measurements (tree:
objectstack-ai/objectstackat6c96b37be8, the branch base)1. The save. The real
saveMetaItemwrite path was driven over a stub engine. The harness is copied fromprotocol.runtime-authoring-gate.test.ts, with an environment id and the default authoring channel, so the runtime authoring gate is live. The probe lived in scratch, not in the tree.PUT /api/v1/meta/:type/:nameinrest-server.tshands its body to this same call withwriteFace: 'meta-envelope', so the probe ran both faces. The HTTP door itself was not booted. Every case was saved, stored and read back throughgetMetaItem:object-gridnodeproperties)pagination: { pageSize: 0 }success: true, noadvisoriesmember, oneactiverow, reads back{ pageSize: 0 }pageSize: 25.5(flat shorthand)success: true, oneactiverow, reads back25.5pagination: { pageSize: 10, pageSizeOptions: [10, 0] }success: true, oneactiverow, reads back as writtenpagination: { pageSize: 25 }(well-formed)success: truetype: 'user:profile'(retired by name)422INVALID_METADATA, issue atregions.0.components.0.typeThe control leg shows that the harness can return a refusal, so the successes above are real readings. The one runtime-publish rule registered for type
pageis notvalidateComponentProps. The registry reportsruntimeAuthoringRulesFor('page')has length 1, and it does not include that rule.2. The CLI. The same page was run through
runAuthoringRules(command, …)for each ofvalidate,buildandlint.packages/cli/src/commands/{validate,compile,lint}.tscall this function. The registry row isvalidateComponentPropswithtier=advisory,surfaces=["cli"]andcommands=["validate","build","lint"]. The output was identical for all three commands: 0 errors and 3 advisories.The code read in the card holds.
PageComponentSchema.propertiesisz.record(z.string(), z.unknown()).validateComponentProps/ComponentPropsMaphave 0 non-test hits underpackages/metadata-protocol/src,packages/objectql/src,packages/metadata/src,packages/rest/srcandpackages/runtime/src. The control hit ispackages/lint/src/authoring-rules.ts:113. The rule's own hint already says "the props bag is not parsed on the storage path either".The correction
acceptanceCriterianow says, in the wording triage gave: the page still saves and loads;propertieson a page component is not parsed on the metadata save path; the component-props gate reports an advisorycomponent-props-invalidfinding atpagination.pageSizeonos validate,os buildandos lint. Measurement 2 shows that apageSizeOptionsentry and the flatpageSizeshorthand are reported the same way at their own paths, so the criterion says that too. It ends with the author's check:os validatereports no such finding for that node.surface,replacementandreasonwere read for the same false claim. None of them states a save-path refusal, so they are unchanged.Sibling
object-grid-default-filters-rule-array: measured the same way. A bare stringdefaultFilters: 'status'and a malformed rule list[{ field: 'status' }]both save withsuccess: trueon both faces. The CLI gives one advisorycomponent-props-invalideach, atproperties.defaultFiltersand atproperties.defaultFilters.0.operator. The entry already says the key's door "refuses such a value only as the component-props gate's advisory finding (os validate, os build, os lint), since a re-save through the metadata API is not refused there". That is true, so the sibling is unchanged.Generated copy
packages/spec/src/migrations/registry.tswas regenerated withpnpm --filter @objectstack/spec gen:migration-registryand was not edited by hand. It has one hunk. With leading whitespace stripped, its+/-lines are byte-identical to the entry file's (cmpexit 0, 10 lines each). The word-diff of both files shows the same replacement.spec-changes.jsonand the protocol upgrade guide project protocol 17 only. As measured,check:spec-changesandcheck:upgrade-guideare green with no regeneration, and neither file is in the diff.Changeset
.changeset/20860-page-size-entry-advisory.md:@objectstack/specpatch,Clause-②: no. It is text-only because the entry ships in the package'sdist.Local verification (all at head
a3fd6c8aef)pnpm --filter @objectstack/spec buildpassed (exit 0).@objectstack/spechas no workspace dependencies, so step 1 of the closure build is empty.pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2gaveTest Files 579 passed (579)andTests 17090 passed | 1 todo.pnpm --filter @objectstack/spec typecheckexited 0 (tsc --noEmit,check:scripts-typecheck,check:test-typecheckOK). The public surface is unchanged (check:api-surface: "public API surface + factory signatures unchanged"), so no importer owes a test.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 82 commands. Each exit code was captured to a file before any pipe.--ranreconciliation: "82 derived famil(ies) accounted for — 81 run, 1 NOT-MEASURED". 80 exited 0 on the first pass.check:lean-entry-closureexited 3 (PREREQUISITE NOT MET, objectqldistabsent), and after@objectstack/objectql...was built it exited 0. Named verdicts:check:migration-registry"registry.ts is current",check:spec-changes"spec-changes.json is up to date",check:upgrade-guide"protocol-upgrade-guide.md is up to date",check:doc-authoringclean,check:nul-bytesOK,check:adr-0087-registration"no declared-breaking changeset",check:empty-changesetOK.check:dual-build-cjs-loads. Reason: it loads the built CJS entry of every workspace package and needs a whole-workspacepnpm build(60+ packages have nodisthere). This diff changes one string literal inside@objectstack/spec, whose own build passed. CI's Lint & Repo Gates and Build Core measure it.a3fd6c8aef(base6c96b37be8). By reconciliation timeorigin/mainhad moved 6 commits, and 4 files that families derive from had changed there (check-stack-collection-maps.mjs, an i18n-walk-parity fixture, one adr-anchor JSON,role-word-baseline.json). None of them reads this diff's paths. The branch is not merged withmain, and CI measures the merge ref.pnpm lint(repo-wide, CI-owned), the type-check lanes and the path-scheduled jobs the derivation lists.Acceptance notes
@objectstack/specCHANGELOG entry for the narrowing (9bb059d) says "theobject-gridpage-component door now refuses a page size of0". That is true of theComponentPropsMapparse. It does not name the save path, so it is not the false claim this card corrects. CHANGELOG is release-owned. Carrier: none.Owed before enqueue: the at-tier contract review by the owning seat (review face
packages/spec/src/**non-test). This PR does not carry that record.Generated by Claude Code