Empty the corpus once, and keep everyone signed in - #216
Merged
Conversation
Production held eight thoughts, all written here to prove a path worked, plus the alerts they raised against each other and an introduction whose own thought had already been deleted. The first person to arrive cannot tell a test from a stranger, and would have been introduced to one. `RESONANCE_PURGE_CORPUS=report|1` removes every thought, every standing-search alert, every introduction, every conversation and every shared topic — and leaves accounts, sign-ins and OAuth client registrations alone. That distinction is the whole point: `reset` also wipes both, so it would sign everyone out and make every connected MCP client re-authorize to achieve the same empty corpus. It takes no exceptions, and refuses RESONANCE_PURGE_KEEP rather than ignoring it, because removing named thoughts is already RESONANCE_PURGE_SESSIONS. Two defects found on the way, both of which left rows behind: `RESONANCE_PURGE_SESSIONS` never retracted standing-search alerts, because it calls the corpus service directly and so bypasses the product's retract. Now it retracts both sides — an alert is a pointer to a pair of thoughts, and `retract_for_session` only ever reached the owner's half, leaving the counterpart's copy naming a deleted thought until whenever they next looked. `reset()` and `import_payload()` cleared intros, channels and messages and forgot all eight workspace tables, so a "reset" store still held every shared topic. Both now name one list, CONNECTION_TABLES. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
What this changes
Production holds eight thoughts, all of them written here to prove a path worked, plus the alerts they raised against each other and an accepted introduction whose own thought had already been deleted. The first person to arrive cannot tell a test from a stranger, and would have been introduced to one.
RESONANCE_PURGE_CORPUS=report|1— one-shot, same shape as the two purges already in the runbook — removes every thought, every standing-search alert, every introduction, every conversation and every shared topic, and leaves accounts, sign-ins and OAuth client registrations alone. That distinction is the whole point:python3 -m src.persistence … resetalso wipes both, so reaching the same empty corpus through it would sign everyone out and make every connected MCP client re-authorize.It takes no exceptions, and refuses
RESONANCE_PURGE_KEEPrather than ignoring it — an operator who sets it expects something to survive, and removing named thoughts is alreadyRESONANCE_PURGE_SESSIONS.Two defects found on the way, both leaving rows behind
RESONANCE_PURGE_SESSIONSnever retracted standing-search alerts. It callslive.delete_sessiondirectly and so bypasses the product's_retract. Worse,retract_for_sessiononly ever reached the owner's half of a pair: the alert recorded for the person on the other end kept naming a deleted thought until whenever they next looked. It now retracts both sides. This is what produced the ghost found in production — an accepted intro whosefrom_session_idno longer exists.reset()andimport_payload()forgot eight tables. Both cleared intros/channels/messages and left everyworkspace*table standing, so a "reset" store still held every shared topic. Both now name one list,CONNECTION_TABLES.Evidence
Ran 711 tests … OK (skipped=1)against PostgreSQL 16 (RESONANCE_TEST_POSTGRES_URL). Six of those are new, intests/test_purge_corpus.py, covering: the variable being unset or unrecognised does nothing;reportcounts without moving anything;1empties sessions/alerts/intros/channels/messages while accounts and an OAuth client registration survive and the index stays current; a second run finds nothing left to do;KEEPis refused; andPURGE_SESSIONSretracts the counterpart's alert. One alert in the applied-case test is deliberately owned by an account that is not inusers— that is what an alert looks like after its owner is revoked, and walking live accounts would never reach it, which is why the store gaineddelete_grants_of_kind.Engine untouched — no scoring, alignment, extraction or index change — so the policy version does not move and the gates are unaffected.
Checklist
benchmark/gold is unedited.ROADMAP.mdcorrected: it opened on "Seven shared thoughts exist in the world" and now says none do, with why.🤖 Generated with Claude Code