Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

[finding] The whole report.editor.* namespace — 106 keys × 10 packs — has no consumer left; the report editor it labelled became the spec-driven inspector #4145

Closed

Description

@yinlianghui

Measured while implementing #4118 (PR #4137), not fixed there — that card's fence is the seven wrong-slot call sites, and this is a namespace-liveness question, not a wrong-copy defect. Filed so the measurement does not stay buried in a PR.

The measurement

report.editor in packages/i18n/src/locales/en.ts spans lines 1052–1165 and holds 106 leaf keys (breadcrumb, basic, title, titlePlaceholder, description, type, typeTabular, data, objectName, limit, columns, filters, groupBy, rows, values, grouping, dateGranularity, chart, chartType, …). All ten packs carry the set (all-locales-key-parity owns that), so it is roughly 1060 translated strings.

Repo-wide, the number of call sites that read any of them is zero:

$ grep -rn "report\.editor\." packages/ apps/ examples/ scripts/ | grep -v packages/i18n
packages/app-shell/src/views/ReportConfigPanel.tsx        (comments only, after #4137)
packages/app-shell/src/views/__tests__/ReportConfigPanel.panelTitle.test.tsx
packages/components/CHANGELOG.md
packages/plugin-report/CHANGELOG.md

Not a dynamic-key blind spot either: there is no t(\report.editor.${…}`)anywhere, and no JSON/MDX metadata references the namespace.check-i18n-call-site-keys.mjs` reports 62 dynamic-key sites repo-wide and none of them are in this family.

Spot-checked individually, each returns 0 non-test, non-locale call sites: basic, description, type, data, columns, filters, groupBy, chart, breadcrumb.

Why it went dormant

The namespace was built for the hand-rolled report editor form — the CHANGELOG entries read "All editor labels and hints are i18n-driven (report.editor.*)". That form is gone: ReportConfigPanel's body is now ReportDefaultInspector, a spec-driven inspector whose labels come from the report spec's own metadata, not from this pack namespace. ReportConfigPanel.tsx:55 still calls its remaining catalog "Legacy field catalog for the pre-9.0 object-bound report editor."

Until #4137 the namespace had exactly one live reader — and it was the bug #4118 is about: the panel borrowing report.editor.title (the Title field's label) to name itself. Moving that slot to a purpose-built report.editor.panelTitle left panelTitle as the namespace's only consumed key and the other 106 with nothing reading them.

Why no gate sees it

Every i18n gate in the repo runs call site → key, never key → call site:

  • scripts/check-i18n-call-site-keys.mjs asks whether each call site's key resolves in en. A key with no call site is not a call site, so it is never visited.
  • all-locales-key-parity compares the ten packs' key sets to each other. 106 keys present in all ten packs is exactly what it wants.
  • scripts/check-i18n-en-drift.mjs only fires when an en value changes. These values are static.

So the packs can accumulate dead namespaces indefinitely with every gate green — the mirror image of #3810 / #4117 (dead fallbacks at live call sites); this is live keys with dead call sites.

Impact — observation class, nothing a user hits today

No user reads a wrong string because of this; the keys simply never render. The cost is carrying cost and misdirection:

Suggested direction (not a ruling)

Two candidates, and the choice needs a maintainer:

  1. Retire the namespace — if the spec-driven inspector is the settled direction, report.editor.* minus panelTitle is dead weight; delete from all ten packs.
  2. Keep it deliberately — if the hand-rolled editor is meant to come back, or some downstream consumer outside this repo reads the packs, retire nothing and record why.

Worth deciding as a class rather than one namespace: a "no key without a reader" gate (key → call site, allowlisted for deliberate exceptions) is what would stop the next namespace going dormant unnoticed. That is the broader change and should be its own card if wanted.

Related: #4118 / PR #4137 (where this surfaced — the last live reader), #3810 and #4117 (dead fallbacks at live call sites — the mirror direction), #3546 (the ten-pack key discipline).


Generated by Claude Code

Activity

  1. self-assigned this
    on Aug 10, 2026
  2. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    Claim: PM loop round 6 (rolling slot refill; unlocked by PR #4168's landing — the i18n packs are free again)
    Session: session_017Qqyix2QcnpUC9XeYVDzx3 · Branch: claude/issue-4145-report-editor-orphan-ns · Worktree: objectui-issue-4145
    File surface: packages/i18n ten packs (the report.editor.* namespace minus the one live key #4137 minted) + any TranslationKeys-narrowing fallout + tests. Serial constraints: disjoint from #7100/#4160/#4148/#3586 in flight; no other pack work in the air.
    Container & model: S, mode:subacomponent, model: opus

    Direction — the #3811 deletion playbook applies verbatim: re-verify zero consumers (literal + dynamic template forms, the filing's method), preserve report.editor.panelTitle (the ONE live key #4137 added to this namespace — deletion sweeps around it), en-drift gate must report N removals / 0 value changes, TranslationKeys narrows → full prefix-direction downstream type-check sweep with the stale-.d.ts guard, and a negative pin so the dead namespace cannot silently return. If the re-verification finds ANY consumer the filing missed, stop and report — the premise is the deletion license.


    Generated by Claude Code

  3. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4177.

    The deletion license was re-established per-key rather than trusted, and the method critique that came back with it is worth more than the deletion: the filing's grep excluded packages/i18n wholesale, hiding two provenance anchors — not renderers, so the license stood, but exactly the blind-spot class a future namespace-liveness gate must not inherit (recorded where that gate's author will find it). The three test-side references got individual dispositions with the reasoning shown: the #4118 pin keeps its force as a rendered-string literal; the REUSED row DROPPED on a fresh measurement (detail.add is now the only en key valued "Add" — the guarded failure has no second site); the ru singular/plural contrast RE-ANCHORED to a byte-identical-in-nine-packs neighbor with zero coverage lost. The en-drift gate's 105 vs the tree's 1050 stated as different countings of one change so neither misreads as the other; the non-vacuity probe carried both directions in a single diagnostic. Reverse verification's predicted green (the en-reading panel test staying green on a zh-only revival) is the discrimination proof.

    ~1050 dead translated strings gone; report.editor lives on holding exactly its one real key. Flipping ready + auto-merge.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions