Skip to content

Commit b758e91

Browse files
docs(qa): re-point the Studio checklist clauses QA run #29672 measured as stale (#29815)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSi9paTx1Lu8ENYwwssthfK3h)_ Fixes #29679 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:测试清单里 6 个 Studio / i18n 测试项改为指向今天 main 上真实成立的行为:记录页改用声明了要点字段的「客户」对象;对象变体用 `activityMilestones` 替代已退役的 `titleFormat`;组织流程改用不带包的 PUT 造夹具;表单视图矩阵去掉已被拒收、或 Studio 已有控件的键;首次闭环分 en / zh-CN 两条腿各自判定;相对日期改读表格单元格的提示文字。只改 `docs/qa/platform-checklist/areas/` 下两个 JSON,不动产品代码。 - **为什么改**:QA 运行 #29672 把这些条款判红,但背后不是产品缺陷,而是条款过时。留着会让清单持续误报,真缺陷(zh-CN 首次发布进不了数据面,#29673)也会混在误报里看不清。 - **风险与回滚**:纯文档。每项 revision 加 1 并追加 history 行,旧运行记录仍按它当时的 revision 解读。zh-CN 腿今天会如实判失败,因为 #29673 还没修。回滚即 revert 本 PR。 - **先看**:`studio-authoring.json` 的 `first-run-loop`(新增 zh-CN 腿与 knownGaps[3]);同文件 `record-page-roundtrip`(对象从 showcase_contact 换成 showcase_account);`i18n.json` 的 `studio-follows-app-locale` acceptance[1] 与 [2]。 - **两分钟验证**:在仓库根运行 `node scripts/check-platform-checklist.mjs`,应输出 `check-platform-checklist: OK — 16 areas, 359 items`,退出码 0。 - **需要你做的**:无,席位落地。 ## What changes Checklist revision only, from QA run #29672 (read at `3482f3d8d2`). Every re-point was re-read on `main` at `339f63da30` (and the merge of `origin/main` at `0e4b0fa411` touches none of the cited sources). Each item gets a revision bump and one `history` row citing #29679 and the run. | item | rev | what was stale | re-pointed to | evidence on main | |:--|:--|:--|:--|:--| | `studio-authoring.record-page-roundtrip` | 13 → 14 | acceptance[0]: `showcase_contact` declares no `highlightFields`, so since #28907 its full create seeds no `record:highlights` | the whole item on `showcase_account` (fixtures, personas[1], steps[0]/[2]/[6], acceptance[0] and [3], automated.ref) | `account.object.ts` declares `highlightFields: ['status', 'industry', 'annual_revenue']`; `deriveHighlightFields` (plugin-detail `buildDefaultPageSchema.ts`) draws declared fields only; no showcase page names the object; the everyone baseline `showcase_member_default` reads it | | `studio-authoring.api-written-keys-survive-studio-save` | 3 → 4 | variants[0]: `titleFormat` is refused at save and publish since 3557366 | `activityMilestones` | graded live in `packages/spec/liveness/object.json`; no Studio surface writes it; the run's matrix read its runtime row hold. `nameField` (the prescription) is not used: Studio has a control for it (`ObjectSettingsPanel.tsx`) | | `studio-authoring.org-scope-flows` | 2 → 3 | fixtures.requires[1], steps[1]: the clone door lands in `BASE.custom` since #28149 | `PUT /api/v1/meta/flow/qa_org_raw` with no `?package=` and no `?mode=` | ADR-0146 D11 closes a package-less write only onto a shipped item (`packagelessOverlayWriteRefusal`); the run read this PUT answer 200 | | `studio-authoring.no-entry-property-matrix` | 4 → 5 | the view.form row: `drawerSide` / `drawerWidth` answer 422; Studio now offers Layout, Columns, Default Tab, Tab Position | `drawerSide` / `drawerWidth` listed as refused at parse; `layout`, `defaultTab`, `tabPosition` out of the matrix per step 4; knownGaps[0] says why | `retiredKey` tombstones in `packages/spec/src/ui/view.zod.ts`; `ViewVariantInspector.tsx` hands the form variant's spec schema to `SchemaForm`; the layout canvas fail was #29676, which #29759 closed | | `studio-authoring.first-run-loop` | 10 → 11 | names no locale; only zh-CN fails | an en leg and a zh-CN leg, each on its own boot, every clause scored per leg (new negative[2]); knownGaps[3] records the zh-CN failure | #29673 is open; `isInjectedColumnDefinition` is still byte-for-byte and the `registerObject` failure is still a `console.warn` in `protocol.ts` | | `i18n.studio-follows-app-locale` | 7 → 8 | acceptance[2] (the card's "[3]" is the run's one-based number): a grid paints the absolute date, relative only as the tooltip; and, from the addendum, acceptance[1] / negative[0] counted an authored label as a mixed-language fail | acceptance[2] reads the date cell's `title` (oracle `dom`), both directions; acceptance[1] and negative[0] carry the authored-override exception | `DateCellRenderer` with `inGridColumn` (`ui/packages/fields/src/index.tsx`); ADR-0029 D9.2a and `translateObject`, pinned by `i18n-resolver.test.ts` and `meta-object-i18n-explicit-override.test.ts` | ## Tests No runtime code changes, so there is no test to add and no ablation. The derived gate set ran on the final head `ede9c13a2f`, each exit code captured before any pipe. `dispatch-gates --ran` reconciliation: 16 derived, 16 run, 0 NOT-MEASURED (a derived zero: all 16 recorded an exit code). <details> <summary>Gate readings at ede9c13</summary> ```text 0 node scripts/check-adr-links.mjs 0 node scripts/check-adr-links.mjs --self-test 0 node scripts/check-closing-keyword-parity.mjs 0 node scripts/check-closing-keyword-parity.mjs --self-test 0 node scripts/check-comment-mask-corpus.mjs 0 node scripts/ci/plan-test-core-shards.mjs --self-test 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions (after building formula and lint, as its prerequisite said) 0 pnpm check:ci-filter-parity 0 pnpm check:cross-package-test-inputs 0 pnpm check:doc-authoring 0 pnpm check:driver-memory-census 0 pnpm check:gitlink-declared 0 pnpm check:nul-bytes 0 pnpm check:platform-checklist 0 pnpm check:refd-timer-probe 0 pnpm check:watch-hint-literal check-platform-checklist: OK — 16 areas, 359 items (353 active, 1 planned); symbol anchors: 1134/1144 resolved, 10 on the named residual, 18 file floors held ``` </details> ## Acceptance notes - **Deviations from the card's table, each measured.** The card names the relative-date clause `acceptance[3]`; it is `acceptance[2]` zero-based (the run numbered from one). In the same items I also corrected four stale readings from the same run: org-scope-flows `steps[0]` (the empty state now has no Open in Setup link), first-run-loop `steps[1]` (since #29734 a Chinese name derives a pinyin package id, so "derives no package id" no longer held), the matrix's object `titleFormat` cell (now a refusal), and the matrix's `buttons` cell (already measured rendering by revision 3's knownGaps). - **Not re-driven live at this base.** Every re-point is read from source, seed data and the run's own readings. record-page acceptance[1] to [3] passed on `showcase_contact` in the run and are not yet driven on `showcase_account`. - **Fixture gaps the card names that this PR does not add.** The two launch entries (`OS_AUTOMATION_SCHEDULED_WORK_ENABLED=1` for flow-status-matches-runtime, `OS_PAGE_REACT_ENABLED=false` for custom-page-source-tiers) live in `.claude/launch.json`, not in the checklist's own fixture declarations, which already name both boots. picklist-bound-select's fixture needs a picklist in the showcase's `objectstack.config.ts`, a seed-data change. Both are left to the seat. - **Notes, not filed.** (1) Studio's landing card `engine.studio.org.description` (en and zh, `ui/packages/i18n/src/namespaces/studio/`) still says the scope holds "a clone of a packaged flow", which #28149 made untrue; read from source only. (2) `i18n.studio-follows-app-locale` knownGaps[0] says 414 untranslated labels; `scripts/i18n-coverage-baseline.json` reads 320. (3) `packages/spec/liveness/object.json` grades `titleFormat` live while the save gate refuses it. (4) The form-view inspector's `SchemaForm` may offer controls for more `view.form` keys than the four the run named; the next run's step 4 census decides. (5) `defaultTab` / `tabPosition`'s partial runtime effect leaves this matrix with them, and no other item claims it. ## Verification ```text node scripts/check-platform-checklist.mjs # OK, exit 0 node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack ``` Session: https://claude.ai/code/session_017ihL2gLghEqeDKTbDTC7Zd 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 31204d1 commit b758e91

2 files changed

Lines changed: 52 additions & 44 deletions

File tree

‎docs/qa/platform-checklist/areas/i18n.json‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
"title": "Studio follows the in-app locale switch — no mixed-language session",
100100
"since": "v16",
101101
"status": "active",
102-
"revision": 7,
102+
"revision": 8,
103103
"priority": "P2",
104104
"surface": "browser",
105105
"personas": ["admin"],
@@ -116,7 +116,7 @@
116116
"sign in as admin on the showcase, switch the in-app locale to zh-CN, and confirm the app shell followed (nav in zh-CN). To switch, use the avatar-menu language switcher (it writes the user's locale); seeding browser storage alone is not a language switch — a run that only seeds the UI language in browser storage leaves the user's stored locale empty, so dates follow the browser and a FAIL read off it is the harness's, not the product's",
117117
"navigate into Studio / metadata-admin: open the object editor for showcase_project and the dashboard designer for showcase_chart_gallery",
118118
"screenshot the object editor's form — its section and field labels come from objectui's metadata-admin catalogue (`designer.object.*` in ui/packages/app-shell/src/views/metadata-admin/i18n.ts, in this checkout), not from the served metadataForms translation group (packages/spec/src/system/translation.zod.ts): judge them against that catalogue (e.g. section 基础信息 with hint 标识、显示名与分类)",
119-
"screenshot a surface showing RELATIVE dates in the switched locale: the Studio Data pillar's records grid (/_console/studio/<package>/data, an object's records), whose timestamps render as '6天前'-style relative forms. The metadata list and history surfaces show none — history renders absolute timestamps — so they cannot score this step",
119+
"read the relative date in the switched locale on the Studio Data pillar's records grid (/_console/studio/<package>/data, an object's records). In a grid column a `date` field that declares no format paints the absolute face (10月28日 / Oct 28) and carries the relative phrase as the cell's title, its tooltip (6天前 / 6 days ago): the #25884 ruling, absolute in a sortable column and relative at most as a tooltip (DateCellRenderer and its inGridColumn prop, ui/packages/fields/src/index.tsx). Pick a record whose date is within the last 7 days: outside that window the relative phrase is the absolute face, and the title falls back to the ISO instant. Screenshot the grid, then read the cell's title attribute. The metadata list and history surfaces show none — history renders absolute timestamps — so they cannot score this step",
120120
"reload the browser fully and re-screenshot one Studio surface — the locale choice must survive the reload",
121121
"switch back to en through the same avatar-menu language switcher and re-screenshot the same two Studio surfaces"
122122
],
@@ -128,16 +128,16 @@
128128
"evidence": "object-editor screenshot"
129129
},
130130
{
131-
"clause": "no mixed-language session in the sense the coverage ratchet defines: every string the bundle DOES translate renders translated, and any string it does not renders its EN SOURCE label — never a raw dotted key. The showcase's frozen untranslated debt is legitimate here, not a FAIL",
131+
"clause": "no mixed-language session in the sense the coverage ratchet defines: every string the bundle DOES translate renders translated, and any string it does not renders its EN SOURCE label — never a raw dotted key. The showcase's frozen untranslated debt is legitimate here, not a FAIL. So is a label authored over the packaged one, a code-shipped objectExtensions scalar or a tenant's rename: it is served as authored in every locale (ADR-0029 D9.2a, an explicit override beats a packaged default)",
132132
"oracle": "screenshot",
133-
"verify": "review each captured Studio screenshot in two passes: (a) no dotted key path anywhere — that is an unconditional FAIL; (b) every residual English string sitting next to Chinese ones is checked against the frozen debt ratcheted by scripts/check-i18n-coverage.mjs + scripts/i18n-coverage-baseline.json — a string inside that debt is expected and ticks, a string the bundle DOES translate rendering English is the FAIL. User data (record values) is exempt",
133+
"verify": "review each captured Studio screenshot in two passes: (a) no dotted key path anywhere — that is an unconditional FAIL; (b) every residual English string sitting next to Chinese ones is checked against the frozen debt ratcheted by scripts/check-i18n-coverage.mjs + scripts/i18n-coverage-baseline.json — a string inside that debt is expected and ticks, a string the bundle DOES translate rendering English is the FAIL. An authored override ticks too: a code extension under examples/app-showcase/src/data/extensions/ or a runtime save of the object declares it, and GET /api/v1/meta/object/OBJ with Accept-Language zh-CN answers it for the scalars it overrides only (translateObject, packages/spec/src/system/i18n-resolver.ts; the showcase's Account (Success Overlay) beside pluralLabel 客户, account.extension.ts, QA run #29672). User data (record values) is exempt",
134134
"evidence": "the annotated screenshots + the coverage-baseline reading each residual English string was judged against"
135135
},
136136
{
137-
"clause": "relative dates follow the locale",
138-
"oracle": "screenshot",
139-
"verify": "the Studio Data pillar's records-grid timestamps render zh-CN relative forms (e.g. 6天前) after the switch, and English relative forms after the switch back; the metadata list / history surfaces carry absolute timestamps and are not this clause's subject",
140-
"evidence": "screenshot"
137+
"clause": "relative dates follow the locale: in a records grid the relative phrase is the date cell's tooltip, and it renders in the switched locale",
138+
"oracle": "dom",
139+
"verify": "after a screenshot confirms the Studio Data pillar's records grid settled, the date cell's title attribute reads a zh-CN relative form (e.g. 6天前) after the switch and the English form (6 days ago) after the switch back, while its painted absolute face follows the locale too (10月28日 / Oct 28); the metadata list / history surfaces carry absolute timestamps and are not this clause's subject",
140+
"evidence": "the grid screenshots and the title-attribute reads, in both locales"
141141
},
142142
{
143143
"clause": "the locale choice persists across a full reload — it is stored, not a transient client state",
@@ -153,7 +153,7 @@
153153
}
154154
],
155155
"negative": [
156-
"a Studio surface staying English after the app switched (mixed session) is the FAIL this item exists for — judged against the bundle, not by counting English words: a string the bundle feeding that surface translates (the console's metadata-admin catalogue for the Studio designers, the app's bundle for app labels such as navigation) rendering English is the FAIL; a string inside the frozen coverage debt rendering its EN source label is not. Check against a fresh objectui build before filing either way (the vendored /_console bundle may be stale)"
156+
"a Studio surface staying English after the app switched (mixed session) is the FAIL this item exists for — judged against the bundle, not by counting English words: a string the bundle feeding that surface translates (the console's metadata-admin catalogue for the Studio designers, the app's bundle for app labels such as navigation) rendering English is the FAIL; a string inside the frozen coverage debt rendering its EN source label is not, and neither is a label authored over the packaged one (a code extension scalar or a tenant rename, acceptance[1]), which is served as authored in every locale. Check against a fresh objectui build before filing either way (the vendored /_console bundle may be stale)"
157157
],
158158
"traps": ["stale-console-bundle"],
159159
"source": [
@@ -172,7 +172,8 @@
172172
{ "revision": 4, "date": "2026-10-05", "change": "the switch steps now name HOW to switch: through the avatar-menu language switcher, which writes the user's locale. Seeding browser storage alone is not a language switch. The 17.7 console run held a relative-date FAIL on this item, and its re-run on #21782 settled it as a harness gap: the first lane had set the UI language only in browser storage, so the user's stored locale stayed empty and dates followed the browser. Through the switcher the clause passed, so the clauses themselves are unchanged (card #21851 entry 11, filed with the follow-up run #21845)", "ref": "#21782" },
173173
{ "revision": 5, "date": "2026-10-13", "change": "steps[3] and acceptance[2].verify re-pointed to the surface that renders relative dates (stale step, #23163 A2; parked on #23121, carried by #23169). The metadata list and history surfaces carry no relative dates — history is absolute — so the step pointed at nothing scorable. QA run #23163 read relative dates (6天前) on the Studio Data pillar's records grid under zh-CN, through the avatar-menu switcher, and passed", "ref": "#23169" },
174174
{ "revision": 6, "date": "2026-10-16", "change": "knownGaps[0], fixtures.requires[0], steps[2], acceptance[0] (clause, verify), negative[0] and source re-pointed (checklist-accuracy notes 2 and 3 of QA run #23951, wave #23878). The clause-0 premise was wrong: the Studio object editor's strings come from objectui's metadata-admin catalogue (designer.object.* in packages/app-shell/src/views/metadata-admin/i18n.ts, ObjectDefaultInspector.tsx), not the served metadataForms group — #23951 read 标识、显示名与分类 / 显示名 where the group carries …分类标签 / 显示名称 — so the clause passed on its verify text while naming the wrong source, and negative[0] judged residual English against the wrong bundle. Both now name the catalogue that feeds the surface. The frozen debt count is 414, not 451 (scripts/i18n-coverage-baseline.json). Not loosened: a zh session still FAILS on any English string the feeding bundle translates, and on any raw dotted key", "ref": "#24036" },
175-
{ "revision": 7, "date": "2026-10-26", "change": "steps[2] names the metadata-admin catalogue at its path under ui/ instead of 'at the .objectui-sha pin': the objectui pin is retired and the console builds from this tree (pnpm console:build). Wording only, left to this file's card by #26035; the catalogue still carries 基础信息 / 标识、显示名与分类", "ref": "#25842" }
175+
{ "revision": 7, "date": "2026-10-26", "change": "steps[2] names the metadata-admin catalogue at its path under ui/ instead of 'at the .objectui-sha pin': the objectui pin is retired and the console builds from this tree (pnpm console:build). Wording only, left to this file's card by #26035; the catalogue still carries 基础信息 / 标识、显示名与分类", "ref": "#25842" },
176+
{ "revision": 8, "date": "2026-11-03", "change": "acceptance[2] (clause, oracle, verify, evidence) and steps[3] read the relative date where it is drawn now, and acceptance[1] and negative[0] carry the authored-override exception. Relative dates: the #25884 ruling paints the absolute face in a grid column and the relative phrase as the cell's tooltip (DateCellRenderer, inGridColumn, ui/packages/fields/src/index.tsx), so QA run #29672 read 10月28日 painted with title 6天前 (en: Oct 28, 6 days ago) and scored the clause FAIL as stale spec; the card names it acceptance[3], the run's one-based number. The clause now reads the tooltip, as a dom read of the title attribute, in both directions; the locale-following phrase it asks for is unchanged. Mixed language (the addendum, 6593917345, from #29675 closed not planned): the run counted Account (Success Overlay) on a zh-CN Studio as a fail, but it is the showcase's code-shipped objectExtensions label (examples/app-showcase/src/data/extensions/account.extension.ts), and ADR-0029 D9.2a makes an explicit override beat the packaged catalog in every locale (translateObject; the i18n-resolver.test.ts case \"a code-shipped extension's scalars beat the catalog\", and packages/rest/src/meta-object-i18n-explicit-override.test.ts). A bundle-translated string drawn English with no override is still the FAIL. Read at base 339f63da30. Card #29679, from QA run #29672", "ref": "#29679" }
176177
]
177178
},
178179
{

0 commit comments

Comments
 (0)