Skip to content

feat(spec): Field.number gains useGrouping presentation hint (#7768) - #7813

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-7768-number-usegrouping
Aug 12, 2026
Merged

feat(spec): Field.number gains useGrouping presentation hint (#7768)#7813
os-zhuang merged 4 commits into
mainfrom
claude/issue-7768-number-usegrouping

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#7768

Problem

Field.number's only presentation-adjacent property is scale, which governs
decimal places, not digit grouping. Console number renderers construct
Intl.NumberFormat with grouping unconditionally ON, so an ordinal/identifier
integer authored as Field.number({ scale: 0, min: 1900 }) (a year) renders
2,026 everywhere it is shown. Downstream apps hit this three times
(hotcrm-heimao#35, #40, #59), each time converting the field to Field.text
to escape the comma — trading away numeric semantics (range validation,
sort-as-number, arithmetic) for a display detail unrelated to the field's type.

Ruled direction (provenance)

Option A ruled on #7768, 2026-08-11 (PM triage comment), maintainer veto
window noted and still open: add a narrow useGrouping?: boolean mapping 1:1
to Intl.NumberFormat's useGrouping. Option B (displayFormat, a broader
presentation slot) explicitly rejected as capability surface without demand
per the maintainer's #7496 norm — narrowest shape with measured pull wins.

What changed

  • packages/spec/src/data/field.zod.tsFieldSchema gains useGrouping: z.boolean().optional(), flat alongside precision/scale/min/max
    ("Number Constraints"). Docblock explains the three-valued contract:

  • Tests added to packages/spec/src/data/field.test.ts: accepts explicit
    true/false, absent stays absent (no materialized default), rejects
    non-boolean, confirms Field.number(...) threading, confirms unknown-key
    strictness is unchanged, and pins the JSON-Schema projection (boolean
    type, no default, not in required) the way
    field-autonumber-default-format.test.ts pins autonumberFormat's.

  • Regenerated: authorable-surface/ + authorable-surface.base.json +
    json-schema/ (via pnpm gen:schema) and content/docs/references/data/field.mdx
    (via the docs gate), which now list useGrouping in the data/Field: key
    set / reference table.

  • packages/spec/liveness/field.json — classified the new key planned
    (not live): it has no runtime consumer yet, objectui#4033 is the
    consumer landing next. Not authorWarn'd, per the ledger's own rule —
    unlike a speculative future phase, an author who sets this today loses
    nothing and needs no re-authoring once the objectui half lands.
    packages/spec/liveness/state-counts.md regenerated to match
    (pnpm gen:liveness-counts); check:liveness is green.

Scope note — sibling authoring surfaces deliberately NOT touched

scale/min/precision also travel into two Setup-app admin field-editor
form definitions (packages/spec/src/data/field.form.ts,
packages/spec/src/data/object.form.ts) and into ui/view.zod.ts's
FormFieldBaseSchema (per-view field override for end-user Form views). I
checked all three; none were extended. Exposing useGrouping as a Studio UI
toggle (which would also need pnpm i18n:extract across 4 locale bundles) or
as a per-view override is a UX decision the ruling did not make, and Option A
was explicitly scoped to "the number field's authorable schema" — extending
those surfaces now would be widening past the ruled direction while the
maintainer veto window is still open. Flagging as a candidate follow-up.

Renderer contract (not implemented here)

explicit hint > interim heuristic > locale default. objectui#4033 is the
consumer that reads this key and retires the interim heuristic
(scale === 0 && no currency ⇒ ungrouped).

Gate results

Local, scoped to this surface (full commands/output in the dev report
comment on #7768):

  • pnpm --filter @objectstack/spec test (full package, 378 files): 376
    passed, 1 pre-existing failure (api-methods-batch-conformance.test.ts on
    sys_api_key, introduced by fix(platform-objects,plugin-auth): give API-key revoke/restore a working product route #7769, tracked as Queue-blocking: #7769 opened update on sys_api_key without bulkapi-methods-batch-conformance fails every merge-queue (full-suite) build #7793 — not touched by this
    PR), 1 file transiently red mid-run on my own uncommitted staleness
    (build-schemas-check-mode.test.ts, re-run clean after gen:schema: 60/60).
  • pnpm --filter @objectstack/spec typecheck: clean, zero errors.
  • pnpm --filter @objectstack/spec build: clean.
  • pnpm --filter @objectstack/spec check:generated: all 13 generated
    artifacts current.
  • check:adr-anchors, check:changeset-gate-self-tests (+ real
    empty-changeset/adr-0087-registration runs against the committed diff),
    check:docs-audit-scope, check:driver-conformance, check:merge-driver,
    check:release-body, check:spec-parsed-alias, check:nul-bytes: all
    green.
  • check:i18n — skipped: needs the built @objectstack/cli (prerequisite
    this worktree doesn't carry), and this PR touches no i18n-extraction
    surface (no field.form.ts/object.form.ts/translation file changed) so
    there is nothing for it to see.
  • --filter @objectstack/lint check:doc-formula-expressions — skipped: needs
    the built @objectstack/formula package, unrelated to this schema-only
    change (no formula-expression doc content touched).

Landing

Per the claim comment, this PR is expected to touch content/docs/references/**
and joins the os-regen one-at-a-time landing relay
(#7758#7759#7763#7782). Left as draft — the PM lands it.


Generated by Claude Code

FieldSchema gains an optional `useGrouping: boolean` (Option A, ruled
2026-08-11 on #7768, maintainer veto window open) so an authored number
field can opt out of Intl.NumberFormat's digit grouping without losing
numeric semantics -- the fix for years (Field.number({ scale: 0, min: 1900 }))
rendering as "2,026" that downstream apps have worked around three times by
converting to Field.text (hotcrm-heimao#35/#40/#59).
No default is declared: absent defers to the renderer (interim heuristic
today, locale default eventually -- objectui#4033's contract, not this
package's). Threads through Field.number(...) automatically via the
existing FieldInput shape, same as scale/min.
Also: liveness ledger classifies the key `planned` (objectui#4033 is the
pending consumer); authorable-surface/data.json, field.mdx and
state-counts.md regenerated to match.
@vercel

vercelBot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 12, 2026 9:05am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via @objectstack/spec)
  • content/docs/automation/connectors.mdx(via @objectstack/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/cli.mdx(via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/permissions/system-context.mdx(via packages/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/apps.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

7 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v16.mdx(via @objectstack/spec)
  • content/docs/releases/v17.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data tests tooling labels Aug 11, 2026
…main merge
Wholesale regen (gen:docs, gen:schema's authorable-surface projection,
gen:liveness-counts) to re-materialize artifacts that drifted from commits
main picked up since this branch's last merge — the `internal` field key
(#7728) and the `flows` translation surface's planned entries (#7763).
check:generated: 13/13 green; check:liveness: green.
@os-zhuang
os-zhuang marked this pull request as ready for review August 12, 2026 09:28
@os-zhuang
os-zhuang added this pull request to the merge queueAug 12, 2026
Merged via the queue into main with commit ef7b5efAug 12, 2026
29 of 30 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7768-number-usegrouping branch August 12, 2026 09:50
huangyiirene pushed a commit that referenced this pull request Aug 12, 2026
Rebase round for PR #7851 (#7521) after the domain:spec os-regen landing
relay tail landed on main (#7758, #7759, #7763, #7782, #7813, #7892).
Every `merge=os-regen` generated path is taken from origin/main WHOLESALE
(`git checkout origin/main -- <paths>`, the 12 entries .gitattributes names),
so this commit is a known-good base: the `os-regen` merge driver exits 0
without conflict markers while silently dropping one side, so a clean merge is
indistinguishable from a dropped baseline. Regeneration lands as a SEPARATE
commit on top of this one, and asserts the relay PRs' entries survived.
Committed with --no-verify deliberately: the os-regen pre-commit hook wants the
artifacts regenerated into this same commit, which would mix "what main brought"
with "what my change produces" into one indistinguishable blob. The very next
commit regenerates them, so the pushed tip is current.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tmmVmCkr4QtvGKMcn5s96
huangyiirene pushed a commit that referenced this pull request Aug 12, 2026
…ee (#7521)
Step 4 of the os-regen rebase, on top of the committed merge (cbea40d) whose
generated baselines came from origin/main wholesale.
`check:generated` proved exactly 2 of 13 artifacts stale — api-surface/ and
export-origins/, both this PR's own — and the other 11 current, so main's
baselines carried across the merge intact. Regenerated only those two.
The diff is 4 pure insertions and zero removals: the four exports
managed-api-affordance.ts adds. The relay tail's entries are asserted present
in the regenerated tree rather than assumed — the os-regen driver drops a side
silently, so a clean merge is not evidence:
#7763 TranslationBundle `flows` — content/docs/references/system/translation.mdx:161
#7813 Field.number `useGrouping` — packages/spec/authorable-surface/data.json
#7892 GlobalFilterSchema `object` — content/docs/references/ui/dashboard.mdx
#7782 InvitationStatus `canceled` — content/docs/references/identity/organization.mdx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tmmVmCkr4QtvGKMcn5s96
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/mteststooling

Projects

None yet

2 participants

@os-zhuang@claude