fix(cognition): whole-word merged in episode classifier (recall quality / distillation fact-yield) - #4245
Merged
rysweet merged 1 commit intoJul 17, 2026
Conversation
…lity / fact-yield)
The episode-ingestion classifier (`memory_consolidation::classifier::classify`)
decides, at every `store_episode` intake site, whether an event is operational
noise (DROP), low-value bookkeeping (DOWN-SCOPE), or a meaningful episodic worth
full-importance storage (STORE). Distillation later mines the STORED,
high-importance episodes into semantic facts, so a misclassification here
propagates straight into recall top-k.
Rule 3's durable-completion signal scored a single token with a raw-substring
`content_lc.contains("merged")`. That fired inside the git-status vocabulary
`unmerged` / `submerged` — which name the OPPOSITE of a completed merge (an
outstanding, un-completed one) — promoting benign/negative bookkeeping to a
durable `ActionCompleted` episode at 0.7 importance. Distillation would then
mine that phantom completion into a phantom "action completed" fact, polluting
recall top-k and dragging recall precision down.
The `merged` signal now matches at WORD BOUNDARIES via a new `contains_word`
helper, aligning this seam with the word-boundary policy already adopted by the
same classifier's failure-signal pass (#4080) and the knowledge-pack relevance
scorer (#4241). `unmerged`/`submerged` down-scope to the operational tier; a
genuine whole-word `merged` still classifies as a durable completion, so no real
completion changes disposition. The multi-word phrases (`opened pr`,
`pull request`) cannot embed in a single word, so they remain substring checks.
Internal surface only — `classify` signature/contract unchanged, no CLI/operator
surface touched. New unit tests pin both the negative (`unmerged`/`submerged`)
and positive (whole-word `merged`) contract; a qa-team gadugi scenario drives
them outside-in.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📊 Coverage Summary
Coverage data from CI run. Test files matching |
rysweet
deleted the
engineer/continuously-research-and-improve-your-own-cogn-70ab8541-1784255034-58f073
branch
July 17, 2026 03:46
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.
Summary
Perpetual-cognition improvement on the recall-quality / distillation-fact-yield axis.
The episode-ingestion classifier (
memory_consolidation::classifier::classify) decides — at everystore_episodeintake site — whether an event is operational noise (DROP), low-value bookkeeping (DOWN-SCOPE), or a meaningful episodic worth full-importance storage (STORE). Distillation later mines the STORED, high-importance episodes into semantic facts, so a misclassification here propagates straight into recall top-k.The defect
Rule 3's durable-completion signal scored a single token with a raw substring
content_lc.contains("merged"). That fired inside the git-status vocabularyunmerged/submerged— which name the opposite of a completed merge (an outstanding, un-completed one) — promoting benign/negative bookkeeping to a durableActionCompletedepisode at 0.7 importance. Distillation would then mine that phantom completion into a phantom "action completed" fact, polluting recall top-k and dragging recall precision down.The fix
mergednow matches at word boundaries via a newcontains_wordhelper, aligning this seam with the word-boundary policy already adopted by the same classifier's failure-signal pass (#4080) and the knowledge-pack relevance scorer (#4241).unmerged/submergeddown-scope to the operational tier; a genuine whole-wordmergedstill classifies as a durable completion, so no real completion changes disposition. The multi-word phrases (opened pr,pull request) cannot embed in a single word, so they intentionally remain substring checks.Merge-ready evidence
Criterion 1 — qa-team scenarios (validated + run):
tests/gadugi/episode-classifier-whole-word-completion.yamldrives the contract over the real classifier (headline assertsunmerged_paths_are_not_a_durable_completion ... ok,whole_word_merged_is_still_a_durable_completion ... ok, and the unchangedmeaningful_completed_action_is_stored, plustest result: ok+ exit 0).gadugi-testbinary is not installed in this engineering environment, sogadugi-test validate/runcould not be executed here. The scenario was validated structurally (YAML parses; schema-parity with the siblingdistill-fact-yield-informative-content.yaml) and its underlying commandcargo test --locked --lib memory_consolidation::classifierpasses (20 passed; 0 failed).Criterion 2 — docs / changed-surface justification: No user-facing surface changed.
classifysignature/contract is unchanged; this refines a private helper and one internal branch only. No CLI/operator/README surface touched → internal-only, no doc update required.Criterion 3 — quality-audit (SEEK→VALIDATE→FIX): 3 cycles. Cycle 1: found the
unmerged/submergedsubstring false-positive → addedcontains_word+ tests. Cycle 2: verified no other single-token durable-completion signal has the same class (multi-word phrases are embed-safe;handoffhas no embedding words and would regresshandoffsunder exact-match, so left as substring;recipeonly routes within the failure branch). Cycle 3: caught + fixed a doc-comment inaccuracy (importance band 0.9→0.7). Final cycle clean: zero critical/high; zero medium correctness/security findings.Criterion 4 — CI green (local gates mirror CI):
cargo fmt --all -- --check✅ (pre-commit + pre-push)cargo clippy --release --no-deps -- -D warnings✅ (pre-commit)cargo clippy --all-targets --all-features --locked -- -D warnings✅ (pre-push)cognitive_memory bootstrap memory_ipc memory_consolidation✅ (pre-push)cargo test --locked --lib memory_consolidation→ 148 passed; 0 failed.Criterion 6 — focused diff: 3 files (
classifier.rsproduction,classifier_tests.rstests, one new gadugi scenario). No unrelated edits.Tests added
unmerged_paths_are_not_a_durable_completion—unmerged/submergeddo NOT store asActionCompleted; down-scope to the operational tier.whole_word_merged_is_still_a_durable_completion— a genuine whole-wordmergedstill classifies asActionCompleted(no regression of the real signal).Standing perpetual goal — durable code improvement, not a snapshot doc.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com