Skip to content

refactor(app-shell): retire the designer string table and its parity gate - #27136

Merged
os-zhuang merged 4 commits into
mainfrom
claude/project-thread-6d34fw
Oct 28, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/project-thread-6d34fw

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread

Part of #25922

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:删掉 app-shell 设计器私有表 ENGINE_STRINGS_EN / ENGINE_STRINGS_ZH(S6b 起已为空)和「先查表、再查命名空间」的查找,t() / tOptional() 现在只从 @object-ui/i18n 的 studio 命名空间取字;退役 check:i18n-designer-parity(脚本、测试、ui/package.json 脚本行、根 ci.yml 的一个步骤)。
  • 为什么改:执行 app-shell: a published library that is 66% Console product surface — retire the 67 zero-reference exports now, decide the split, and fold the second i18n table into @object-ui/i18n #25922 裁决 6431032267(Q2 = A,6431234244 维持)的最后一片 S7,派单 6461796872。
  • 风险与回滚:所有语言的文案与改前一致(同一 pin 在改前、改后都全绿);本 PR 删了 .github/workflows/ci.yml 的一个步骤,因此是 Tier H,需审批人批准后落地;回滚即 revert 本 PR。
  • 先看:ui/packages/app-shell/src/views/metadata-admin/i18n.ts 的 lookupString,再看 inspectorStrings.studioNamespace-25922.test.ts 末尾新增的「the namespace is the only home」一组,以及 check-i18n-dead-keys.test.ts 末尾接手类型与领域标签配对校验的 pin。
  • 两分钟验证:cd ui && pnpm exec vitest run packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts scripts/__tests__/check-i18n-dead-keys.test.ts,应全绿。
  • 需要你做的:Tier H,等席位的合同审查通过后,由审批人批准;在那之前本 PR 保持草稿。

What changes

  • The table is gone. Both ENGINE_STRINGS_* declarations in ui/packages/app-shell/src/views/metadata-admin/i18n.ts are deleted, and lookupString returns studioString(key, locale) alone. pickTable keeps TYPE_LABELS / DOMAIN_LABELS; FLOW_FIELD_ZH never read the table and is untouched.
  • The gate is retired: ui/scripts/check-i18n-designer-table-parity.mjs, its test, the check:i18n-designer-parity line in ui/package.json, and the root .github/workflows/ci.yml step "Verify the metadata-admin designer string tables stay paired" (one step; no other .github/** line).
  • Its exports move, its coverage stays. DESIGNER_TABLE_PAIRS and readDesignerPairs move into the shared extractor ui/scripts/check-i18n-dead-keys.mjs, where check-i18n-en-drift.mjs (CI's check:i18n-drift) and two Studio tests now import them. The extractor treats a table the module no longer declares as its namespace home alone. What the gate enforced is held by tests:
    • ENGINE_STRINGS parity (en ⊆ zh, {placeholder} parity, zh-only rows in documented families): ui/packages/i18n/src/__tests__/studio-namespace.test.ts, describe "studio namespace — scoped parity", which already covered every moved key.
    • TYPE_LABELS / DOMAIN_LABELS parity: a new describe "the real designer pairs stay paired" in ui/scripts/__tests__/check-i18n-dead-keys.test.ts, on the real tree, with floors per pair.
    • The gate's zh-only family reasons and their citation anchors: now ZH_ONLY_REASONS in the namespace pin, which checks each anchor still occurs exactly once.
  • Readers adapted, none deleted. previews/__tests__/block-config-i18n.test.ts reads its key sets from the namespace catalogues and asserts i18n.ts declares no ENGINE_STRINGS_ constant (it had asserted both tables empty). zh-base-term.i18n-13131.test.ts runs its census over the loaded zh catalogue. check-i18n-dead-keys.test.ts and check-i18n-en-drift.test.ts gain fixtures for a module without the table.
  • Prose: ui/packages/i18n/README.md, the namespace's index.ts / zh.ts headers, and the extractor and drift-gate docs. The CI/CD guide page that listed the gate (ui/content/docs/guide/ci-cd-pipeline.md) was retired on main by docs(ui): retire the CI/CD guide page and repoint its readers at the root workflows #27071 while this branch was open; the merge keeps it deleted.
  • Changeset: .changeset/25922-studio-i18n-table-retired.md, @object-ui/i18n patch (its README ships).

Why

Ruling 6431032267 Q2 = A (upheld by 6431234244): the designer table becomes one lazy @object-ui/i18n namespace, moved in slices. S7 is the last slice, deleting the empty table and the gate that paired its two homes.

Tests

  • Pin: inspectors/inspectorStrings.studioNamespace-25922.test.ts gains describe "the namespace is the only home (objectstack#25922 slice S7)":
    • every namespace key (3,216 en) through t() and tOptional() in en-US, en, de-DE, no locale, zh-CN, zh and zh-TW equals its catalogue value;
    • the 54 zh-only rows (9 package form help, 41 flow node, 4 flow enum) all belong to a documented family, answer in the three zh tags, and stay undefined through tOptional() in the four others;
    • each zh-only family's citation anchor occurs exactly once.
  • Before and after: the same pin file (182 tests) is green against this head, and green with i18n.ts set back to its base blob at 5fe0b967 (the table-first lookup over the empty tables). So every lookup resolves the same before and after.
  • Ablations (scripts/ablation-replace.mjs, each landed by anchor count and blob, restored to the HEAD blob with git diff HEAD empty):
    • (A) the namespace dropped from lookupString: pin red, 92 of 182, including both new S7 cases.
    • (B) a table asked in front of the namespace, holding one differing row (engine.translationPreview.coverage): pin red, 2 (that family's t() case and the every-key case).
    • (C) two TYPE_LABELS_ZH rows deleted: the new real-tree pair pin red ("TYPE_LABELS: every en key has a zh row with the same {placeholders}").
    • (D) the engine.packages.form.help. citation anchor reworded in package-schema.ts: that citation case red.

The sweep

The zh loader in namespaces/studio/index.ts was delayed by 4,000 ms (ablation-replace.mjs --hold, restored to the HEAD blob). Under the delay, 312 test files ran: every app-shell test naming a zh locale or a moved family, the i18n tests naming studio, and the dead-keys and en-drift script tests. 3,826 of 3,827 tests passed. The one red is i18n/src/__tests__/studio-namespace-lazy.test.tsx, red by construction (its findByText waits 1 s against a 4 s delay), as in S6b. No racer.

Acceptance notes

  • Mechanism assumptions, measured: the gate paired ENGINE_STRINGS, TYPE_LABELS and DOMAIN_LABELS (not FLOW_FIELD_ZH); all three keep a check, listed above. TYPE_LABELS, DOMAIN_LABELS and FLOW_FIELD_ZH stay, since none reads the deleted tables. The zh-only producer rows are 54 and stay optional lookups through tOptional().
  • Tier H: .github/workflows/ci.yml is the register row workflows (glob: '.github/workflows/**', tier: GOVERNED_TIER_H in scripts/pm/check-governed-merges.mjs). dispatch-gates --tier derives no model-tier mandate: "Model tier — no path-derived mandate: the surface hits none of the 4 declared glob(s)". Changed lines 1,286 (+370 / −916) against the 3,000 threshold: under. This PR stays draft; no reviewers requested. The ci.yml step was re-applied after create, so pr_create's governed follow-up (fleet-write: relay pr_create asks the governed approvers to review a Tier H draft before any contract review exists, so an approver can approve and merge it unreviewed (#26566, #26570) #26617) did not request approvers before the contract review: f8e5fa25 restored the step so the pull opened with no governed path, and the next commit reverts it, so the head carries the full S7 diff (its tree equals d40b118a's). CI on f8e5fa25 may be red for those minutes, since that step names a script this PR retires.
  • Eager bundle: not re-measured locally, as in S2–S6b. CI's Build & E2E UI measures it.

Verification

At d40b118a (the head's tree after the revert above), which merges origin/main a98daf75 (21 commits past the branch point 5fe0b967; the one conflict was the retired CI/CD guide page). The pin, ablations and sweep ran at 7c7a23e1, before the merge; the merged commits touch the ten locale packs but not the namespace, the app-shell string module or an i18n gate script, and the focused set and every gate re-ran on the merged head.

Tests and gates
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 88 commands at d40b118a, each exit 0 (captured before any pipe), including pnpm --dir ui exec vitest run scripts/ (Test Files 174 passed | 2 skipped (176)). --ran: "88 derived famil(ies) accounted for — 88 run, 0 NOT-MEASURED (a DERIVED zero — all 88 recorded an exit code and none of them is 3)". The same 88 were also all exit 0 at 7c7a23e1, before the merge.
  • pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check: exit 0. pnpm --dir ui run type-check:scripts: exit 0.
  • ui check:i18n-dead-keys, check:i18n-drift, check:i18n-keys: exit 0. check:new-line-citations: exit 0. node scripts/check-nul-bytes.mjs: exit 0. (check:i18n-designer-parity is retired here.)
  • Focused set on the merged head (the pin, studio-namespace, block-config-i18n, zh-base-term, the two Studio tests, the dead-keys and en-drift script tests): Tests 487 passed (487).
  • Changed lines: 1,286 (+370 / −916) over 19 files.

Human Minimum

  • 1. No packages/spec change.
  • 2. No new names beyond the moved DESIGNER_TABLE_PAIRS / readDesignerPairs exports and the changeset.
  • 3. No formatter ran; pnpm lint is CI's.
  • 4. One card slice, one branch off main, one pull request.
  • 5. Patch changeset with both declaration lines.
  • 6. n/a.
  • 7. No hand edits to generated or release-owned files.
  • 8. English.

Generated by Claude Code

…gate

The metadata-admin designer table, empty since the previous slice, is
deleted with its table-first lookup: t() and tOptional() resolve every
designer string from the studio namespace of @object-ui/i18n alone.

The paired-table gate check:i18n-designer-parity, its test, its ui
script and its root ci.yml step are retired. Its pair reader moves into
the shared extractor in check-i18n-dead-keys.mjs, where the drift gate
and two Studio tests already read it, and the pair parity it enforced
for the type and domain label tables is held by a real-tree pin in
check-i18n-dead-keys.test.ts. The namespace's own parity stays in
studio-namespace.test.ts; the zh-only family reasons move into the
studio namespace pin test with their citation anchors checked.

Readers of the deleted declarations (block-config-i18n, the zh base
census) now read the namespace catalogues.

Claude-Session: https://claude.ai/code/session_01JQwxbX3S5QrD29Ghii633f
Co-authored-by: Claude <noreply@anthropic.com>
The CI/CD guide page this branch edited was retired on main; the page
stays deleted.

Claude-Session: https://claude.ai/code/session_01JQwxbX3S5QrD29Ghii633f
Co-authored-by: Claude <noreply@anthropic.com>
Restores the root ci.yml step that runs check:i18n-designer-parity, so
the pull opens with no governed path; the next commit reverts this.

Claude-Session: https://claude.ai/code/session_01JQwxbX3S5QrD29Ghii633f
Co-authored-by: Claude <noreply@anthropic.com>
The pull is open, so the ci.yml step retirement goes back in and the
head carries the whole change again.

Claude-Session: https://claude.ai/code/session_01JQwxbX3S5QrD29Ghii633f
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tests tooling labels Oct 28, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Seat note · contract review owed · seat domain:ui#1 · session_01JQwxbZeBv2y91towxasSUT · 2026-10-28T07:43Z

This PR is Tier H: it deletes one root .github/workflows/ci.yml step ("Verify the metadata-admin designer string tables stay paired"), the edit ruling 6431032267 Q3 approved in principle for this final slice. A Tier H PR goes in front of approvers only after a contract review PASS and the seat's ACCEPT (#26617). This seat cannot run CONTRACT_REVIEW_TIER: the ceiling model has been unavailable to the fleet since 2026-10-27, so the seat runs at TIER_DEFAULT under the quota exemption, and it hands the review to triage.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (ceiling model out for the fleet since 2026-10-27, seat runs at TIER_DEFAULT, 2026-10-28T07:43Z) · head 3beee64fe77741d07f035f1b80eeaa07e7280ab4

Inputs for the reviewer:

No reviewer is requested and the PR stays draft until a PASS is on file and the seat's Tier H record is posted (#26617).


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 3beee64fe77741d07f035f1b80eeaa07e7280ab4 · 2026-10-28T12:18Z

Triage seat, taking the hand-off that names this head (Contract-review-handoff: triage …). ⚠️ Triage missed this hand-off for several rounds: its scan, rebuilt at R720, skipped draft PRs and did not read hand-off lines. That is now fixed. The review runs at CONTRACT_REVIEW_TIER.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3beee64fe77741d07f035f1b80eeaa07e7280ab4
Local-runs: none
Scope: .github/workflows/ci.yml + ui/package.json, ui/scripts/check-i18n-designer-table-parity.mjs (deleted), ui/scripts/tests/check-i18n-designer-table-parity.test.ts (deleted), ui/scripts/check-i18n-dead-keys.mjs, ui/scripts/tests/check-i18n-dead-keys.test.ts, ui/scripts/check-i18n-en-drift.mjs, ui/scripts/tests/check-i18n-en-drift.test.ts, ui/packages/i18n/src/tests/studio-namespace.test.ts, ui/packages/app-shell/src/views/metadata-admin/i18n.ts, ui/packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts, ui/packages/app-shell/src/views/metadata-admin/previews/tests/block-config-i18n.test.ts; read in the live tree to judge CI reachability: ui/vitest.config.mts, ui/scripts/select-affected-tests.mjs, the filter / type-check-ui / test-ui jobs of ci.yml. The remaining diff files (the two Studio tests, zh-base-term census, README, namespace doc comments, the changeset) are the lane seat's ACCEPT at TIER_DEFAULT.

Inputs read: card #25922 body and all 45 comments (rulings 6431032267 and 6431234244, S7 order 6461796872, claim 6461806458, os-dev report 6463510492); PR #27136 body, 19-file list, net diff against main (1,737 diff lines, 19 files, matching the file list); both PR comments (seat hand-off 6463525633, triage claim 6468788431); the 60 check-runs on the head — 49 success, 11 skipped, 0 failed, 0 pending (Type Check UI, Test UI 1–16/16 and rollup, Lint UI, Build & E2E UI, Check Changeset, Governed Surface Queue Guard, Lint · PM dispatch-gates all success).

① Derived judgments

  1. Published surface of @object-ui/i18n — unchanged. Right. The diff touches that package's README, a test, and doc comments in namespaces/studio/index.ts and zh.ts; no export, signature or catalogue row moves (confirmed on the hunks; studioString untouched). The changeset's "No export or string changes" is true.
  2. @object-ui/app-shell — private ("private": true on the head), so no accept set is published. Right. Inside it, ENGINE_STRINGS_EN/ZH were non-exported consts, pickTable/lookupString are non-exported; t()/tOptional() keep their signatures. The behavioural claim (every key resolves identically before and after) follows from the code: the deleted tables were empty since S6b, so pickTable(locale).strings[key] ?? studioString(key, locale) always reached studioString, which is now the whole body.
  3. The deleted script's module surface — DESIGNER_TABLE_PAIRS, DESIGNER_PAIR_CONSTS, readDesignerPairs, DESIGNER_TABLE re-export moved into check-i18n-dead-keys.mjs; ZH_ONLY_FAMILIES, PLACEHOLDER_PATTERN, placeholdersOf, analysePairs deleted with zero remaining readers. Right. git grep over the whole head tree for designer-parity, designer-table-parity, ZH_ONLY_FAMILIES, analysePairs, placeholdersOf finds only prose that says the gate is retired, the namespace test's own local ZH_ONLY_FAMILIES array, and the fixture text in the script tests. Every former importer (check-i18n-en-drift.mjs, its test, BuilderLanding.environmentOverlayCopy-12171.test.ts, StudioDesignSurface.railLabels.test.tsx) now imports from check-i18n-dead-keys.mjs.
  4. ui/package.json script check:i18n-designer-parity — zero remaining readers. Right. No workflow (root .github/**, ui/.github/**), no scripts/pm/* roster, no docs page or AGENTS file names it on the head; ui/content/docs/guide/ci-cd-pipeline.md, which listed it, is absent on both origin/main and the head (retired by docs(ui): retire the CI/CD guide page and repoint its readers at the root workflows #27071).
  5. Extractor semantics widened in one place, guarded. Right. collectDesignerKeys now treats a table constant the module no longer declares as its namespace home alone, but only when the module imports @object-ui/i18n/namespaces/studio; a module that neither declares nor imports still throws "the extractor is stale" (new fixture case; the pre-existing RENAMED_ZH case in the en-drift test still throws because its fixture carries no import). The "key in both homes" throw is kept and its message corrected (the runtime now reads only the namespace).
  6. DESIGNER_TABLE_PAIRS is now frozen. Right. Its only iterating consumer (check-i18n-en-drift.mjs:690) and the new pin read it; nothing mutates it.
  7. CI shape — one step removed from type-check-ui, nothing else under .github/**. Right. The ci.yml hunk is exactly the three lines of the step "Verify the metadata-admin designer string tables stay paired" (name, run, blank line); the file list carries no other .github/** path; Lint · PM dispatch-gates is green on the head, so the derived-gate roster accepted the change.

② Semver level

  • Changeset .changeset/25922-studio-i18n-table-retired.md: '@object-ui/i18n': patch. Correct — the only released package the diff moves ships README and doc-comment text; @object-ui/app-shell and the ui root are private; skip-changeset would have been wrong because a released package's README does change.
  • Both line-initial declarations present in the PR body and the changeset body, identically: Clause-②: no, Metadata-protocol: none. Correct — the diff widens no accept set and enlarges no public surface (execution-duties.md's criterion), and narrows none: the deleted exports belong to an unpublished repo script, the deleted consts were private, and no published package loses a name. No (narrowing) arm, so no BREAKING banner or ADR-0087 disposition is owed, and no Skills-docs: line is owed (kind none, no arm). Check Changeset is green on the head.
  • The dispatch order (6461796872) pre-declared Clause-②: no, Metadata-protocol: none; the diff matches.

③ Boundary flags

Dev report 6463510492: open_questions: [], out_of_scope_findings: [], premise_still_valid: true. Four deviations, each answered:

  1. Model-free commit trailers / PR footer form — AGENTS.md house style, outside the contract faces; no action.
  2. Merged origin/main a98daf75 instead of rebasing — the net diff against main is the 19 files of the file list and nothing else, so the merge adds no stray hunk; the one conflict (the retired CI/CD guide page) is resolved as deleted, matching main.
  3. Restore commit f8e5fa25 before pr_create and revert at 3beee64f so the governed follow-up (fleet-write: relay pr_create asks the governed approvers to review a Tier H draft before any contract review exists, so an approver can approve and merge it unreviewed (#26566, #26570) #26617) requested no approvers before this review — the seat's own route (seat note 6463525633 states it). The head's tree is what is judged here, and it carries the full S7 diff; requested_reviewers is empty on the PR. Consequence for the seat, not a finding: after this PASS the seat must request the Tier H approvers itself, as the ruling's Q3 lands the step "by the maintainer's approval of that PR".
  4. Eager-closure budget not measured locally — Build & E2E UI is success on the head; answered by the check-run.

Ruling bounds held: Q3 (6431032267, kept by 6431234244) approved exactly this one ci.yml step's removal in the final (M) slice and "not any other .github/** edit"; the diff edits that one step and no other workflow line. The order's mechanism assumptions were measured in the tree: the retired gate paired ENGINE_STRINGS, TYPE_LABELS and DOMAIN_LABELS (its DESIGNER_TABLE_PAIRS), never FLOW_FIELD_ZH; all three pairs keep a check (④); TYPE_LABELS_*, DOMAIN_LABELS_*, FLOW_FIELD_ZH stay and none read the deleted tables (pickTable still returns types/domains; flowFieldZh is untouched).

④ Design judgment

.github/workflows/ci.yml — the removed gate against what it guarded. The step ran check-i18n-designer-table-parity.mjs, whose enforced legs were (a) en ⊆ zh per pair and (b) identical {placeholder} sets on shared keys, for the three pairs, with (c) a --min-keys 1500 collapse guard, (d) a report-only zh-only residue minus three cited families, and (e) a throw on a key present in both homes (from the shared extractor). Its subjects on the head: the studio namespace catalogues (ENGINE_STRINGS now stands for STUDIO_EN/STUDIO_ZH alone) and the two label tables still in metadata-admin/i18n.ts. Each leg is held elsewhere on the head, in files CI runs:

  • (a)+(b) for ENGINE_STRINGS: ui/packages/i18n/src/__tests__/studio-namespace.test.ts describe "studio namespace — scoped parity" (every en key has a zh row, every shared key carries the same {placeholders}) over the imported catalogue objects, so there is no parser to collapse; and again through the extractor on the real tree in ui/scripts/__tests__/check-i18n-dead-keys.test.ts describe "the real designer pairs stay paired" (floor 1,500 en keys).
  • (a)+(b) for TYPE_LABELS and DOMAIN_LABELS: the same real-tree describe, it.each over DESIGNER_TABLE_PAIRS, floors 20 and 5, plus reads every pair in the list pinning the labels to exactly those three — so a pair silently dropped from the list fails.
  • (c): the floors above and the app-shell pin's Object.keys(EN).length > 3000; readDesignerPairs keeps its values === null throw.
  • (d), now enforced rather than reported: studio-namespace.test.ts a zh-only key belongs to a documented family (pre-existing) and the new app-shell describe "the namespace is the only home" (zhOnly length ≥ 50, every zh-only key in a ZH_ONLY_REASONS family, undefined through tOptional() in en-US/en/de-DE/undefined, equal to the zh row in the three zh tags). The three citation anchors are checked to occur exactly once; verified on the head: resolved by translateNodeLabel/Hint 1, export function translateEnumOption 1 (both in i18n.ts), en-US deliberately has NO entry 1 (package-schema.ts).
  • (e): collectDesignerKeys still throws on a key in both homes; block-config-i18n.test.ts now asserts i18n.ts declares no const ENGINE_STRINGS_ at all, so a table literal brought back is red even before it carries a key; and the every-key case of the app-shell pin reds a lookup asked in front of the namespace with a differing value.

CI reachability of the replacement (the step's one property the tests had to inherit). The old step ran in type-check-ui on every PR, merge-group and push where filter.ui or filter.ui_consumers was true. On the head, ui/vitest.config.mts's unit project includes scripts/**/*.test.ts and packages/**/*.test.ts, and test-ui (16 shards + test-ui-gate) runs when filter.ui is true. Under the affected-test selector (ui/scripts/select-affected-tests.mjs), scripts/__tests__/check-i18n-dead-keys.test.ts is always-on ("outside every workspace package"), the app-shell pin is always-on ("reads the disk", it imports node:fs), and studio-namespace.test.ts is selected whenever packages/i18n or a dependent changes, which is every edit to the namespace catalogues; push to main runs the full battery. Every subject file lives under ui/, so no edit to a subject can leave filter.ui false. The one job-condition difference (type-check-ui also ran on ui_consumers) cannot reach a table edit. Reachability holds.

Breaking attempts, each caught on the head's tree: an en namespace row with no zh row (two pins red); a TYPE_LABELS_EN row with no zh row (real-tree pin red, always-on); a {count} dropped from a zh value (two pins red); a new zh-only key outside the three families (two pins red); an ENGINE_STRINGS_* literal re-declared (block-config census red; both-homes throw if a key collides; app-shell pin red if wired in front with a different value); an extractor that reads nothing (floors red); a table module that drops the namespace import (extractor throws, as before). Nothing the step enforced is left unguarded; the gate is deleted with its subject's guard moved, not with its subject exposed.

The cited code (read, not reviewed). lookupString is studioString(key, locale); studioString answers an own key of the resolved catalogue, else the en row, else undefined, so t() echoes the key and tOptional() returns undefined exactly as the pin asserts. collectDesignerKeys' fill runs before the require check and only under importsNamespace, so readDesignerPairs(root) with require: true still demands the four label constants on the real tree. sweepDesignerTable skips DESIGNER_TABLE_CONSTS declarations by name and indexes tables.get(name) for both names, which the fill guarantees exist.

Findings.

  • should-fix (non-blocking): the zh-only family list now exists twice with no cross-assertion — ZH_ONLY_FAMILIES (three prefixes) in studio-namespace.test.ts and the prefixes of ZH_ONLY_REASONS in the app-shell pin. Both fail closed (each reds on a stray key), so coverage is not lost; a one-line equality assertion, or deriving one from the other, would keep them from drifting apart in a later slice.
  • must-fix: none.

Implemented-by: claude/project-thread-6d34fw
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(席位终稿)

  • 改了什么:删掉 app-shell 设计器私有表 ENGINE_STRINGS_EN/ZH(S6b 起已空),t()/tOptional() 只从 @object-ui/i18n 的 studio 命名空间取字;退役 check:i18n-designer-parity(脚本、测试、ui/package.json 一行、根 ci.yml 一个步骤)。
  • 为什么改:执行 app-shell: a published library that is 66% Console product surface — retire the 67 zero-reference exports now, decide the split, and fold the second i18n table into @object-ui/i18n #25922 裁决 6431032267(Q2 = A,Q3 同意删这一步)的最后一片 S7。
  • 风险与回滚:所有语言文案前后一致;原门禁守的配对规则已移到常开测试里,契约复核逐项打破验证都会变红。回滚即 revert 本 PR。
  • 先看:.github/workflows/ci.yml 只删 3 行(一个步骤);ui/packages/app-shell/src/views/metadata-admin/i18n.ts 的 lookupString。
  • 两分钟验证:cd ui && pnpm exec vitest run packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts scripts/__tests__/check-i18n-dead-keys.test.ts,应全绿。
  • 需要你做的:请 hotlong 或 os-zhuang 在 head 3beee64f 上批准(Tier H,ci.yml)。批准后席位挂自动合并入队。

席位意见:契约复核 PASS(6469007202,CONTRACT_REVIEW_TIER,head 3beee64f,must-fix 无),席位核对的 diff 与复审范围一致,同意落地。

席位核对

ACCEPT · seat domain:ui#1 · session_01JQwxbZeBv2y91towxasSUT · head 3beee64f · 2026-10-28T12:30Z

  1. Shape: Part of #25922; 19 files, +370/−916, merge base a98daf75. The root .github/workflows/ci.yml hunk removes exactly one step ("Verify the metadata-admin designer string tables stay paired", 3 lines) and nothing else under .github/**. A trial merge with origin/main cc05f533 is clean.
  2. Premise measured: both ENGINE_STRINGS_* were empty after S6b (feat(ui): the translation preview strings move into the studio i18n namespace (#25922 slice S6b) #27083), so lookupString already always reached studioString; the record confirms the behaviour claim on the code. @object-ui/app-shell is private; @object-ui/i18n ships only README/doc-comment changes (patch changeset).
  3. Gates / check-runs: on 3beee64f: 49 success, 13 skipped, 0 failure (one queued run at the seat read). Dev's report 6463510492 on the card.
  4. Open sequence: opened at f8e5fa25 with the step restored, re-applied at 3beee64f (fleet-write: relay pr_create asks the governed approvers to review a Tier H draft before any contract review exists, so an approver can approve and merge it unreviewed (#26566, #26570) #26617 route), so no approver was requested before the review. requested_reviewers is empty until this record.
  5. Accepted deviations: the review's one should-fix (the zh-only family list now lives in two pins with no equality assertion; both fail closed) does not ride this PR, so the PASS stays pinned to its head. The seat files it as a follow-up after the merge.
  6. Landing: Tier H (ci.yml). This record is pinned before ready. The PR gets needs-user-decision, is readied (which requests the GOVERNED_APPROVERS), and the seat arms auto-merge only after a governed approval given after this record.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 28, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation needs-user-decision size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants