Repository navigation
Description
domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo
carries item 7 of #31391; #31391 keeps items 1–6 and 8 (PR #31451).
Filing gate: ④ coordination child, the spec layer of #31391 item 7, under #30208 row 5 (ruling record 6715997428, option A).
Business reason: an administrator using Setup in Chinese (or any non-English locale) sees Data Lifecycle's map tables headed in English (Object, Keep rows for, Expire rows after, Max rows, Lifecycle class) beside translated labels and help text. Until this lands, those five headers cannot be translated by any bundle.
Reader: a domain:spec seat first (the translation schema), then the domain:ui seat (the console reads the new group; a small follow-up in ui/apps/console/src/pages/settings/SettingsMapField.tsx).
Dedupe (open AND closed): map specifier columns translation, keyColumn label translation → #31391 and #30208 only; none is this group.
reach: Setup → Data Lifecycle in any non-English locale, once PR #31451 draws the map tables (the headers render keyColumn.label / columns[].label as served).
维护者速读
数据生命周期的三张 map 表(保留期覆盖、行数配额、按类默认配额)表头是英文字面量,现在没有地方可以翻译。要在设置的翻译结构里给每个键加一个 columns 分组(键列 + 各值列的标签),控制台再读它。存储与保存门不变。
Readings (origin/main 216b18a6c)
- The literals:
packages/objectql/src/lifecycle/lifecycle-settings.ts~L51–80 (keyColumn: { label: 'Object' },{ name: 'maxAge', label: 'Keep rows for' },{ name: 'expireAfter', label: 'Expire rows after' },{ name: 'max_rows', label: 'Max rows' },keyColumn: { label: 'Lifecycle class' }). - The settings
keys.<key>translation entry inpackages/spec/src/system/translation.zod.tshas nocolumnsgroup (the card Console: draw themapsettings specifier as a table of keyed rows (Data Lifecycle retention overrides and quotas) #31391 body, item 7: "Translating them needs acolumnsgroup in the settingskeys.<key>translation entry … and ui's copies of that schema"). - PR feat(console): draw the map settings specifier as a table of keyed rows #31451 renders the headers through
pickLocalized, so an inline locale map would already show; a bundle-keyed group is what is missing.
Expected
- Spec: the settings
keys.<key>translation entry gains an optionalcolumnsgroup (the key column's label and each value column's label, by columnname), with the strictness the sibling groups use. - The lifecycle settings' zh-CN (and other shipped) bundles carry the five headers.
- Console: the map control reads the group (ui follow-up on this card or a child, as the spec seat cuts it).
Activity
objectstack-fleet commentedon Nov 8, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p3 ·
domain:spec· 2026-11-08T08:54Z⛔ Not a claim.
mapsettings specifier as a table of keyed rows (Data Lifecycle retention overrides and quotas) #31391 / PR feat(console): draw the map settings specifier as a table of keyed rows #31451) head their columns with English literals fromlifecycle-settings.ts. The settings translation schema has no place for them. The ask is acolumnsgroup per key (the key column and each value column), which the console then reads.domain:specfirst, for the translation schema, under the spec red line. The ui follow-up inSettingsMapField.tsxis a small paired card once spec lands.pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 8, 2026
domain:spec#4 · marchtian · session_017ihL2eAG5J8aqAyPZif4BJ
Claim: PM loop round 6 · 2026-11-08T09:51Z
Session:
session_017ihL2fxVwyhFFqT657pqUh(card thread; dispatched by seat sessionsession_017ihL2eAG5J8aqAyPZif4BJ)Account:
marchtianBranch:
claude/project-thread-b3hqevWorktree: the card thread's own container checkout (
objectstack-issue-31453)Domain:
domain:specSeat:
domain:spec#4Ruling-ref: triage 6719503629 (spec translation schema first; the console read is a paired ui follow-up once spec lands). Seat: the overlay goes wherever
keys.<key>.labelis overlaid today, in this PR, so that the new leaves are enforced and not just declaredFile surface:
packages/spec/src/system/translation.zod.ts(+ test, regenerated references), the settings-translation overlay site (measured by the dev:@objectstack/service-settings/packages/objectql, orui/apps/console/src/pages/settings/SettingsMapField.tsxif the console overlays), the lifecycle settings bundles that already translate the namespace'skeys, and changesetsContainer & model:
M,mode:thread,model: default tier,effort: default; independent Fable review of the spec diff before ACCEPT (the maintainer's standing spec rule)Clause-②: yes — the bundle schema accepts the new
keyColumn/columnsleaves it refused beforeMetadata-protocol: none
Responsibility: n/a — the five map-table headers cannot be translated by any bundle today
Thread-read: 6719503629
Premise: holds (
settings.<ns>.keys.<key>declares label/help/placeholder/options/confirmOffText and no column leaf;lifecycle-settings.tscarries the five literals); the dev re-measures on its baseSerial constraints cleared: none (disjoint from #31380 / PR #31456); PR #31451 (domain:ui) draws these tables, and the dev states whether this branch is serial behind it
objectstack-fleet commentedon Nov 8, 2026
domain:spec#4 · marchtian · session_017ihL2fxVwyhFFqT657pqUh
os-dev-report
{ "card": 31453, "status": "pr_open", "pr": { "number": 31484, "head_sha": "7d137518f17b648f28560b3f2d859c964cf2d176", "draft": true, "branch": "claude/project-thread-b3hqev" }, "premise_still_valid": true, "premise_reading": "origin/main 3c380253: settings.NAMESPACE.keys.KEY declared label/help/placeholder/options/confirmOffText and no column leaf; lifecycle-settings.ts carries the five header literals; PR 31451 (SettingsMapField) merged as f88ca70e.", "files_changed": [ ".changeset/31453-settings-map-column-translations.md", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md", "packages/services/service-settings/src/translations/ar.ts", "packages/services/service-settings/src/translations/de.ts", "packages/services/service-settings/src/translations/es-ES.ts", "packages/services/service-settings/src/translations/fr.ts", "packages/services/service-settings/src/translations/ja-JP.ts", "packages/services/service-settings/src/translations/ko.ts", "packages/services/service-settings/src/translations/pt-BR.ts", "packages/services/service-settings/src/translations/ru.ts", "packages/services/service-settings/src/translations/settings-translation-coverage.test.ts", "packages/services/service-settings/src/translations/zh-CN.ts", "packages/services/service-settings/src/translations/zh-Hant.ts", "packages/spec/src/system/settings-manifest.zod.ts", "packages/spec/src/system/translation.test.ts", "packages/spec/src/system/translation.zod.ts", "ui/apps/console/src/pages/settings/SettingsField.tsx", "ui/apps/console/src/pages/settings/SettingsMapField.tsx", "ui/apps/console/src/pages/settings/__tests__/SettingsView.mapRows-31391.test.tsx", "ui/apps/console/src/pages/settings/useSettingsLabel.ts" ], "line_budget": { "insertions": 350, "deletions": 11, "files": 20, "over_3000": false }, "gates": { "dispatch_gates": "97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN (dispatch-gates --ran exit 0)", "first_pass_exit_3": [ "check-plugin-teardown-shape --self-test (fixture commit absent from shallow clone)", "spec check:api-surface, check:browser-reachable-entries, check:dual-source-exports, check:entry-nameability, check:exported-any, check:generated (stale dist)", "check:dual-build-cjs-loads, check:i18n-walk-parity (unbuilt packages)" ], "after_build_and_fetch": "all 9 exit 0", "extra": [ "spec check:generated :: exit 0", "check:doc-authoring :: exit 0", "eslint on touched packages files :: exit 0", "eslint on touched console files :: exit 0 (2 pre-existing warnings)", "turbo type-check @object-ui/console :: exit 0", "spec translation.test.ts + src/shared :: 1224 pass", "service-settings src/translations :: 135 pass", "console SettingsView.mapRows-31391 + useSettingsLabel suites :: 22 pass", "check:test-typecheck :: exit 0 with NODE_OPTIONS heap 12288 (local OOM only; debt not regenerated)" ] }, "proof": { "spec": "leaves parse on platform face, platform bundle and served document; entry aliases name targets; undeclared column leaf refused at its path; bare string refused as invalid_type at its path; pasted specifier column gets the columns.NAME prescription, no name rename", "coverage_mutation": "renaming zh-CN expireAfter to expireAt reds both missing (columns.expireAfter) and undeclared (columns.expireAt)", "overlay_reverse": "with headerText unwired in SettingsField, both new console cases red (headers stay Object / Keep rows for / ...)", "zh_cn_before_after": "retention_overrides headers: before Object | Keep rows for | Expire rows after; after 对象 | 行保留时长 | 行过期时长" }, "deviations": [ "Shape: keyColumn is an object {label, help}, not the plain string the order proposed. Measured: SpecifierMapKeyColumnSchema declares label AND description; SpecifierMapColumnSchema declares label, description, kind, name. description is user-visible (value column headers render it as title), so both groups are {label, help}; the key column now also shows its declared description as hover text so the help leaf is read.", "Changeset level: @objectstack/spec patch, not minor. Metadata-protocol none grades every entry patch (check-changeset-no-major.mjs); none holds because settings is platform-only (both application doors refuse it) and authorable-surface does not move.", "Overlay location: keys.KEY.label is overlaid in the console (useSettingsLabel), not server-side; the new read rides this PR as cross-lane ui files (useSettingsLabel.ts, SettingsField.tsx, SettingsMapField.tsx, map rows test).", "Aliases: key_column dropped after review (distance fallback already answers keyColumn); column-level name alias replaced by a prescription." ], "ui_exhaustive_copies": "not moved: nested leaf, SpecTranslationData forwards settings opaquely; only useSettingsLabel enumerates settings-key leaves and it is extended here", "serial": "PR 31451 merged; no open PR on these files found", "open_questions": [], "out_of_scope_findings": [], "fable_review": { "comment": 6720495586, "round1": "PASS with should-fix (3 should-fix, 3 nits), all fixed", "round2": "PASS on delta 7d137518" }, "mcp_calls": { "reads": [ "issue_read x3 (31453 get/comments x2)", "pull_request_read get_files 30489 (precedent)" ], "writes": 0 }, "api_writes": [ "relay pr_create 31484 (run 42472548071, read-back identical)", "post-stamped comment 6720495586 on PR 31484", "post-stamped os-dev-report on 31453 (this comment)" ] }objectstack-fleet commentedon Nov 8, 2026
domain:spec#4 · marchtian · session_017ihL2eAG5J8aqAyPZif4BJ
ACCEPT → PR #31484 comment 6720589885 · head
7d137518f· 2026-11-08T10:54ZCONTRACT_REVIEW_TIER(widening face; spec diff plus the console read that enforces it): PASS at7d137518(6720589885), no must-fix or should-fix, three nits.keyColumnis{label, help}, not a plain string.SpecifierMapKeyColumnSchemadeclaresdescriptiontoo (settings-manifest.zod.ts:97-116), so the order's "carries onlylabel" was wrong.patch.Metadata-protocol: noneforces patch in check-changeset-no-major; the order's "none+ spec minor" pairing could not pass.useSettingsLabel. That is wherekeys.<key>.labelis overlaid today. No server overlay exists, soSettingsField.tsx/SettingsMapField.tsxride as cross-lane ui files, named in the body.Clause-②: yes (widening)andMetadata-protocol: none: confirmed.settingsstays platform-only (PER_APP_SETTINGS_PLATFORM_ONLY), and the app face is unchanged.label/help; strict; the aliasesdescription→help,title→label,headers/columnLabels→columns,keyHeader→keyColumn; old bundles parse unchanged; platform-only;titlefrom itsdescription, while value columns already carriedtitle={c.description};columnsrecord key is unconstrained, like its siblingoptions.objectstack-fleet commentedon Nov 8, 2026
domain:spec#4 · marchtian · session_017ihL2eAG5J8aqAyPZif4BJ
Landed ·
domain:spec#4· 2026-11-08T11:49Z7d137518f; merge commit76e4c2cdf1e6f411b98f6520c0a2bc83ebbd68c4. Contract review PASS 6720589885; ACCEPT on this cardFixesState:
pm:dispatchedremoved. The three accepted nits are recorded only:columnsrecord key is unconstrained, like its siblingoptions.