fix(cat): forgetting "work" deleted network, framework and coworking - #831
Merged
Conversation
The containment branch compared raw substrings both ways, and
MIN_FORGET_FRAGMENT_CHARS lets a four-character fact through. So "work" was
contained in "network", "framework", "coworking" and "homework": a user asking
Cat to forget "work" lost every memory that merely SPELLED it.
Reproduced before fixing — against a corpus of five memories, forgetting "work"
deleted three the user never mentioned. Cat then reported those three as
removed, accurately, which is exactly what makes this hard to notice: the
report is true, the deletion was not asked for.
This is the mirror of finding 8, shipped an hour ago, and the worse half. That
bug told someone a memory survived when it was gone; this one destroys memories
they never named, irreversibly.
Containment is now word-boundaried in both directions. Boundaries are checked
by CHARACTER CLASS, not a `\b` regex, because `\b` is ASCII-only in JavaScript:
it treats "café" as ending after "caf", so "café" would match inside
"cafétéria" while plain words behaved correctly. `\p{L}`/`\p{N}` cover the
accented alphabet the tokenizer in this file already speaks.
Deliberately NOT touched: the stemmer. "cafés" → "café", "weekends" →
"weekend", "photography" → "photographer" are the matches stemming exists for,
and a test now pins that they still fire — this narrows raw containment only.
One of my own test expectations was wrong on exactly that point and was
corrected rather than the code.
#563 finding 9. #555, which the finding said to coordinate
with, is closed.
73 Cat suites (1031 tests) and type-check green — the risk in narrowing a match
is under-matching, so the existing forget tests are the real check here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018waGt1ieA9TjpscqrbrnGb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes finding 9 of #563.
The containment branch compared raw substrings both ways, and
MIN_FORGET_FRAGMENT_CHARSlets a four-character fact through. So"work"was contained in network, framework, coworking and homework — a user asking Cat to forget "work" lost every memory that merely spelled it.Reproduced before fixing. Against a five-memory corpus, forgetting
"work"deleted three the user never mentioned:Cat then reported those three as removed — accurately, which is exactly what makes it hard to notice. The report is true; the deletion was never asked for.
This is the mirror of finding 8 (shipped an hour ago) and the worse half: that bug told someone a memory survived when it was gone, this one destroys memories they never named, irreversibly.
The fix
Containment is now word-boundaried in both directions.
Boundaries are checked by character class, not a
\bregex, because\bis ASCII-only in JavaScript: it treatscaféas ending aftercaf, so"café"would match insidecafétériawhile plain words behaved correctly.\p{L}/\p{N}cover the accented alphabet the tokenizer in this file already speaks.Deliberately not touched: the stemmer
cafés → café,weekends → weekend,photography → photographerare the matches stemming exists for, and a test now pins that they still fire. This narrows raw containment only.One of my own test expectations was wrong on exactly that point — I'd asserted
caféshouldn't matchcafés, but the stemmer unifies them by design. Corrected the test, not the code.Verification
6 new tests (over-match, whole-word-in-sentence, multi-word phrase, prefix-of-longer-word, accents, stemmer-still-works).
73 Cat suites (1031 tests) and
type-checkgreen — the risk when narrowing a match is under-matching, so the existing forget tests are the real check here.#555, which the finding said to coordinate with, is closed.