Stop regenerating the world on every check
A card vanishing and coming back seconds later, with different words, was never about latency: every pass deleted its whole family and re-inserted it, so each round minted new row ids. The rail keys on suggestion.id, so a full remount was guaranteed — new id, new created_at (hence the re-fired chime), and a fresh explanation from a model that re-reasons every time it is asked. One unchanged mistake carried three different explanations in a single sitting. Passes now reconcile instead of replace. A re-proposed edit keeps its row: its id, its created_at, and the wording she has already read. And the grammar checkpoint stops asking about sentences nobody touched — the document is split into hashed sentences, checked_chunks records which ones a family has read, and only the difference is sent. When nothing changed it doesn't call the model at all, and doesn't spend its rate-limit slot on having done nothing. The tone is part of a sentence's identity: cached advice was written for the old register, so switching doc type re-reads every line. replaceMechanics reconciles too, which mattered more than expected — the rule pack fires 250 ms after a keystroke, so it was re-minting every local card's id several times a sentence. Only the grammar checkpoint is chunked. Voice is a property of the whole document, and the collocation coach is a button she pressed asking for a fresh read. No client change was needed; stable ids were the whole of it. Claude-Session: https://claude.ai/code/session_016y6gyuHkQXPiEuW8RGQyua
This commit is contained in:
@@ -497,6 +497,32 @@ CREATE INDEX idx_suggestions_resolved ON suggestions(status, resolved_at);
|
||||
stmt: `
|
||||
ALTER TABLE suggestions ADD COLUMN source TEXT NOT NULL DEFAULT 'llm';
|
||||
UPDATE suggestions SET source = 'local' WHERE type = 'mechanics';
|
||||
`,
|
||||
},
|
||||
{
|
||||
// Sentence-level identity, so a re-check stops regenerating the world.
|
||||
// Every pass used to delete its whole family and re-insert it, which
|
||||
// meant accepting one edit gave every other card a new id and a newly
|
||||
// worded explanation — the rail visibly emptied and refilled, and the
|
||||
// model was asked again about sentences nobody had touched.
|
||||
//
|
||||
// `chunk_hash` records which sentence a suggestion belongs to, and
|
||||
// checked_chunks records which sentences a family has already read. A
|
||||
// re-check then asks only about the difference and keeps the rest of
|
||||
// the rows exactly as they are, id and wording included.
|
||||
//
|
||||
// Existing rows get '' — "sentence unknown", which reads as in-play, so
|
||||
// they are simply reconciled on the next pass like any fresh finding.
|
||||
name: "0014_suggestion_chunk_hash",
|
||||
stmt: `
|
||||
ALTER TABLE suggestions ADD COLUMN chunk_hash TEXT NOT NULL DEFAULT '';
|
||||
|
||||
CREATE TABLE checked_chunks (
|
||||
doc_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
|
||||
family TEXT NOT NULL,
|
||||
hash TEXT NOT NULL,
|
||||
PRIMARY KEY (doc_id, family, hash)
|
||||
);
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user