Uh oh!
There was an error while loading. Please reload this page.
spec: GlobalFilterSchema gains optional object for i18n label resolution (#7804) - #7892
Conversation
…l resolution (#7804) GlobalFilterSchema gains an optional `object?: string` (Route A, ruled on the triage-seat comment on #7804, 2026-08-11) so a dashboard global filter's field label (e.g. "Sales Channel:") and its option labels resolve through the same `fields.<object>.<field>` translation-bundle convention lists/forms already use -- zero new i18n vocabulary, one resolver path. Rejects Route B (a new `dashboards.*.filters` bundle node -- duplicate vocabulary, no precedence rule) and Route C (inline I18nLabelSchema forms -- orthogonal, tracked separately). Deliberately independent of `optionsFrom.object`, which names the object dynamic OPTIONS are fetched from and may differ (e.g. filtering `opportunity` by `owner` with options sourced from `user`). Additive optional key: nothing that parsed before stops parsing. Unblocks objectui#4324, the dashboard filter-bar renderer half already landed behind this key. Also: content/docs/references/ui/dashboard.mdx and packages/spec/authorable-surface/ui.json regenerated to match (`pnpm --filter @objectstack/spec gen:docs`; check:generated all 13 green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
…ema.object (#7804) pnpm --filter @objectstack/spec gen:docs after adding the schema key; check:generated all 13 artifacts green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
…e-match) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
pnpm --filter @objectstack/spec gen:schema; check:authorable-surface green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
…tion (#7804) The schema-source half of the change: `object?: string` on GlobalFilterSchema between `field` and `label`, documented as distinct from `optionsFrom.object`. See the changeset for the full rationale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
New describe block: accepts string, optional/absent, rejects non-string, independence from optionsFrom.object, unknown-key strictness unchanged, JSON-Schema pin (string slot, not required). pnpm --filter @objectstack/spec test: 378 files / 9954 tests passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
…e-match local) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
…transcription) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY2Q5Xto1u8YHADgrZDTnk
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
…s-regen driver's second half `authorable-surface/ui.json` carries `merge=os-regen`, so a merge resolves it by taking a side and leaving it REGEN-PENDING rather than by textually splicing two generated files. That is the driver working as designed; the half that must follow is the regeneration, and it is not optional here — measured on the merged tree before pushing, `check:authorable-surface` fails: ❌ authorable-surface/ is out of date (1 key(s) not recorded). + ui/GlobalFilter:object The missing key is main's own, from #7892 (`GlobalFilterSchema` gains an optional `object` for i18n label resolution). Nothing of this branch's is involved: the regenerated diff is exactly that one line, and batch A's five declared keys were already recorded. Worth stating because the failure mode is quiet: `pnpm build` REWRITES this artifact, so a `check:generated` run that happens to follow a build reports all 13 green against the file the build just fixed. Only `check:authorable-surface` on its own, against the merged bytes, shows the drift — which is how this was caught before the merge queue caught it. Merged tree verified: spec 381 files / 10091 tests, lint 71 / 1932, check:generated 13/13, check:strictness-ledger current (438 sites / 149 strip / 9 authorable — unmoved by the merge). The ledger counts and liveness counts were regenerated too and came back byte-identical. Part of #4001 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NLJ8PWLdwLSyi84LHzrAx
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
…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
Fixes#7804
Problem
A dashboard global filter renders its field label (e.g. "Sales Channel:") and its option labels untranslated, and there was no key to fix it with:
GlobalFilterSchemadeclared noobject, and neither doesDashboardSchema, so the canonicalfields.<object>.<field>translation-bundle convention that lists/forms already use has nothing to resolve against. Measured in objectui#4324's implementation, and hit in production on a hotcrm-heimao dashboard.Fix (Route A, ruled on the triage-seat comment on #7804, 2026-08-11)
Adds an optional authorable
object?: stringtoGlobalFilterSchemainpackages/spec/src/ui/dashboard.zod.ts, betweenfieldandlabel. When set, it names the objectfieldlives on, and the filter's field label and option labels resolve through the samefields.<object>.<field>bundle entry lists/forms already use — zero new i18n vocabulary, one resolver path.Deliberately independent of
optionsFrom.object, which names the object dynamic options are fetched from and may differ (e.g. filteringopportunitybyownerwith options sourced fromuser).Rejects Route B (a new
dashboards.*.filtersbundle node inTranslationData— duplicate vocabulary, no precedence rule) and Route C (inlineI18nLabelSchemaforms — orthogonal, tracked separately on objectui#4163).Additive and optional: a filter that omits
objectrenders exactly as it always has. Nothing that parses today stops parsing. Unblocks objectui#4324, the dashboard filter-bar renderer half already landed behind this key.This PR is a continuation
Branch
claude/issue-7804-globalfilter-objectwas pushed by an earlier dev session that died before opening a PR or reporting (handoff note on #7804). This session fetched the existing branch into a dedicated worktree, reviewed every commit (schema change, tests, changeset, regenerated docs/authorable-surface), mergedorigin/main(clean, no conflicts), and re-ran full verification from scratch — nothing here was trusted blindly.Changes
packages/spec/src/ui/dashboard.zod.ts—GlobalFilterSchema.object(optional string)packages/spec/src/ui/dashboard.test.ts— newdescribeblock pinning: accepts string, optional/absent (no default materializes), rejects non-string, independence fromoptionsFrom.object, unknown-key strictness unchanged, JSON-Schema pin (string slot, not required)content/docs/references/ui/dashboard.mdx— regenerated (gen:docs)packages/spec/authorable-surface/ui.json— regenerated (gen:schema).changeset/global-filter-object-i18n-7804.md— minor bump on@objectstack/specVerification (this session, re-run in full)
pnpm --filter @objectstack/spec build— green, tree clean after (generated artifacts already matched, no diff)pnpm --filter @objectstack/spec typecheck— green (tsc --noEmit,check:scripts-typecheck,check:test-typecheck)pnpm --filter @objectstack/spec test -- --maxWorkers=2— 379 test files / 9989 tests passedpnpm --filter @objectstack/spec check:generated— all 13 generated artifacts up to date, includingcheck:authorable-surfaceandcheck:docspnpm check:i18n(after building@objectstack/cli) — 9 packages, all bundles in sync, no undeclared authoring keyspnpm --filter @objectstack/lint run check:doc-formula-expressions— green (self-test 24/24, 22 + 9 example sites judged clean)pnpm check:adr-anchors,check:changeset-gate-self-tests,check:docs-audit-scope,check:merge-driver,check:release-body,check:spec-parsed-alias,check:nul-bytes— all greenCI (ESLint job, TypeScript Type Check job, and the rest of the gate farm) has not been waited on from this session per the current reporting contract — the PM reads real gate-job conclusions before any ready-flip.
Generated by Claude Code