feat(plugins): optional yantrik_memory — semantic memory + supersession (opt-in) - #16
Open
spranab wants to merge 3 commits into
Open
feat(plugins): optional yantrik_memory — semantic memory + supersession (opt-in)#16spranab wants to merge 3 commits into
spranab wants to merge 3 commits into
Conversation
…on (opt-in) Ports the plugin from code_puppy#465, which was closed because plugins now live in this repository. No behaviour change from the reviewed version; only the packaging moves. code_puppy/plugins/yantrik_memory/ -> code_puppy_core_plugins/yantrik_memory/ plugin-local test_integration.py -> tests/test_yantrik_memory.py registered in pyproject entry-points and plugin-names.txt Opt-in and fail-soft: the yantrikdb import is guarded, so the plugin is inert rather than fatal when the dependency is absent — matching the convention aws_bedrock already uses for boto3. Verified on this repo: ruff clean; tests/test_yantrik_memory.py passes; the remaining 235 tests pass. tests/test_aws_bedrock.py has one Windows file-locking failure that reproduces on a clean main checkout and is unrelated to this change.
Supersession was silently broken. yantrikdb's correct() gained a required
`reason` parameter, so every call raised TypeError, and the recorder's
fallback caught it and inserted the new fact as a DUPLICATE — leaving the
superseded value in the current band. From the outside that looks exactly like
working memory, which is why it survived unnoticed.
Verified against yantrikdb 0.15.3 / yantrikdb-mcp 0.19.2: 3/3 runs now show
the new value present and the superseded one absent, and the chatter probe
drops from 2 durable facts to 1 because the correction replaces rather than
appends.
Two things that hid it, both fixed here:
* the pytest entrypoint returned PASS when yantrikdb was absent, so CI (which
does not install it) would have reported green forever. It now SKIPs, and
that is what surfaced the failure.
* the correct() fallback swallowed the exception silently. It still keeps the
fact rather than losing it, but now says why it fired.
The skip check also has to import through _bootstrap_imports(): config.py
resolves DB_PATH at import time, so touching substrate any earlier binds the
developer's real store and the test accumulates facts across runs.
…e's trust signals
Three defects a live two-turn session made obvious.
DUPLICATES. Two writers reach the store — the passive distiller and the
agent's own yantrik_remember tool — and only the distiller de-duplicated. A
single "remember X" turn fired both, so the same fact landed twice in
different phrasings ("Deploy key for node4 is X" / "Node4 deploy key is X").
think() notices the redundancy but its trigger is ADVISORY: the originals stay
`active` with `consolidated_into` unset, so there is nothing to filter on
afterwards. Fixed at both ends — the tool checks before writing, and prefs()
collapses restatements when building the band. Measured on the same two turns:
4 stored facts -> 1.
TRUST SIGNALS. The engine returns superseded_by, disputed_with,
current_status and why_retrieved on every hit; the recall block forwarded only
`text`, so an agent could not tell a disputed or superseded fact from a good
one. Now surfaced as a short parenthetical, keeping only the warning entries
in why_retrieved rather than the routine "semantically similar" reasons.
Verified live, not just in tests: two separate code-puppy processes against
engine 0.15.3 with qwen3.8:27b as agent and distiller. Turn two recalls the
fact in a fresh process, and the current band is a single clean entry.
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.
Re-homed from mpfaffenberger/code_puppy#465, which was closed because plugins moved here. Thanks for the pointer — the port turned up three real bugs, so this is not a straight copy.
What it is
An opt-in plugin giving Code Puppy durable memory across sessions, backed by YantrikDB. A local distiller reads each user turn and extracts durable facts, so the user never hand-tags anything; a later turn that contradicts an earlier fact supersedes it rather than piling up. Default OFF, enabled with
/yantrik enable.Purely additive: new package, new test, two registration lines. No existing code changes.
Conventions followed
code_puppy_core_plugins/yantrik_memory/tests/test_yantrik_memory.pypyproject.tomlentry-points andplugin-names.txtyantrikdbimport is guarded, matching howaws_bedrocktreatsboto3— absent dependency makes the plugin inert, never fatalThree bugs the port exposed
The test could not fail. Its pytest entrypoint returned PASS when
yantrikdbwas absent. CI here does not install it, so this would have been green forever. It nowSKIPs — and that is what surfaced the next two.Supersession was broken.
YantrikDB.correct()gained a requiredreasonparameter, so every call raisedTypeError; the fallback caught it and inserted a duplicate, leaving the stale value in the current band. From outside that is indistinguishable from working memory.Facts were written twice. The passive distiller and the agent's
yantrik_remembertool both wrote, and only the distiller de-duplicated. One "remember X" turn stored the same fact in two phrasings. Fixed at both ends; measured 4 stored facts → 1 for the same two turns.Also now forwards the engine's per-hit trust signals (
superseded_by,disputed_with,current_status, staleness inwhy_retrieved) into the recall block, so the agent can tell a disputed fact from a good one.Verification
Live, not just unit-tested: two separate
code-puppy -pprocesses against engine 0.15.3, withqwen3.8:27bas both agent and distiller. Turn one states a fact; turn two, in a fresh process, recalls it and grounds it correctly. Current band ends as a single clean entry.ruffcleantests/test_yantrik_memory.pypasses 3/3 with the engine present, SKIPs without itmaincheckout (Windows file-locking inaws_bedrock,steer_queue,web_retriever_skill), unrelated to this changeKnown limitations
think()flags redundancy as an advisory trigger without applying it, so de-duplication is handled in the plugin rather than relying on a maintenance pass.