Skip to content

fix(platform-objects): the zh-CN dashboard metadata-form subtree says what its source says - #14926

Merged
os-musk merged 3 commits into
mainfrom
claude/issue-14587-zh-cn-dashboard-sections-layout
Sep 3, 2026
Merged

fix(platform-objects): the zh-CN dashboard metadata-form subtree says what its source says#14926
os-musk merged 3 commits into
mainfrom
claude/issue-14587-zh-cn-dashboard-sections-layout

Conversation

@os-musk

@os-musk os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Part of #14587.

The zh-CN metadataForms.dashboard subtree now says what its source
(packages/spec/src/ui/dashboard.form.ts) says. Five leaves, which is the
scope the card's triage ruling set: two named leaves plus a sweep bounded to the
dashboard subtree.

leaf zh-CN was zh-CN now source
sections.layout.description 栅格与响应式 栅格尺寸与刷新间隔 :21 Grid sizing and refresh cadence.
sections.basics.description 名称与图标 仪表板标识与描述 :11 Dashboard identity and description.
sections.widgets.description 图表、指标、列表等 放置在栅格上的卡片与图表 :32 Cards and charts placed on the grid.
sections.filters.description 全局筛选与日期范围 应用到所有组件的默认筛选与全局筛选 :39 Default and global filters applied across widgets.
fields.header.helpText 标题、操作按钮与筛选 仪表板页眉配置(title、subtitle、actions) :27 Dashboard header config (title, subtitle, actions)

Each old value named a concept the source omits while dropping one it names.
Wording is taken from this bundle's own established terms — grid is 栅格,
widgets is 组件, identity is 标识 (as in 应用标识与启用状态 for App identity and activation.), and the literal key list is rendered (title、subtitle、actions)
the way page.fields.layout.helpText renders (header、main、sidebar、footer).
es-ES and ja-JP are correct at all five and were the reference.

Why Part of and not a closing keyword

Part 2 of the card — whether drifted leaves can be reported at all — stays open
after this PR, so merging this must not close the card. That half is now tracked
separately as #14931 (⛔ not #14929 — an earlier comment on the card cited that
number before the card existed and has since corrected itself; #14929 is an
unrelated issue), and the remaining stale leaves outside this subtree belong to
it, not here.

A. ⭐ Two of the five pointed authors at controls that do not exist

sections.layout promised a responsive-breakpoint input; the section holds
columns, gap, refreshInterval and header (dashboard.form.ts:19-29), and
the refresh cadence it does hold went unnamed.

sections.basics promised an icon input. That section holds name, label
and description (dashboard.form.ts:9-18), and the dashboard schema declares
no icon key at all — the only icon under packages/spec/src/ui/dashboard.zod.ts
is per header action (:97, Icon identifier for the action button). So the
string asserted a UI element that has never existed anywhere on this form.

The other three swapped which concepts the section covers: widgets is cards and
charts on the grid, not metrics and lists; filters is default plus global filters
across widgets, not the date range (that is the separate dateRange field, whose
own helpText already says so); and the header carries a subtitle, not filters.

B. All five were still stale at the branch head, and no source moved

Every source string is byte-identical across that file's only two commits
c7707850d (2026-05-28, file creation) and 12a19a88a (2026-07-30, which only
removed inert keys from the Advanced section). Verified by reading both blobs,
not inferred.

⇒ Not drift after a source edit — a mistranslation at authoring time. All three
locales were seeded with the English verbatim (ae2da1e7d); es-ES and ja-JP were
then translated from it (874cb084e), while zh-CN alone was overwritten the same
day by e0077ea36, which imported the pre-consolidation
src/metadata-translations/zh-CN.ts overlay (746 lines deleted) and never
reconciled it against the seeded English.

C. Subtree sweep: the dashboard subtree holds 30 leaves, and no others are stale

Both bundles were flattened to dotted leaf paths (767 each, key sets identical
across all four locales) and the 30 under dashboard were compared leaf by leaf
against en. Beyond the five above, none asserts a concept the source omits or
drops one it names. Two near-misses are recorded so the threshold is auditable
rather than asserted, and neither was touched:

  • sections.advanced.description — 性能与无障碍 for Accessibility and performance tuning. Same two concepts, order reversed. Accurate.
  • fields.header.label — 页眉 for Header. A narrower term than es-ES
    Encabezado / ja-JP ヘッダー, but it names the same region and asserts nothing
    extra. Left as the bundle's own established term, and reused in the helpText
    above so the label and its help text share one vocabulary.

D. ⭐ The gate blindness is now PROVEN, not assumed — a control was added

The previous round measured all three i18n gates green with a stale string in
place. A green ablation alone cannot distinguish "the gate is blind" from "the
gate never read this file", so this round ran a positive control first: the
same leaf, but with the KEY deleted rather than the value made wrong.

LEG 1 — CONTROL: delete the leaf key entirely
  removed-text occurrences : 1 -> 0     injected-text occurrences: 0 -> 1
  on-disk blob 76d1ce5a8 (HEAD 5c1965222); grep of the fixed value: 0 hits
  EXIT=1  pnpm check:i18n              check-i18n-bundles: 1 bundle problem(s)
  EXIT=0  pnpm check:i18n-stale-fill   OK (10 bundle set(s) — no new stale fills, 0 baselined)
  EXIT=0  pnpm check:i18n-coverage     OK (13 config(s), 691 baselined untranslated string(s), none new)
  restore: blob 5c1965222 == HEAD; git diff HEAD empty

LEG 2 — ABLATION: key present, value made stale again (名称与图标)
  fixed-value occurrences: 1 -> 0      stale-value occurrences: 0 -> 1
  on-disk blob 5db3b5973 (HEAD 5c1965222)
  EXIT=0  pnpm check:i18n              OK (9 package(s) — all bundles in sync, no undeclared authoring keys)
  EXIT=0  pnpm check:i18n-stale-fill   OK (10 bundle set(s) — no new stale fills, 0 baselined)
  EXIT=0  pnpm check:i18n-coverage     OK (13 config(s), 691 baselined untranslated string(s), none new)
  RESTORE OK: blob 5c1965222291b1f40b7e93442f9fe9b8eb0b6575 == HEAD blob 5c1965222291b1f40b7e93442f9fe9b8eb0b6575

Leg 1 going red is what makes leg 2 a reading: check:i18n demonstrably parses
this exact file from disk, with no rebuild in between, and still returns OK on a
wrong value. ⇒ No gate fired on any of the four new corrections — a
re-confirmation of the previous round's finding, with the boundary now drawn
precisely: the gate detects a missing KEY (a fresh extract refills it, which is
drift) and is blind to a wrong VALUE, because merge mode treats any non-empty
value as already-translated. Both legs restored from HEAD with blob equality
asserted, and the script carried a trap ... EXIT INT TERM restoring by absolute
path.

E. The producer was established before the file was hand-edited

The triage named the trap: do not hand-edit a regenerated bundle. Confirmed by
running the real producer, not by reading its docstring:

pnpm i18n:extract      -> exit 0, "Generated 11 file(s)"; all 11 rewritten
git status --porcelain -> empty
blob before 5c1965222291b1f40b7e93442f9fe9b8eb0b6575
blob after  5c1965222291b1f40b7e93442f9fe9b8eb0b6575

Merge mode preserves every hand-edited leaf value, so the documented
regeneration command reproduces this commit byte for byte. zh-CN.source-hashes.generated.ts
is unchanged and stays correct: these five leaves are legacy-trusted, carrying no
digest before or after, because none is a byte copy of any source revision.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
(no path arguments). The first derivation warned STALE TREE, so origin/main was
merged and the family re-derived on the merged tree: 35 commands over the same
2-path change set, identical list
. Run at 236b66e93, the final commit, and
re-run there after the merge. All green except three that could not measure:

  • node scripts/check-test-completeness.mjs — exit 3, NOT MEASURED (needs a
    saved turbo run test log; the script itself says to record it as NOT MEASURED
    when running the family locally). CI tees one.
  • pnpm check:dual-build-cjs-loads — exit 3, PREREQUISITE NOT MET (reads built
    output for packages this change does not touch; needs a whole-repo build).
  • node scripts/pm/check-half-states.mjs — exit 3, NOT MEASURED (needs
    repo-scoped GitHub egress, which this seat's session gate refuses). Its
    pnpm check:pm-half-states sibling is green.

pnpm check:i18n first returned exit 1 as PREREQUISITE NOT MET — the built CLI
was absent because the earlier build used the dependencies-of filter
(@objectstack/cli^...), which does not build the CLI itself. Its named closure
was run and the gate is green; the same happened once for
check:i18n-coverage, cleared the same way. Neither exit was a finding.

Also run: pnpm --filter @objectstack/platform-objects run typecheck (green;
tsc --listFiles confirms the edited file is in the program, 1 hit) and that
package's full test (33 files, 518 tests, all pass), plus its translations
suite alone (7 files, 85 tests) which carries the vocabulary and bundle-ownership
pins. node scripts/pm/check-governed-merges.mjs --test on the final two-file
list: NOT governed, ordinary queue landing applies. Heavy runs went through
scripts/pm/os-verify-lock.sh.

The two changesets on this branch were consolidated into one so the subtree's
correction lands as a single release-note row.

Authored by Claude Code in session 0112hMx9hjJ9BgB28X97DS68
(https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68).

🤖 Generated with Claude Code

Generated by Claude Code

…on description

`metadataForms.dashboard.sections.layout.description` read 「栅格与响应式」
against a source of "Grid sizing and refresh cadence." — it named a
responsiveness control the section does not hold and omitted the refresh
cadence it does. Now 「栅格尺寸与刷新间隔」, matching the bundle's own terms
for `columns` and `refreshInterval`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@github-actions github-actions Bot added the size/s label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 7317cf266e9682edc830ccac6fe78e66b3ddfc32packageMentionDocs.

…ce says

Four more leaves of `metadataForms.dashboard` described the Studio dashboard
property panel in terms `packages/spec/src/ui/dashboard.form.ts` does not use —
each naming a concept the source omits while dropping one it names:

  sections.basics.description   「名称与图标」          -> 「仪表板标识与描述」
  sections.widgets.description  「图表、指标、列表等」  -> 「放置在栅格上的卡片与图表」
  sections.filters.description  「全局筛选与日期范围」  -> 「应用到所有组件的默认筛选与全局筛选」
  fields.header.helpText        「标题、操作按钮与筛选」 -> 「仪表板页眉配置(title、subtitle、actions)」

`basics` promised an icon input, and the dashboard schema declares no icon key
at all (the only `icon` under `dashboard.zod.ts` is per header action) — the
same defect class as the layout leaf this branch already corrected, which
promised a responsive-breakpoint control. The other three swapped which concepts
the section covers: widgets is cards and charts on the grid, not metrics and
lists; filters is default plus global filters across widgets, not the date range
(that is the separate `dateRange` field); and the header carries a subtitle, not
filters.

The replacements reuse this bundle's own established terms and mirror es-ES /
ja-JP, both of which are correct at all five leaves. The two changesets are
consolidated into one so the subtree's correction lands as a single release
note row.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-musk os-musk changed the title fix(platform-objects): the zh-CN dashboard Layout section description names what that section holds fix(platform-objects): the zh-CN dashboard metadata-form subtree says what its source says Sep 3, 2026

os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

CI triage — Test Core (6/6) is not this PR's failure

The one red check. Of 39 check runs on head, exactly two are red: Test Core (6/6) (job 100630582890) and the Test Core aggregate that reports it. Lint & Repo Gates, all five Type Check lanes, the other five Test Core shards, all three Dogfood shards, Check Changeset, Governed Surface Queue Guard and every claim gate are green or skipped.

The failure, verbatim from the shard log:

FAIL  src/durability-swallow-repair.test.ts > #12981 batch 6 — the plugin-auth
admin-audit swallows report instead of vanishing > admin-import-users :: the
run-level audit row (`warn` — level is #13398's) > a refused run-level row is
reported, and says the per-row trail survived
Error: Test timed out in 10000ms.
 ❯ src/durability-swallow-repair.test.ts:673:5
Test Files  1 failed | 91 passed (92)
      Tests  1 failed | 1908 passed (1909)

Why it is not this PR's. The change set is two files — .changeset/zh-cn-dashboard-subtree-source-parity.md and five string leaves of packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts. The failing test is in packages/plugins/plugin-auth, exercises runAdminImportUsers against a mocked data engine, and reads no translation bundle. No zh-CN description/helpText value can reach a 10 s test timeout in that package.

The shard ran to completion, so this is not a lost runner: check-test-completeness: OK (8 of 8 scheduled package(s) reported, 0 had nothing to run, 0 never reached; 4384 test(s) declared and all accounted for).

What the timeout looks like mechanically. The failing it is the first of three siblings whose bodies are structurally identical and each begin await import('./admin-import-users.js'); the two later ones — which hit the warm module cache — passed. The shard reported Duration 202.45s (transform 62.18s, import 338.65s, tests 243.11s), i.e. the cold transform-plus-import cost dominates this shard, and the first dynamic import in this file pays it inside a 10 000 ms testTimeout. That makes pass/fail load-dependent rather than diff-dependent.

Base branch. main is green on this test across today's successful pushes (runs 29838, 29835, 29823, 29812, 29810, 29806, 29802, 29798, 29790, 29757), so it is not a standing red on the base either.

Action taken: the single permitted re-run of the failed jobs on run 33749760205 has been queued. If it comes back green, this PR is clear to land unchanged. If it reproduces identically, the failure is a plugin-auth test-harness defect owned by that package's lane, not something to fix inside this translation PR — a separate card will carry it.


Generated by Claude Code

os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

Re-run came back greenTest Core (6/6) attempt 2 (job 100726770850) succeeded at 16:32:31, and the Test Core aggregate re-ran green with it. All 39 check runs on head 236b66e93 are success or skipped, zero red. So the failure did not reproduce: it was load-dependent, and this PR is clear on its own merits. Marked ready and auto-merge armed.

The plugin-auth timeout itself is now carried by its own card, as promised: #14998. It has six closed same-family precedents, two of which (#5421, #3662) are the same file-with-a-sibling-that-already-sets-a-longer-timeout shape, so the remedy shape already exists in-repo.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants