Skip to content

fix(cat): "we could not look" was reported as "you have no such memory" - #828

Merged
github-actions[bot] merged 1 commit into
mainfrom
fix/forget-failure-is-not-no-match
Aug 29, 2026
Merged

fix(cat): "we could not look" was reported as "you have no such memory"#828
github-actions[bot] merged 1 commit into
mainfrom
fix/forget-failure-is-not-no-match

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

Closes finding 8 of #563.

Both forget stores swallowed database errors into { deleted: [], notFound: wanted }the exact shape they return when they looked properly and found nothing. So a user who asked Cat to forget something was told it wasn't there, in two situations where it was:

  • the SELECT failed, so we never read the corpus at all;
  • the DELETE failed, so we had matched their memory and left it in place.

The second is the bad one. Cat found the memory, couldn't remove it, and replied that nothing matched — while the fact the user had just disowned was still stored. Telling someone their data is gone when it isn't is the worst thing a forget feature can do, and it did it silently.

The fix

ForgetResult and ProfileRemovalResult now carry a failed channel, separate from notFound, at all three swallow sites (memory load, memory delete, profile upsert).

Both consumers report it honestly:

  • exec_action handlersuccess: false with "Could not reach your memories just now, so nothing was removed… Nothing has been deleted." Checked before the no-match branch, because that branch's wording is a factual claim about the user's data that we're in no position to make when the query failed.
  • LLM tool path → a failedToRemove list plus an instruction to say the removal did not happen and never to describe those entries as absent or removed.

One existing test had pinned the bug

// memory-forget.test.ts, before:
it('a failed delete reports nothing as deleted', )
expect(result.notFound).toEqual(['photography']);   // ← the lie, asserted

Corrected rather than worked around, and it now says why. Three tool-executor-forget fixtures predated the new field and are extended.

Verification

Mutation-proven: reverting either swallow site fails exactly one of the four new tests — the load-error revert fails the read test, the delete-error revert fails the delete test.

72 Cat suites (1025 tests) and type-check green.

Both forget stores swallowed database errors into `{ deleted: [], notFound:
wanted }` — the exact shape they return when they looked properly and found
nothing. So a user who asked Cat to forget something was told it was not there,
in two different situations where it was:

  * the SELECT failed, so we never read the corpus at all;
  * the DELETE failed, so we HAD matched their memory and left it in place.

The second is the bad one. Cat found the memory, could not remove it, and
replied that nothing matched — while the fact the user had just disowned was
still stored. Telling someone their data is gone when it is not is the worst
thing a forget feature can do, and it did it silently.

ForgetResult and ProfileRemovalResult now carry a `failed` channel, separate
from `notFound`, at all three swallow sites (memory load, memory delete,
profile upsert). Both consumers report it honestly: the exec_action handler
returns success:false with "could not reach your memories … nothing has been
deleted", checked BEFORE the no-match branch, because that branch's wording is
a factual claim about the user's data we are in no position to make. The LLM
tool path gets a `failedToRemove` list and an instruction never to describe
those as absent or removed.

One existing test asserted the old behaviour verbatim — `expect(result.notFound)
.toEqual(['photography'])` on a failed delete. It pinned the bug, so it is
corrected rather than worked around, and says why. Three tool-executor fixtures
predated the new field and are extended.

#563 finding 8.

Mutation-proven: reverting either swallow site fails exactly one of the four new
tests. 72 Cat suites (1025 tests) and type-check green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018waGt1ieA9TjpscqrbrnGb
@github-actions
github-actions Bot merged commit 1fdc48e into main Aug 29, 2026
6 checks passed
@github-actions
github-actions Bot deleted the fix/forget-failure-is-not-no-match branch August 29, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant