Skip to content

feat(spec): converge ComponentPropsMap['object-grid'].data onto ViewDataSchema (ui#6207 Option A); record the ui#6206-B measurement fork - #12120

Merged
os-litant merged 5 commits into
mainfrom
claude/issue-12039-componentpropsmap-rulings
Aug 25, 2026
Merged

feat(spec): converge ComponentPropsMap['object-grid'].data onto ViewDataSchema (ui#6207 Option A); record the ui#6206-B measurement fork#12120
os-litant merged 5 commits into
mainfrom
claude/issue-12039-componentpropsmap-rulings

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #12039 — Key 1 of 2 (object-grid.data, ruling objectui#6207 Option A) is implemented here. Key 2 (element:number.filter, ruling objectui#6206 Option B) is deliberately not changed: its binding measurement-first precondition measured the pinned runtime refusing the array form on the element's primary read path, which per the ruling's own text is a fork back to triage — the card report on #12039 carries the fork. #12039 must therefore stay open past this merge; objectui#6207 and objectui#6206 also remain open (their unlock is the downstream exemption deletion after a released spec version reaches the objectui pin).

Key 1 — ComponentPropsMap['object-grid'].dataViewDataSchema

Ruling (objectui#6207, 2026-08-25, batch adjudication; verbatim acceptance: 「同意」): Option A — the props-map entry converges onto ViewDataSchema (the #5090-ruled, pinned authority); the bare-array form is the deprecated staticData shortcut the objectui#4648 carve-out already refuses to publish.

  • packages/spec/src/ui/component.zod.ts: data was z.array(z.unknown()).optional() ("Static inline rows"), now ViewDataSchema.optional() (provider-discriminated: object / api / value / schema). staticData keeps its shape; its describe now points at the prescription instead of calling itself an alternate spelling of data.
  • ADR-0087: semantic entry object-grid-data-view-data-converged (packages/spec/src/migrations/entries/semantic/18.object-grid-data-view-data-converged.ts), registry regenerated via gen:migration-registry. Changeset carries the FROM → TO and the adr-0087: registered marker.
  • Ruled migration check (bare-array authors in generated artifacts/templates): swept examples/, skills/, packages/create-objectstack/, content/docs/, and spec fixtures for object-grid nodes — the only authors (showcase my-work.page.ts, command-center.page.ts) author objectName/columns/filter and never data; zero bare-array data authors found, so no rewrite ships and the semantic entry carries the prescription for out-of-repo authors.
  • ADR-0122 consequence: ViewDataSchema's own z.inputz.infer (measured: an Eq probe on ViewDataSchema alone answers false), so object-grid leaves the type-alias pin file's default-free family exactly the way that family's comment prescribes — ObjectGridPropsParsed declared, pin Iso839 deleted, pin count 835 → 834 with its receipt (post-merge count; main added Iso857/858 in feat(spec): declare the audit door and catch the delete request schema up — both meta-door casts retired #12003 while this branch was in flight).
  • Tests (packages/spec/src/ui/component.test.ts): safeParse({ data: { provider: 'value', items: [] } }) → success (the issue's acceptance criterion — the exact value the old entry refused), a second union arm (provider: 'object') → success, and the reverse pin: bare-array data → refused at the data path.

Key 2 — element:number.filter: the binding measurement, recorded

Ruling 6206-B's precondition, verbatim: "Measurement-first is binding: the upstream card must verify the adapter/runtime behaviour on array filters for this element's read path before editing — if the runtime genuinely cannot take the array form, that is a fork back to triage, not a silent flip to Option A."

Measured, at objectui pin 190fbd01 (.objectui-sha) and this repo's head:

  1. Renderer (packages/components/src/renderers/basic/elements.tsx @ pin): opaque pass-through — adapter.aggregate(object, { field, function, groupBy: '_all', filter }); filter?: unknown.
  2. Adapter (packages/data-objectstack/src/index.ts @ pin): for that params shape, aggregate() takes the analytics path and sends the filter raw: payload.where = params.filterclient.analytics.query(payload). The rule-array lowering machinery (translateFilterArray / objectFilterEntriesToAST) exists in the same file but runs only on the find() path (convertQueryParams), which aggregate() reaches only when the analytics capability is absent (404/501) — and deliberately not on a server rejection (AnalyticsQueryRejectedError is thrown instead, per the file's own framework#3878 note).
  3. Runtime door (this repo, executed via tsx on service-analytics src after building the package's dependency closure; both strategies pass through it):
  4. Deployment reach: the analytics capability is foundational — examples/app-showcase/objectstack.config.ts records "the CLI always loads it" — so the refusing path is the default deployment's path, not an edge case.

Conclusion: at the current pin the runtime genuinely cannot take the raw ViewFilterRule[] form on this element's primary read path (an authored array filter renders the element into its error state on any analytics-capable deployment). Landing the spec declaration now would be exactly the "declaration the runtime refuses" the ruling forbids. Forked back to triage in the #12039 report, with a recommended sequencing (objectui adapter lowers rule-arrays on the aggregate path — the machinery already exists one method over — then pin bump, then the spec convergence as ruled).

Verification

Union run at 8fcbd6b (this branch's final commit, after merging origin/main @ a933ed7):

  • pnpm --filter @objectstack/spec check:generated — gate's own line: "✓ All 14 generated artifacts are up to date" (check:test-typecheck ✓ after the Iso839 departure was recorded).
  • pnpm --filter @objectstack/spec run typecheck — green (tsc --noEmit + scripts + test tsconfig).
  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2Test Files 425 passed (425) / Tests 11340 passed (11340).
  • Dispatch-named gates, each exit 0 at 8fcbd6b: check:changeset-gate-self-tests, check:cross-package-test-inputs, @objectstack/lint check:doc-formula-expressions (self-test 50 cases; 22/9/14 clean), @objectstack/spec check:empty-state / check:liveness / check:strictness-ledger / check:variant-docs, check:merge-driver, check:published-files, check:query-options-erasure, check:slot-lookup, check:spec-parsed-alias, scripts/check-adr-0087-registration.mjs, check:nul-bytes.
  • scripts/pm/dispatch-gates.mjs re-derived with no paths at 8fcbd6b (stderr stamps the answer's repo and commit); every additionally derived family run and green: doc-anchors, doc-authoring, doc-security-posture, docs-audit-scope, docs-redirects, published-readme-links, quick-reference-counts, react-page-adapter-contract, role-word, objectui-changeset, test-source-alias, type-source-resolution, engine-double-contract, where-matcher, changeset-no-major, ci-filter-parity, doc-frontmatter, doc-route-spelling, docs-section-name, empty-changeset, plugin-teardown-shape, section-landing-index, docs-audit affected/drift-comment, release-rehearsal self-test; dev-prereqs / type-check-coverage / type-check-debt after the workspace build they demand (results in the issue report).
  • Type-level reverse verification against the rebuilt dist/*.d.ts: bare-array data → TS2322 naming the ViewData union (red); provider-object data → compiles (green).
  • Repo-wide pnpm lint and the full multi-package farm are CI's runs; local verification was scoped to the affected package plus every path-derived gate above (declared narrowing — CI runs the farm on this PR).

H17 note: packages/spec/src/ui/view.zod.ts is NOT touched — ViewDataSchema is imported from it in component.zod.ts only.


Generated by Claude Code

…Schema (objectui-6207 Option A)
Accept-set change on one props-map entry: data was z.array(z.unknown()),
now ViewDataSchema (provider-discriminated object). Static inline rows move
to { provider: 'value', items: [...] }. ADR-0087 semantic entry
object-grid-data-view-data-converged carries the prescription; sweep found
zero bare-array authors in first-party corpora. The element:number.filter
sibling key of the same card is deliberately untouched (measurement-first
fork; see the card report).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
…ult-free pin family (ADR-0122)
ViewDataSchema's own input/infer split rides into ObjectGridPropsSchema, so
Iso839 is deleted per its comment's prescription and the Parsed alias is
declared. Regenerates api-surface, export-origins and docs references.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
…ith its receipt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
…mponentpropsmap-rulings
# Conflicts:
#	packages/spec/src/type-alias-convention.pin.test.ts
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

3 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️2 changed file(s) yielded no anchor (packages/spec/api-surface/ui.json, packages/spec/export-origins/ui.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/spec/api-surface/ui.json, packages/spec/export-origins/ui.json) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 45 of 222 client-bound route-ledger rows — the other 177 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 399ecad58033006635b69d645b4df1d2091c98e5packageMentionDocs.

Which tree this was computed on

This run read content/docs from c9f5227d8ad83c49bf0ffa6b8b0a56bad9f82d85 — the merge of head 8fcbd6b3c6f546b4aceb60ac27e2677efed6c73b into base 399ecad58033006635b69d645b4df1d2091c98e5, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin c9f5227d8ad83c49bf0ffa6b8b0a56bad9f82d85 && git checkout c9f5227d8ad83c49bf0ffa6b8b0a56bad9f82d85
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 399ecad58033006635b69d645b4df1d2091c98e5 8fcbd6b3c6f546b4aceb60ac27e2677efed6c73b && git checkout -B drift-repro 399ecad58033006635b69d645b4df1d2091c98e5 && git merge --no-ff 8fcbd6b3c6f546b4aceb60ac27e2677efed6c73b
node scripts/docs-audit/affected-docs.mjs --json 399ecad58033006635b69d645b4df1d2091c98e5

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:ui tests tooling labels Aug 25, 2026
@os-litant
os-litant marked this pull request as ready for review August 25, 2026 11:28
@os-litant
os-litant added this pull request to the merge queueAug 25, 2026
@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Aug 25, 2026
@os-litant
os-litant added this pull request to the merge queueAug 25, 2026
@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Aug 25, 2026
@os-litant
os-litant added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 8f79379Aug 25, 2026
39 checks passed
@os-litant
os-litant deleted the claude/issue-12039-componentpropsmap-rulings branch August 25, 2026 13:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:uisize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-litant@claude