Skip to content

test(docs): converge the zh-Hant tile term, and check the vocabulary the rule reads with - #1374

Merged
os-steve merged 2 commits into
mainfrom
claude/issue-949-tile-vocabulary-coverage
Aug 27, 2026
Merged

test(docs): converge the zh-Hant tile term, and check the vocabulary the rule reads with#1374
os-steve merged 2 commits into
mainfrom
claude/issue-949-tile-vocabulary-coverage

Conversation

@claude

@claude claude Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Fixes #949

Converges the one Traditional page that called a dashboard tile 「磁磚」 onto 「磁貼」, and closes the two blind spots that let the discrepancy sit unread — plus the third one the first two exposed.

Premise check

⚠️ The card and its triage both name the wrong file. Both place DOC_PAGES / TILE_WORDS in test/docs-drift.test.ts at :572 / :608. That suite was split into 24 test/docs-*.test.ts files; the constants live in test/docs-dashboard-tiles.test.ts at :68 / :104, contents unchanged. The dispatch flagged this and it is confirmed. No line number on the card was trusted.

Everything else re-measured on origin/main @ c772cbe and reproduced exactly:

content/docs/service/cases.zh-Hant.mdx         「磁磚」 x4 on 3 lines (:167 x2, :212, :220)
content/docs/analytics/dashboards.zh-Hant.mdx  「磁貼」 x15               (control group)
TILE_WORDS = ['tiles', 'tile', '磁贴', '磁貼']   — no 磁磚
DOC_PAGES  = the three analytics/dashboards pages — no service page

The 磁磚 lines are character-for-character parallel with their zh-Hans siblings, which write 磁贴 in all four positions. The Simplified sentence 數量則看服務概覽上的 **SLA Violations** 磁贴。 was a readable tile reference; the identical Traditional one was read by nothing, from both sides at once.

The three decisions, done as three

  1. Converge the terminology. 磁磚 → 磁貼, 4 occurrences.
  2. List 磁磚 in TILE_WORDS anyway, as a backstop. Doing only (1) is the trap: 磁磚 is an ordinary Traditional word for a tile, the next translator reaches for it, and the reference silently stops being read.
  3. Widen the page set so service-side references are covered.

On (3) I widened to every .mdx under content/docs, derived by walking the tree, rather than appending the service pages to the list. A hand-written page set has the same defect as a hand-written word list — it is self-consistent and cannot report what it omits — so extending it would have moved the blind spot rather than closed it. Measured: 3 pages before, 201 after; the newly covered references are **SLA Violations** tile on five service pages, **Tasks Completed** tile on three sales pages, **Open Leads** tile on three analytics pages and **KB Deflection Rate** tile on the service index. All resolve.

⚠️ The ALL_TITLES scope call, stated

Widening forces a choice, because a dashboards page reference sits inside a ## dashboard-label section and could be narrowed to that dashboard's own widgets, while a reference on service/cases.zh-Hant.mdx cannot — nothing on that page says which dashboard is meant.

Chosen: the union of every tile title, for every page. In order of weight:

  • Narrowing is wrong even on the page that affords it. Running prose is exactly where cross-dashboard advice belongs — "compare this with the SLA Violations tile on Customer Service" is correct writing that a narrowed rule would fail, with no way to spell the intent. The case this rule was written for, content/docs/analytics/dashboards.mdx describes tiles that no dashboard ships (near-total drift, plus a fabricated usage stat) #610's "use the Slipping Deals tile every Friday", sits in a Tips section belonging to no dashboard at all.
  • The strength given up is narrower than it sounds. The strong per-dashboard check still runs where it applies: the tile list rule resolves - **Name** — … against that dashboard only, unchanged. What relaxes to the union is running prose, and only running prose.
  • One rule with one meaning beats two strengths for the same sentence depending on which file it was written in.

Stated plainly: this now enforces that a documented tile name exists somewhere in the app — a notch weaker per reference than a three-page rule could have been, applied to 201 pages instead of 3. That is the trade, made deliberately. The reasoning is in the source at ALL_TITLES, not only here.

⭐ Making the coverage half checkable

#725's self-check probes each word already in TILE_WORDS, so it proves those words are readable and structurally cannot notice that a page uses one the list lacks. It is self-consistent with its own vocabulary and inconsistent with reality. Three rules were added that fail on a gap instead of being silent about one:

rule asks bound
every Chinese tile spelling the docs use is one TILE_WORDS can read did I list the words the pages use? the 磁 family — stated in source, not implied
each locale spells "tile" exactly one way did the terminology stay converged? authors nothing canonical: one locale, one word, whichever that locale already uses
both Chinese scripts read the same tile references did a spelling drop out of reach? family-agnostic; the two scripts are character-parallel here

The third rule catches a missing word without anyone having to guess it in advance, which is the property the self-check could never have.

The second rule was added because ablation A4 below measured a hole in the first draft: with 磁磚 listed, a relapse left all ten rules green. The backstop keeps a relapsed reference readable — that is its job — but the triage called the inconsistency itself the user-visible defect, and nothing was keeping it loud.

Two bounded in-place fixes, named with their evidence

1. test/docs-dashboard-tiles.test.ts — the extraction walks bold runs instead of matching one regex. Required by the widening, not a drive-by. A regex cannot tell an opening ** from a closing one:

- **Pipeline by Stage** is a dashboard **tile** and a chart title

The engine fails at the real opener ( is a… is not a tile word), restarts at the closing **, and matches the prose between the two bold runs — reporting a phantom tile named is a dashboard. Invisible while the rule read three pages that do not write that sentence; analytics/reports.mdx and both translations do, so widening surfaced three at once. Splitting a line on ** is what markdown itself does: segments alternate plain/bold, an odd index is a bold run, and is a dashboard lands on an even index where it can never be read as a name. Measured over all of content/docs: the two extractions agree on every real reference and differ only by those three phantoms.

2. test/docs-drift.test.ts — one comment line. The SPLIT BY FAMILY routing table describes this suite; its row went stale the moment the scope widened. Comment only, no assertion touched — the shape #931 was filed for.

Both were declared on the claim comment before the first commit.

Acceptance: the widened rule catching something

Every leg ran from a committed tree, mutation proven on disk by occurrence count before the suite ran, restore proven by git hash-object against the HEAD blob, absolute paths, trap … EXIT INT TERM.

# mutation predicted measured
A1 Open the **Bogus Tile** tile every Friday. into content/docs/service/cases.mdx — a newly covered page red, prose rule only 1 failed | 9 passed× every "**Name** tile" … names a real tile
A2 **SLA Violations** 磁貼磁塊 on cases.zh-Hant.mdx — a spelling no rule carries red, vocabulary rule 2 failed | 8 passed — vocabulary and script-parity; stronger than predicted, because dropping out of reach also costs Traditional its reference
A3 the original defect rebuilt: page back to 磁磚 and 磁磚 out of TILE_WORDS red on the coverage rules 3 failed | 8 passed — all three
A4 relapse: page back to 磁磚, 磁磚 stays in TILE_WORDS backstop keeps the reference readable 1 failed | 10 passed — only the terminology rule; the reference is still checked, the split is now loud

⚠️ A3 and A4 were run twice. The first attempt asserted count('磁貼') == 3 where the file holds 4 occurrences on 3 lines, so the mutation script aborted, the tree was never mutated, and vitest reported 10 passed — a healthy-looking reading of the unmutated tree. The on-disk proof line caught it (page 磁磚=0 (want 3)). Both legs were re-run behind a hard gate that refuses to invoke the suite unless the occurrence counts match. The first run produced no reading and none is quoted above.

Verification

pnpm verify green on 5e0a2da, the final commit, run after it:

✓ objectstack validate · tsc --noEmit · objectstack lint
✓ i18n lint gate: 0 `i18n/missing-*` issues
✓ source hygiene clean
✓ source token ratchet clean
✓ objectstack build → dist/objectstack.json (1969.8 KB)
  Test Files  147 passed (147)
       Tests  3064 passed | 1 skipped (3065)

The tile suite goes 8 rules → 11.

Changeset

Empty frontmatter. No src/ metadata changed — no object, field, view, label, page, dashboard or hook; the diff is docs prose plus two test files. Verified against the diff rather than assumed, and matching PR #1367, a content/docs prose PR from this week that used the same declaration. The skip-changeset label is not used.

Scope

Out, and untouched: #802 / #809 / #837, the split-suite structure, and other locales' terminology. The 磁贴 Simplified pages were not edited.

Generated by Claude Code


Generated by Claude Code

claude added 2 commits August 27, 2026 14:33
…he vocabulary

The tile-reference rule had two blind spots of the same shape: a hand-written
three-page list, and a hand-written word list that only its own self-check
looked at. Neither could report what it omitted.

content/docs/service/cases.zh-Hant.mdx wrote 磁磚 four times where every other
Traditional page writes 磁貼, so Traditional readers met two names for one
screen element and its **SLA Violations** 磁磚 reference was read by nothing --
while the character-for-character identical zh-Hans sentence was readable, had
that page been in scope.

- Converge the page onto 磁貼, and keep 磁磚 in TILE_WORDS as a backstop so a
  relapse is caught instead of silently unread. Two decisions, not one.
- Derive the prose rule's page set by walking content/docs instead of listing
  three pages, so a page that names a tile is in scope the day it is written.
- Walk bold runs instead of matching one regex. A regex cannot tell an opening
  ** from a closing one, so `**Pipeline by Stage** is a dashboard **tile**`
  yielded a phantom tile named "is a dashboard" -- invisible on three pages,
  three occurrences once the rule reads the tree.
- Add the coverage half the #725 self-check structurally cannot do: every
  magnetic-family spelling the docs use must be one TILE_WORDS can read, and
  the two Chinese scripts must read the same tile references.

Prose references resolve against the union of every tile title, on every page.
The reasoning for that scope choice is stated at ALL_TITLES.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
A4 of the ablation set measured the hole this closes: with 磁磚 listed as a
backstop, a translator writing it back into a zh-Hant page left all ten rules
green. The backstop keeps the relapsed reference READABLE, which was its job --
it does not keep the docs consistent, and the triage on #949 called the
inconsistency itself the user-visible defect (a Traditional reader met 磁磚 on
cases and 磁貼 on dashboards, sla-and-escalation and faq).

Nothing canonical is authored: the rule is one locale, one word, and which word
is whatever that locale already uses -- so it holds the tree to its own
convention rather than to a preference written into a test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 27, 2026 2:47pm

Request Review

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