When she writes in Chinese, say Translate — not Clarity
She reaches for her own language mid-sentence when English won't come, and Petal already handled it: it found the span and rendered it into English. It just filed the result as a Clarity fix, so the pair model's flagship moment read as tidying up her Chinese. The type is now derived from the span rather than asked of the model. A type is structural, and a model that re-reasons every pass would drift between labels for a sentence nobody had touched — the instability the last session spent itself removing. The label the model volunteers is still ignored. Only the grammar checkpoint can be promoted. A pass with a forced type owns its family: voice reads paragraphs for tone and its rows carry no replacement, so a "translation" there would be a card offering nothing to accept. zh is a different script and counting Han runes is close to certain. The Latin pairs share an alphabet with English and get none of that, so they fall back to function words and need two before Petal claims anything — with every word that is also English left out, even the common ones. The heuristic is justified by how cheap being wrong is: it changes a coloured pill, and nothing else. The pill is the one bilingual type name in the rail. Every other type stays English because those are the terms she is learning; this card's whole subject is her own language. And it stops truncating its two lines — elsewhere the diff is a word and the explanation is what she reads, but here the two sentences are the card. Two things only the running page could report. The inline underline was invisible: the decoration carries a per-type class and the base rule is a transparent border, so a type with no colour rule gets no mark at all. And at 1517×810 with the document list open there is no rail — the margin is 258 where railEnabled wants 348 — so what she gets is the inline hover card. Item 7 is written the other way round. Migration 0015 rebuilds the suggestions table for the CHECK, which makes it the first one here that could quietly drop her rows; there is a test that carries every column, both timestamps and both indexes across it. Claude-Session: https://claude.ai/code/session_016y6gyuHkQXPiEuW8RGQyua
This commit is contained in:
@@ -11,6 +11,20 @@ import type { Pack } from './types'
|
||||
// author's pack satisfies isn't a shape, it's a coincidence.
|
||||
const PACKS: Pack[] = [zh, ptPT, fr]
|
||||
|
||||
// Every string a pack would ever put on screen, and nothing else — field names
|
||||
// excluded (see the pt-PT grep below for what including them cost). Templates are
|
||||
// invoked so an interpolated line is checked as she'd read it, with the same
|
||||
// stand-in arguments the old JSON replacer used.
|
||||
function copyOf(p: Pack): string {
|
||||
const strings = (v: unknown): string[] => {
|
||||
if (typeof v === 'string') return [v]
|
||||
if (typeof v === 'function') return strings((v as (...a: unknown[]) => unknown)(1, 'x'))
|
||||
if (v && typeof v === 'object') return Object.values(v).flatMap(strings)
|
||||
return []
|
||||
}
|
||||
return strings(p).join('\n')
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
resetPackForTests()
|
||||
})
|
||||
@@ -194,10 +208,23 @@ describe('the pt-PT pack', () => {
|
||||
// is invisible to anyone who doesn't read Portuguese — including whoever
|
||||
// reviews this diff.
|
||||
it('is European Portuguese, not Brazilian', () => {
|
||||
// The pack's *copy*, and only its copy. Keys are English identifiers and can
|
||||
// never be Brazilian, but they used to be in this haystack — and a naive
|
||||
// substring grep duly failed on `translateLabel`, which lowercases to
|
||||
// "transla·tela·bel" and so "contains" the pt-BR *tela*. A test that fires on
|
||||
// its own field names is a test that gets deleted the third time it does it.
|
||||
//
|
||||
// Lowercased: half this copy is sentences, and a form that only ever appears
|
||||
// at the start of one ("Actualmente…") would otherwise walk straight past
|
||||
// both greps below.
|
||||
const text = JSON.stringify(ptPT, (_k, v) => (typeof v === 'function' ? v(1, 'x') : v)).toLowerCase()
|
||||
const text = copyOf(ptPT).toLowerCase()
|
||||
|
||||
// Canaries. Every assertion below is a *negative*, so a copyOf that quietly
|
||||
// returned nothing — or stopped invoking templates — would make this whole
|
||||
// test pass by having nothing to search. The second line is inside a
|
||||
// function, and only appears if templates are still being called.
|
||||
expect(text, 'copyOf collected no pack copy').toContain('sinónimos')
|
||||
expect(text, 'copyOf stopped invoking templates').toContain('já vais em 1 palavras')
|
||||
|
||||
// Brazilian spellings and vocabulary that would give the pack away.
|
||||
for (const bad of ['sinônimo', 'acadêmico', 'arquivo', 'tela', 'salvar', 'deletar', 'usuário', 'você']) {
|
||||
|
||||
Reference in New Issue
Block a user