Skip to content

test(docs): check view-roster name columns on the Chinese faces too - #1556

Merged
os-sales merged 2 commits into
mainfrom
claude/issue-1551-view-roster-translated-faces
Sep 3, 2026
Merged

test(docs): check view-roster name columns on the Chinese faces too#1556
os-sales merged 2 commits into
mainfrom
claude/issue-1551-view-roster-translated-faces

Conversation

@os-sales

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

Copy link
Copy Markdown
Collaborator

Fixes #1551

test/docs-view-rosters.test.ts checked view-name exactness on the English
faces only, and said so for a real reason: while two spellings were lawful on
the Chinese pages — the zh-CN pack wording on some, the English label on
others — 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. No src/ metadata and
no content/docs/ prose changed.

The two translated faces are not symmetric, and are not built the same way

  • zh-Hans is DERIVED, live. src/translations/zh-CN.ts carries a _views
    entry for every view a documented object ships — 55 of 55, measured — and
    the Chinese console resolves a view's label through it, which is what makes
    the 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 in
    the pack turns the page red without the page changing — ablated below.
  • zh-Hant is PINNED, by hand, and says so. i18n.supportedLocales is
    en / 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_NAMES table opens by stating that, states what it cannot buy (a
    rename 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 -l on this tree:
合同合約 (308); 营销行銷 (230), strict-glyph 營銷 0;
联系人聯絡人 (270), strict-glyph 聯繫人 0. A derivation is wrong on
all three, across four pages, the day it is written.

revenue/approvals is out by structure, not by exemption

That 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. There
is 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 rosterOf returns null for it on all three faces and
it never enters PAGE_OBJECT or any rule in this file. Whether those names
should 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 at b3f03130, 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 HEAD with the blob hash back at its HEAD value. One attempt was
voided by the harness for mutating as an insertion rather than a
replacement, and re-run — the harness is not rubber-stamping.

mutation red
service/cases.zh-Hans 全部工单 → 全部工單 zh-Hans rule: names "全部工單", which is not the zh-CN spelling of any view crm_case ships
revenue/contracts.zh-Hant 合約條款 → 合同條款 zh-Hant rule: names "合同條款", which is in no pinned Traditional roster for crm_contract
zh-CN.ts all_products 全部产品 → 全部产品清单 zh-Hans rule on revenue/products.zh-Hans — the page did not move, the pack did
zh-CN.ts crm_case._views.all_cases key renamed producer rule: crm_case._views.all_cases is missing — "All Cases" is named on content/docs/service/cases.mdx
src/views/product.view.ts product_catalogcatalog_gallery four rules, pin audit among them: crm_product.catalog_gallery ("Product Catalog", …) has no pinned name
phantom_view added to ZH_HANT_VIEW_NAMES pin audit: crm_product.phantom_view is pinned as "幻影檢視", which the app does not ship
## 標準列表檢視 renamed on revenue/products.zh-Hant vacuity guard: zh-Hant: roster sections this rule read no name column out of: content/docs/revenue/products.zh-Hant.mdx

Row 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 same
way (expectNameColumnIsReadable — did this rule read a name column out of every
mapped 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 phantom check
and 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

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
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 3, 2026 11:39am UTC

Request Review

@github-actions github-actions Bot added the ci/cd CI plumbing and the verification pipeline label Sep 3, 2026
@os-sales
os-sales marked this pull request as ready for review September 3, 2026 11:43
@os-sales
os-sales added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit f4068c4 Sep 3, 2026
10 checks passed
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline

Projects

None yet

2 participants