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:
prosolis
2026-07-28 00:09:42 -07:00
parent 3bcc967f51
commit 25e415daa2
20 changed files with 917 additions and 15 deletions
+38
View File
@@ -523,6 +523,44 @@ CREATE TABLE checked_chunks (
hash TEXT NOT NULL,
PRIMARY KEY (doc_id, family, hash)
);
`,
},
{
// A sentence she wrote in her own language gets its own type. Petal already
// detected such spans and already rendered them into English — it just
// filed the result under 'clarity', so the pair model's flagship moment
// read as tidying up her Chinese. As with 0005 and 0008, the `type` CHECK
// can't be ALTERed in place, so rebuild the table with the extended
// constraint, copy every row across, and recreate both indexes.
//
// Existing rows are left on whatever type they have. A card she is already
// reading keeps the label she has already read (the same rule reconcile.go
// follows for a re-proposed edit); new findings get the new label.
name: "0015_translate_suggestion_type",
stmt: `
CREATE TABLE suggestions_new (
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
doc_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
from_pos INTEGER NOT NULL,
to_pos INTEGER NOT NULL,
original TEXT NOT NULL,
replacement TEXT NOT NULL,
explanation TEXT NOT NULL,
type TEXT NOT NULL CHECK(type IN ('grammar','phrasing','idiom','clarity','translate','voice','collocation','mechanics')),
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','accepted','rejected')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
resolved_at DATETIME,
source TEXT NOT NULL DEFAULT 'llm',
chunk_hash TEXT NOT NULL DEFAULT ''
);
INSERT INTO suggestions_new (id, doc_id, from_pos, to_pos, original, replacement, explanation, type, status, created_at, resolved_at, source, chunk_hash)
SELECT id, doc_id, from_pos, to_pos, original, replacement, explanation, type, status, created_at, resolved_at, source, chunk_hash FROM suggestions;
DROP TABLE suggestions;
ALTER TABLE suggestions_new RENAME TO suggestions;
CREATE INDEX idx_suggestions_doc_id ON suggestions(doc_id);
CREATE INDEX idx_suggestions_resolved ON suggestions(status, resolved_at);
`,
},
}