test(docs): check view-roster name columns on the Chinese faces too - #1556
Merged
Conversation
The name-exactness rule in `test/docs-view-rosters.test.ts` was scoped to the English faces because two spellings were lawful on the Chinese ones and no single string could be checked against. #1329's ruling (2026-08-31) ended that split and PR #1548 executed it; item 3 declares this guard's extension unlocked. zh-Hans is derived live from `src/translations/zh-CN.ts` — the producer the Chinese console itself resolves labels through — keyed by the view key `src/views/**` registers. A companion rule fails first when a shipped view has no `_views` entry, so a pack gap is reported at the pack rather than as a phantom name on the page. zh-Hant has no producer: the app ships no Traditional pack and nothing in the repo generates those strings. It is a pinned, hand-maintained table that says so in its own header, audited one-to-one against the shipped views so a view arriving or leaving fails until a human writes its Traditional name. It is deliberately not derived: the corpus convention substitutes words, not glyphs (合同 → 合約, 营销 → 行銷, 联系人 → 聯絡人, the last two with zero occurrences of their strict-glyph forms). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t
…ules Seven ablations, one per rule and one per leg of the pin audit, each with its red quoted verbatim. Mutations were proved on disk by blob hash and anchored counts on both the removed and the injected text; restores by an empty `git diff HEAD` with the blob hash back at its HEAD value. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
os-sales
marked this pull request as ready for review
September 3, 2026 11:43
os-sales
added a commit
that referenced
this pull request
Sep 3, 2026
`test/docs-view-rosters.test.ts` runs two complementary directions on the English face — coverage (every view the app ships is named in its page's roster) and name exactness (the name column names only views the app ships). #1551 gave the translated faces name exactness plus a structural rule pinning each face to the English page's roster row count, and no coverage. Those three leave one shape open: a roster that keeps the row count, names only lawful names, but names one view twice and omits another. Measured before writing anything, on the tree #1556 landed: `revenue/ products.zh-Hans` with both rows renamed to 全部产品 — dropping 产品目录, two rows in and two rows out — ran 9 passed. Green over the defect. The rules read the NAME COLUMN, not the section body. The English coverage rule asks `body.includes(label)`, a pure existence question over prose as well as table, so it cannot see a duplicate at all and misses the omission whenever the prose mentions the dropped name — measured, 9 of the 55 names on each of the three faces are echoed in the body outside their own row, and on one of them a body-shaped rule stays green over this exact defect. Coverage and not set equality, deliberately: set equality implies name exactness and would make #1551's two rules dead weight. The count rule keeps its place too — coverage and exactness pin the SET of names and say nothing about multiplicity, so an extra row repeating a lawful name fails only the count rule. `revenue/approvals` stays out structurally, inherited rather than restated: the rules walk PAGE_OBJECT and `rosterOf`, and that page has no roster heading on any face. No exemption list grew and #1552 is untouched. Nothing under `content/docs/**` or `src/` changes, and nothing needed to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1551
test/docs-view-rosters.test.tschecked view-name exactness on the Englishfaces only, and said so for a real reason: while two spellings were lawful on
the Chinese pages — the
zh-CNpack wording on some, the English label onothers — there was no single string a name column could be checked against.
#1329's ruling (2026-08-31) ended that split, PR #1548 executed it, and
item 3 of that ruling declares this guard's extension unlocked. This is the
extension.
Surface:
test/docs-view-rosters.test.ts+ a changeset. Nosrc/metadata andno
content/docs/prose changed.The two translated faces are not symmetric, and are not built the same way
src/translations/zh-CN.tscarries a_viewsentry for every view a documented object ships — 55 of 55, measured — and
the Chinese console resolves a view's
labelthrough it, which is what makesthe pack wording the string a reader can search the UI with. The allowed set
is read off the pack at run time, keyed by the view key
src/views/**registers, exactly as the English rule reads the shipped
label. A rename inthe pack turns the page red without the page changing — ablated below.
i18n.supportedLocalesisen / zh-CN / ja-JP / es-ES. This app ships no Traditional pack, nothing in
the repo produces those strings, and nothing but this rule reads them. The new
ZH_HANT_VIEW_NAMEStable opens by stating that, states what it cannot buy (arename that happens only upstream will never move it), and is audited
one-to-one against the shipped views so a view arriving or leaving fails here
until a human writes its Traditional name.
⛔ Deliberately not derived by glyph conversion. #1329's dev measured that
the corpus convention substitutes words; a third case turned up writing this
rule. Counted with
grep -ro <term> content/docs | wc -lon this tree:合同→ 合約 (308);营销→ 行銷 (230), strict-glyph 營銷 0;联系人→ 聯絡人 (270), strict-glyph 聯繫人 0. A derivation is wrong onall three, across four pages, the day it is written.
revenue/approvalsis out by structure, not by exemptionThat page names five views owned by the approval plugin's
sys_approval_request, and this app's pack has no entry for any of them. Thereis no exclusion list and no quarantine entry: the page heads those tables Where
to find pending approvals / the object's own list views and carries no
roster heading at all, so
rosterOfreturns null for it on all three faces andit never enters
PAGE_OBJECTor any rule in this file. Whether those namesshould be checked, and against what, is open on #1552 — nothing here answers
that and nothing here forecloses an answer.
Green, then proved able to go red
pnpm verify— validate, typecheck, lint,lint:i18n-gate, hygiene,hygiene:tokens, build, test — is green atb3f03130, the tip of this branch:✓ Validation passed·✓ i18n lint gate: 0·✓ source hygiene clean·✓ source token ratchet clean·✓ Build complete·Test Files 159 passed (159)/Tests 3348 passed | 1 skipped (3349).This file goes 5 → 9 rules, reading 55 name cells per translated face, 0
unresolved on each, with no page edited to get there.
A new guard accepted on a green run alone is not evidence it works, so each rule
was ablated. Every mutation was proved on disk by blob hash and anchored
counts on both the removed and the injected text; every restore by an empty
git diff HEADwith the blob hash back at its HEAD value. One attempt wasvoided by the harness for mutating as an insertion rather than a
replacement, and re-run — the harness is not rubber-stamping.
service/cases.zh-Hans全部工单 → 全部工單names "全部工單", which is not the zh-CN spelling of any view crm_case shipsrevenue/contracts.zh-Hant合約條款 → 合同條款names "合同條款", which is in no pinned Traditional roster for crm_contractzh-CN.tsall_products全部产品 → 全部产品清单revenue/products.zh-Hans— the page did not move, the pack didzh-CN.tscrm_case._views.all_caseskey renamedcrm_case._views.all_cases is missing — "All Cases" is named on content/docs/service/cases.mdxsrc/views/product.view.tsproduct_catalog→catalog_gallerycrm_product.catalog_gallery ("Product Catalog", …) has no pinned namephantom_viewadded toZH_HANT_VIEW_NAMEScrm_product.phantom_view is pinned as "幻影檢視", which the app does not ship## 標準列表檢視renamed onrevenue/products.zh-Hantzh-Hant: roster sections this rule read no name column out of: content/docs/revenue/products.zh-Hant.mdxRow 3 is the property the derived side exists for. Row 2 is exactly the mistake
a glyph-derived zh-Hant rule would have made, caught by the pinned one.
The English path is not rewritten
Parsing a name column is now one code path shared by the three faces
(
nameColumns), and so is the pair of vacuity checks every face answers the sameway (
expectNameColumnIsReadable— did this rule read a name column out of everymapped page at all, and does every cell open with a bold run). What each rule
allows in that column, and what its failure means, stays in the rule with its
own message, because those are three different facts and a generic message would
be worse than three specific ones. The English rule's body is its
phantomcheckand nothing else now; its messages are unchanged.
The structural entry-count rule stays and its message is corrected: it no longer
claims names cannot be checked here. It still earns its place as the rule that
notices a face losing or gaining a row, which a name rule reading only the
rows that are there cannot.
🤖 Generated with Claude Code
https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t
Generated by Claude Code