Repository navigation
feat(spec,cli): reports are translatable — reports in the translation bundle - #25826
Conversation
… in the translation bundle Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
…; review nits Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
📓 Docs Drift CheckThis PR changes 5 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 154 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 9cec64144e4d9b5f9eca6271af2b0f995836dd0e && git checkout 9cec64144e4d9b5f9eca6271af2b0f995836dd0e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f00e8d5c85392db7a3a7d4f41a4c3f619550d11d 5e30af5c5ca0cbd13d70f811614e720770f91f2c && git checkout -B drift-repro f00e8d5c85392db7a3a7d4f41a4c3f619550d11d && git merge --no-ff 5e30af5c5ca0cbd13d70f811614e720770f91f2c
node scripts/docs-audit/affected-docs.mjs --json f00e8d5c85392db7a3a7d4f41a4c3f619550d11d
|
Contract reviewServed-tier: ① Derived judgmentsThe Its readers — right, each verified in the cited code.
Removing The Regime O yield (ADR-0029 D9.2a) — verified against both ADRs. ADR-0126 section 3 lists Regime O as exactly ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
维护者速读改了什么 为什么改 风险与代价(含回滚) 席位意见 你要做的 席位核对Seat
|
…orts group objectui is now this repository's ui/ workspace, so the consumer half filed as objectui#13543 lands with the spec change: a reports row in the translation designer's CATEGORY_DEFS (en/zh heading keys), 'reports' in SPEC_TRANSLATION_GROUPS, and the two tests that pin both lists. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
…s edit The ui half of the reports group edits two registry sources (app-shell's TranslationPreview and metadata-admin i18n table, and i18n's spec-translations), so check-sdui-manifest's in-tree digest moved. Regenerated with scripts/gen-sdui-manifest-node.mjs: the manifest itself is byte-identical (106 components, sha256 1f6e1ccb925a), only the record's registrySourcesSha256 and date move. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
|
Generated by Claude Code |
Contract reviewServed-tier: This is a delta record. The PASS at ① Derived judgmentsThe spec/runtime half is unchanged, measured rather than assumed. Three commits sit between the two heads: a merge of The
The sdui digest re-record is the regeneration it claims. The diff on ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
|
Regen-provenance: 6407328168 · The seat merged |
维护者速读改了什么 为什么改 风险与代价(含回滚) 席位意见
唯一的红是 Test UI (11/16)。它是 main 上已知的同一个红,不是本 PR 引起的,也不是必需检查。 你要做的 席位核对Seat
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40265890690 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
…ain's demoStaff Merging origin/main (f00e8d5, #25830) stacked its demoStaff schema on this branch's reports group. The os-regen paths both sides moved are regenerated from the merged tree: api-surface, authorable-surface and export-origins carry both DemoStaff and the reports entries, and the strictness ledger's system/ row moves 381 -> 382. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF
|
Regen-provenance: 6407328168 · The merge queue dropped this PR (run 40265890690) because |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40271237932 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by 田騏 · project thread
Fixes #25788
Clause-②: yes
Metadata-protocol: added
Ruling-ref: none; triage first grade 6397355491 (a protocol addition under the standing order, p1)
Body refreshed 2026-10-26T02:56Z, after the
ui/merge (#25825): the console half now ships in this PR.What
A translation bundle can now carry reports:
Before, an app's reports listed in the authoring language on the console's report index and report page under any locale: the bundle had no key for a report (
reportswas a retired object-first dialect key, soos validaterefused it), andos i18n checkreported 100 % with zero report keys (HotCRM,✓ All 1691 translation keys covered).@objectstack/spec(system/translation.zod.ts): areportsgroup on the shared per-app shape, so the bundle entry (TranslationData), the registeredtranslationitem and the platform bundle all accept it. Keyed by the report'snameand closed atlabel/description(strict:name/titleare refused with a message pointing atlabel, and the singularreportwith a message pointing atreports).@objectstack/spec(system/i18n-resolver.ts):translateReport, registered inMETADATA_DOCUMENT_TRANSLATORS.TRANSLATABLE_METADATA_TYPESis derived from that table and@objectstack/restreads it, soGET /meta/report(list and item) is served in the request's locale. A key the bundle does not carry leaves the authored string, and an untouched document keeps its reference.@objectstack/metadata-protocol+@objectstack/rest: a report is overlay-editable (ADR-0126 Regime O), so likedashboardandviewits translator honours the packaged base (ADR-0029 D9.2a):getPackagedReportBase(name)returns the shipped document under any overlay, andPACKAGED_BASE_ACCESSORShands it to the translator. A label an org re-authored is served as written; the strings it did not touch are still translated.@objectstack/spec(liveness ledger):translation/reportsadded aslive, with drilledlabel/descriptionchildren, seeded with its reader.@objectstack/cli:os i18n extractwalksreports[](walkReports), andos i18n check/os lintcoverage report a gap in its own bucket (i18n/missing-report). Every key is recorded withpushOptional, so a description nobody wrote is never demanded.@objectstack/lint:translation-target-unknownresolves eachreports.NAMEkey against the stack'sreports[]names, sibling packages' declarations included; an unknown name is anerrorwith the nearest declared name.os explain translation-target-unknownnames the leg.scripts/fixtures/i18n-walk-parity/every-group.stack.json: authors one report, socheck:i18n-walk-paritysees the group walked.packages/runtimemeta-list projection census:report/reportsjoined both axes; the reference-moves blocks pin the zh-CN label on both reads.examples/app-todo(zh-CN, ja-JP),examples/app-showcase(zh-CN): translations for their 5 + 4 reports. The new walk counts them; deleting one todo key growscheck:i18n-coverage106 → 108, so the fix was to translate them, not to raise the ratchet.ui/(@object-ui/app-shell,@object-ui/i18n): the translation designer's preview draws thereportsgroup as a "Reports" / 「报表」 category beside the others, and the console's translation loader recognises a payload that carries onlyreports.protocol/kernel/i18n-standard.mdx(group list, count, leg table) andui/translations.mdx.Acceptance notes
The
LEGACY_OBJECT_FIRST_KEYScollision (the order's PM assumption), decided:reportsleaves the list.authored-translation-syncskips every stored translation row that carries one of those keys as a retired dialect, so a declared group still on the list would parse in a file and never load from a Studio-authored row. The legacy object-first dialect never usedreports(zero footprint, i18n: two unbridged bundle shapes — file-authoredobjects.<name>vs the runtimetranslationmetadata type'so.<object>, so translations cannot be authored in the product #3778), so nothing loses its retired-key diagnostic. ItsTRANSLATION_KEY_GUIDANCEentry goes with it. A test pins the removal.Deviation from the precedent's shape (and the reason): feat(spec,cli): positions and permission sets are translatable —
positionsandpermissionsin the translation bundle #25701 touched spec, cli and lint only, because positions and permission sets are not overlay-editable. A report is (ADR-0126 Regime O), so a translator that ignored the packaged base would overwrite an org's re-authored label with the catalog string, the metadata: a published org overlay on the built-in system_overview dashboard is never served — the plain read and the rendered board keep the shipped body while ?layers=true reports the overlay as effective #20680 defect class. Hence the two extra packages (metadata-protocol, one accessor;rest, one table row), inside the claim's "runtime meta translation path".The console half ships in this PR (app-shell + i18n: add the
reportstranslation group objectstack #25788 adds — TranslationPreview's CATEGORY_DEFS fails type-check at the next pin, and the console loader does not recognise a reports-only payload #25859, transferred here from objectui#13543). Since merge(ui): objectui becomes the ui/ workspace of this repository — subtree import at the frozen tip 9e1fe03286 plus the adaptation series (objectstack#25752) #25825 moved objectui into this repo asui/,Type Check UIandTest UIbuild against this tree'spackages/spec, so the console's exhaustive copies of the group list have to move with the group or this PR is red. The copies are:TranslationPreview.tsx'sCATEGORY_DEFS(satisfies Record<keyof TranslationDataSchema['shape'], …>), with its en / zh label keys inmetadata-admin/i18n.ts;spec-translations.ts'sSPEC_TRANSLATION_GROUPS, pinned byloadLanguage.test.tsx;TranslationPreview.categories-11765(ONE_ENTRY) andadminPreviews.i18n-10862-s2(its key list, and the2/13denominator becoming2/14).The report surfaces themselves (the report index
appReportIndex.ts, the page headingReportView.tsx, the header crumbAppHeader.tsx, the recent-items labeluseRecentItemLabel.ts) read the server-translatedGET /meta/reportand need no change. The earlier sequencing question (the scheduledConsole Pin Gategoing red until a.objectui-shabump) went away with the pin (release(ui-merge): one release lane for both scopes — @object-ui joins the fixed group, @objectstack/console builds from ui/apps/console, the objectui pin is deleted (#25711) #25745).ui/reads neitherLEGACY_OBJECT_FIRST_KEYSnorTRANSLATION_KEY_GUIDANCE(git grepatda49afeb6c: no hits). This PR does not carryFixes #25859, because the claim gate requires a claim naming this branch; app-shell + i18n: add thereportstranslation group objectstack #25788 adds — TranslationPreview's CATEGORY_DEFS fails type-check at the next pin, and the console loader does not recognise a reports-only payload #25859 closes after the merge.Out of scope, recorded: a joined report's
blocks[].label(ui/report.zod.ts, anI18nLabelSchema) is not on the face, soshowcase_task_overviewwill show a translated heading over its block labels as authored. The card asks forlabel/descriptiononly.No
!in the title and no(narrowing)arm, so no full dogfood run is owed.Receipts for the comments on this PR before this refresh:
i18n-standard.mdxandtranslations.mdxare updated in this PR.concepts/metadata-lifecycle.mdxnames no packaged-base accessor, sogetPackagedReportBasechanges nothing it says.blocks[].labelhas no key) is a follow-up for the seat to file, recorded above as out of scope.Console Pin Gate, no.objectui-sha.Verification
After the
ui/merge, at head378f52336f(main merged a third time atbbb49e33f1, clean, then theui/portda49afeb6cand the sdui re-record378f52336f). Every result is exit 0.TranslationPreview*,adminPreviews.i18n-10862-s2,packages/i18n/src,apps/console/src/loadLanguage.test.tsx), run fromui/: 91 files, 1424 passed, 13 skipped.ui/half stashed, the three pinned files fail 19 tests in 2 files, and app-shelltscreports TS1360 atTranslationPreview.tsx:103(CATEGORY_DEFSdoes not satisfy the record of 14 groups). With the port, that error is gone. The stash was popped andgit diffwas empty afterwards.check:i18n-keys,check:i18n-drift,check:i18n-designer-parity,check:i18n-dead-keys,check:spec-symbolsandcheck:icon-record-namespassed.check-sdui-manifest: theui/packages/i18nsource edit moved the in-tree registry digest, which reddenedLint · repo & tooling gatesonda49afeb6c.scripts/gen-sdui-manifest-node.mjsregenerated it.sdui.manifest.jsonis byte-identical (sha2561f6e1ccb925a…, 106 components); only the record'sregistrySourcesSha256andgeneratedAtmoved. The gate now passes, locally and in CI.dispatch-gates --commandsderived 135 families, the same list atda49afeb6cand378f52336f. Each ran with its exit code captured before any pipe: 134 atda49afeb6cand the sdui gate again at378f52336f, all 135 exit 0.--ranreports 135 run, 0 NOT-MEASURED, 0 UNRUN.@types/reactunhoisted, so@object-ui/components' declaration build failed locally on three third-party typings in files this PR does not touch. The generator ran after@types/reactand@types/react-domwere hoisted locally; no install change is committed.ui/packages/components/is unchanged frommain, whereType Check UIbuilds it green.Before the
ui/merge, all at headac2bcb0ba(main merged twice, the second clean) unless noted. Every result is exit 0.test:repoona79e5bc2; resttest, lint and cli onf6725a90, before the first merge):@objectstack/spec:test21849 passed,test:repo1269 passed.@objectstack/runtime:test7100 passed,test:repo947 passed.@objectstack/objectql:test8723 passed.@objectstack/metadata-protocol:test21490 passed.@objectstack/rest:test6737 passed,test:repo280 passed.@objectstack/lint:test7302 passed.@objectstack/cli: unit project 4848 passed.ac2bcb0ba: specsrc/system(1974), the cli report walk (4), lintvalidate-translation-references(209), rest explicit-override (76), runtime projection census (878) and the new objectql accessor file (5) re-ran green, and spectsc --noEmitpassed.typecheckpassed forspec,cli,lint,rest,metadata-protocol,runtime,example-todoandexample-showcase.dispatch-gates --commandsatac2bcb0baderived 134 families. A fullturbo run buildcame first. Each family ran with its exit code captured before any pipe, and all 134 exited 0.--ranreports 134 run, 0 NOT-MEASURED, 0 UNRUN.check-engine-split-ratio --days 90first refused (exit 2) because the clone was shallow. Aftergit fetch --shallow-since=2026-07-20it passed.check:i18n-coverage: OK, 527 baselined, none new.--updatemoved nothing.zh-CNreport key in app-todo turns it red (106 → 108), then the file was restored.check:i18n,check:i18n-walk-parity(14 declared, 12 walked, 2 exempted),check:generated: green.git diffempty afterwards:report: translateReport,turnsi18n-report.test.tsred (2 of 16 failed).walkReports(config, out);call turnsi18n-report-walk.test.tsred (4 of 4 failed).['report', 'getPackagedReportBase']row turns the REST explicit-override file red (9 failed: §1 and every §4 edited-label cell).os i18n checkreports 100 % with zero report keys while the console's Reports index shows every report in English under zh-CN #25788 comment 6399284479. Round 3 (the merge, theui/port and the re-record) is spec/i18n: a report's label and description have no translation key —os i18n checkreports 100 % with zero report keys while the console's Reports index shows every report in English under zh-CN #25788 comment 6407105388; its one nit is that378f52336f's message credits app-shell as well as i18n for the digest move, when app-shell is not a registry package.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01BUeRMD4VYCYUfzxTKcZFAF