fix(memory): never resolve an unsourced value conflict at ~explicit - #1832
Open
Chuckos wants to merge 1 commit into
Open
fix(memory): never resolve an unsourced value conflict at ~explicit#1832Chuckos wants to merge 1 commit into
Chuckos wants to merge 1 commit into
Conversation
The memory reviewer is instructed to SUPERSEDE on contradiction: when a new fact contradicts an existing entry, drop the old one. That is right when the principal has just stated the new fact. It is wrong when two stale entries merely disagree and the reviewer picks a winner -- the pick is a guess, and it is written with an ~explicit tag, which every later read treats as "the principal stated this". Observed in the wild: a memory file held three incompatible answers to one question (which days a recurring activity happens). A curation write collapsed them by choosing one. The choice was wrong, it was recorded at full confidence, and the correct answer had never been asked for. The same shape had previously produced a fabricated identity fact that survived several review cycles. Two halves: - MemoryReviewer: supersede only on evidence from the conversation. A disagreement nothing in the session can settle must be kept, tagged ~inferred, and surfaced for confirmation rather than silently decided. - MemoryWriter: detectValueConflicts(), a pure deterministic check over closed, enumerable vocabularies -- weekday names, HH:MM clock values, and number+unit quantities, where each unit is its own class. It fires only when the PRIOR state already held two or more distinct values for a topic AND a disagreeing sibling was evicted, i.e. the reviewer actually resolved an ambiguity. Ordinary supersession (one prior value, a new value stated) is untouched. A topic requires two shared content words, since one common token links entries that are plainly about different things. Enforcement is proportionate: a detected conflict downgrades the entry's provenance to ~inferred and records the conflict in the write log. It does not reject the write, which would freeze curation on a heuristic. Detection is deliberately narrow. It never asks a model whether two statements conflict -- that judgement is the defect being removed. Conflicts outside those vocabularies go undetected by design. Measured by replaying a real 186 -> 45 curation: 4 flags, 2 true (including the motivating regression and a genuine review-day conflict that had gone unnoticed), 2 false. The false-positive shape is recorded as a test rather than wished away. The rule is tuned to over-flag: a false positive costs one provenance downgrade that the next explicit statement restores, while a false negative leaves a guess reading as principal-stated indefinitely. Tests: 8 cases covering the regression, ordinary supersession, cross-unit non-comparison, and the known false positive.
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.
Problem
The memory reviewer resolves conflicting factual values by picking a winner and stamping it
~explicit— as if the principal had stated it. When memory already holds ≥2 distinct values for the same topic (a weekday, a time, a quantity) and the reviewer keeps one while evicting a disagreeing sibling, that's the reviewer guessing, not recording something the principal said — yet the guess carries the highest-confidence marker.This is a confabulation defect: a gap filled by inference, then marked as fact. Consumers that trust
~explicit(and any metric derived from a conflicted value, e.g. a session count) are silently corrupted until someone notices.Fix
Add a deterministic
detectValueConflicts()inMemoryWriter.ts, run in-lock duringsetEntries:HH:MM,number+unit. Anything outside is left alone by design; a broader rule would have to infer, which is the very defect.~inferred(text preserved). Curation keeps flowing; authority does not.Two false-positive guards: unit-scoped comparison (7h is not a rival of 150g), and a two-shared-word topic match (so a single shared token doesn't link two entries that are plainly about different things).
Tests
Adds
MemoryWriter.conflict.test.ts— 8 cases: the real regression plus false-positive guards (unit scoping, two-word anchor, ordinary supersession, no-closed-vocab, unchanged entries).