You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Soul.note() shipped in #233 (Phase 1) and the soul remember deprecation work landed in #236 (Phase 2). One acceptance criterion from #231 is still open: contradiction detection on the dedup path.
The runtime method accepts a detect_contradictions: bool | None = None parameter (defaults to True for semantic, False for the other tiers), but the implementation at src/soul_protocol/runtime/soul.py:1497-1498 is a TODO:
# TODO: wire ContradictionDetector — see issue #231 follow-up._=detect_contradictions# currently unused; reserved for follow-up.
A working ContradictionDetector already exists at src/soul_protocol/runtime/memory/contradiction.py:123 and is wired into MemoryManager.observe() (the cognitive pipeline). The remaining work is to expose it on the note() path.
Scope
When note() runs the dedup pipeline and the action is CREATE (the content is novel, not a SKIP/MERGE), pass the new entry through the existing ContradictionDetector.
Respect the detect_contradictions parameter. The default (True for semantic, False elsewhere) stays.
Return the supersede in the result dict so callers can branch on it. Suggested shape: extend the existing return with "contradicted_id": str | None alongside the existing action / id / existing_id / similarity fields.
Acceptance
A semantic note() call that contradicts an existing fact returns {"action": "CREATE", "contradicted_id": "<old>", ...} and the old fact carries superseded_by
The same call with detect_contradictions=False skips the check and returns contradicted_id: None
Procedural / social tiers default-off behaviour preserved
New tests cover: clean CREATE (no contradiction), CREATE with contradiction → supersede, opt-out via detect_contradictions=False, the existing SKIP/MERGE paths unchanged
CHANGELOG entry under ## [Unreleased] / ### Memory update primitives
Out of scope
Refactoring ContradictionDetector itself. Whatever shape it has in MemoryManager.observe() is what note() should reuse.
New CLI flags. The existing --no-contradictions flag on soul note already maps cleanly to detect_contradictions=False (currently plumbed but a no-op).
Notes for mentees
Phase 1 of #231 left # TODO: wire ContradictionDetector as an explicit marker in the runtime, and the corresponding --no-contradictions CLI flag was plumbed without a backing implementation. Both will start working once this lands. Touches: runtime/soul.py (the TODO), the existing ContradictionDetector usage in manager.py (for the call shape), cli/main.py (verify the flag now actually has an effect), tests in tests/test_cli/ and tests/test_memory/ for the dedup-with-contradiction paths.
Tracking: closes the final acceptance item from #231.
Background
Soul.note()shipped in #233 (Phase 1) and thesoul rememberdeprecation work landed in #236 (Phase 2). One acceptance criterion from #231 is still open: contradiction detection on the dedup path.The runtime method accepts a
detect_contradictions: bool | None = Noneparameter (defaults to True for semantic, False for the other tiers), but the implementation at src/soul_protocol/runtime/soul.py:1497-1498 is a TODO:A working
ContradictionDetectoralready exists at src/soul_protocol/runtime/memory/contradiction.py:123 and is wired intoMemoryManager.observe()(the cognitive pipeline). The remaining work is to expose it on thenote()path.Scope
note()runs the dedup pipeline and the action isCREATE(the content is novel, not a SKIP/MERGE), pass the new entry through the existingContradictionDetector.old.superseded_by = new.id, mirrornew.supersedes = old.id, recordprediction_errorper the Memory updates: brain-aligned primitive set (supersede + confirm + update + weight-decay forget) #192 memory-update primitives).detect_contradictionsparameter. The default (True for semantic, False elsewhere) stays."contradicted_id": str | Nonealongside the existingaction / id / existing_id / similarityfields.Acceptance
note()call that contradicts an existing fact returns{"action": "CREATE", "contradicted_id": "<old>", ...}and the old fact carriessuperseded_bydetect_contradictions=Falseskips the check and returnscontradicted_id: Nonedetect_contradictions=False, the existing SKIP/MERGE paths unchanged## [Unreleased] / ### Memory update primitivesOut of scope
ContradictionDetectoritself. Whatever shape it has inMemoryManager.observe()is whatnote()should reuse.--no-contradictionsflag onsoul notealready maps cleanly todetect_contradictions=False(currently plumbed but a no-op).Notes for mentees
Phase 1 of #231 left
# TODO: wire ContradictionDetectoras an explicit marker in the runtime, and the corresponding--no-contradictionsCLI flag was plumbed without a backing implementation. Both will start working once this lands. Touches:runtime/soul.py(the TODO), the existingContradictionDetectorusage inmanager.py(for the call shape),cli/main.py(verify the flag now actually has an effect), tests intests/test_cli/andtests/test_memory/for the dedup-with-contradiction paths.Tracking: closes the final acceptance item from #231.