Repository navigation
feat(spec): settings info_banner translation slot — banners.ID.{title,text} and its two resolvers - #23886
Conversation
Add settings.<namespace>.banners.<banner_id>.{title,text} to the platform
translation contract, keyed by the info_banner specifier id, with
strictObject aliases for the borrowed specifier spellings, plus
resolveSettingsBannerTitle / resolveSettingsBannerText in the
resolveSettings* family.
Claude-Session: https://claude.ai/code/session_01MbQTsgWtBx7fxYsCN5UKgC
Co-authored-by: Claude <noreply@anthropic.com>
…nd strictness ledger Claude-Session: https://claude.ai/code/session_01MbQTsgWtBx7fxYsCN5UKgC Co-authored-by: Claude <noreply@anthropic.com>
…ttings-banner-translation-slot
📓 Docs Drift Check4 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 142 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 b7c1381b5f3ab7cd22e273ea2ed504c1aeee911b && git checkout b7c1381b5f3ab7cd22e273ea2ed504c1aeee911b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 94114c1f269f6b3d885f24b6f4689dce29504574 1f081ab7c11fbe7fb7dd13a9ab24bd62a6aacbd4 && git checkout -B drift-repro 94114c1f269f6b3d885f24b6f4689dce29504574 && git merge --no-ff 1f081ab7c11fbe7fb7dd13a9ab24bd62a6aacbd4
node scripts/docs-audit/affected-docs.mjs --json 94114c1f269f6b3d885f24b6f4689dce29504574 |
Contract reviewServed-tier: Read in this act, clock 2026-10-16T12:21Z: card #23855 body and all three comments (first grade ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
席位核对 · ACCEPT · PR #23886 @
|
Fixes #23855
Clause-②: yes
What changed
The platform translation contract gains a slot for a settings
info_bannerrow, and theresolveSettings*family gains its two readers.packages/spec/src/system/translation.zod.ts—platformSettingsShapedeclaressettings.NAMESPACE.banners.BANNER_ID.{title,text}, keyed by theinfo_bannerspecifier'sid, besidegroups/keys/actions. It is built with the samestrictObject({ surface, history, aliases })helper as its siblings. The convention list in the docblock names the two new paths.label,name,heading→title;bannerText,body,description,message→text.banner,notices,alerts→banners. A wrong key now gets a named remedy, not a bareunrecognized_keys.packages/spec/src/system/i18n-resolver.ts—resolveSettingsBannerTitleandresolveSettingsBannerText. They walk the requested locale and then the declared fallback chain, and finally return the manifest literal (label/bannerText).packages/spec/src/system/settings-manifest.zod.ts—SpecifierSchema.idTSDoc namesinfo_banneramong the specifiers whose text is looked up byid. TSDoc only: nosuperRefine, and the specifier's accept set is unchanged.api-surface/system.jsonandexport-origins/system.json(+2 exports each),content/docs/references/system/translation.mdx, strictness-ledger counts (system/373 → 374)..changeset/23855-settings-banner-translation-slot.md—minor,Clause-②: yes (widening).Spelling: why
title/textThe specifier carries
labelandbannerText. The nearest house precedent isgroups: agroupspecifier'slabeltranslates asgroups.ID.title. So the banner's heading reuses that leaf name,title. For the body there is no sibling that holds the same field.descriptionon a group is the specifier'sdescription, a different field, so reusing it would invite confusion.textis the card's proposal and names thebannerTextfield it translates. The specifier's own spellings and the group'sdescriptionare aliases, so the likely borrowings are refused with the right leaf.Who reads it
Measured at
origin/main7a6ba03109:git grep "resolveSettings[A-Z]"outsidei18n-resolver.tsfinds only the generated baselines and docblocks. The family has no caller in objectstack outside its own exports. The objectui console resolves by convention in its own hook. That hook was not measured here, because no objectui checkout exists in this container. The resolvers are the family's executable statement of the convention. Rendering the slot in the console is a follow-up card in objectui, filed at landing. This PR makes no claim that the console renders it yet.Verification (head
1f081ab7c1unless noted)packages/spec/src/system/settings-banner-translation.test.ts, 8 tests.bannerText/label/descriptionon a banner and the singularbannergroup are each refused at the right path, namingtext/title/banners.scripts/ablation-replace.mjs, restore proven by blob == HEAD and an emptygit diff HEAD):bannerskey out of the shape: 4 schema pins go red (accept, plus the three leaf-alias refusals). The singular-bannerpin stays green, because its alias lives one level up.resolveSettingsBannerTitleatgroups.ID.description: 2 resolver pins go red (hit, fallback chain).resolveSettingsBannerText: the same 2 go red.settingsBuiltinTranslations(en,zh-CN,ja-JP,es-ES) withPlatformTranslationDataSchema. All four parse.@objectstack/spec:typecheckexit 0. The fullvitest runat63894195e5(pre-merge) passed 748 files, 21985 tests. Rerun on the merged head: see the report.pnpm --filter @objectstack/spec check:generatedafter a real build: all 14 artifacts up to date, before and after mergingorigin/main.dispatch-gates --commands): 109 of 109 exit 0, reconciled with--ran(a derived zero, all exit codes recorded). Nine first exited 3 (prerequisite: unbuilt workspace or a shallow clone). After a workspace build and an unshallow fetch, all nine exit 0.Acceptance notes
.objectui-shaat this base pinsdaeb77fc84. That is the card's pin, not the1f23d5b070the dispatch named. Noted, not acted on.beta_notice(feature-flags.manifest.ts) already carries anid, so it is addressable as soon as service-settings: the storage, knowledge and AI manifests carry their ⚠ warnings inside description and help strings; move each into aninfo_bannerrow (bannerSeverity: warning), item 2 of objectui#12610 #23839 adds its three locale copies. service-settings: the storage, knowledge and AI manifests carry their ⚠ warnings inside description and help strings; move each into aninfo_bannerrow (bannerSeverity: warning), item 2 of objectui#12610 #23839 is not addressed here.Generated by Claude Code