Skip to content

fix(cognition): word-boundary relevance gate on fact recall (recall precision + fact-yield) - #4309

Merged
rysweet merged 1 commit into
mainfrom
engineer/continuously-research-and-improve-your-own-cogn-70ab8541-1784337090-73f124
Jul 18, 2026
Merged

fix(cognition): word-boundary relevance gate on fact recall (recall precision + fact-yield)#4309
rysweet merged 1 commit into
mainfrom
engineer/continuously-research-and-improve-your-own-cogn-70ab8541-1784337090-73f124

Conversation

@rysweet

@rysweet rysweet commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

LibraryCognitiveMemory::search_facts — the fact-recall seam the OODA turn/context path (base_type_turn::prepare_turn_context) and every natural-language fact caller reach — delegated matching to the upstream library, which matches each query token as a raw case-insensitive SUBSTRING of a fact's concept OR content. A clean natural-language token therefore floated facts in on the interior/suffix of an unrelated word, polluting the capped working-context recall the OODA cycle feeds to reasoning and dragging fact recall precision — and effective distillation fact-yield — down.

This is the same defect the episodic recall gate already removed (recall_episodes_ranked / search_episodes_by_keywords, PR #4241 lineage). Fact recall was never gated. This PR applies the analogous marker-safe word-boundary gate to the FACT path, reusing the existing shares_word_prefix helper.

Empirical bug evidence (live in-memory backend)

For a fact whose content is "the reactor overheated":

query raw-substring match genuinely relevant
reactor yes (whole word) ✅ yes
react yes (prefix) ✅ yes
deploy yes → deployed ✅ yes (inflection)
act yes → reactor no (interior)
own yes → download no (interior)
test yes → latest no (suffix)

Fix

search_facts partitions the query into two token shapes (mirroring search_episodes_by_keywords) and post-filters the backend's results:

  • CLEAN token (all-alphanumeric): kept only when it is a prefix of a whole word in the concept OR content (word-boundary), dropping interior/suffix noise while preserving inflectional recall (deploy → "deployed").
  • RAW token (any non-alphanumeric char — a hyphenated concept like bug-pattern, or a journal: / goal-edge: / sub: marker): keeps the library's exact contiguous-substring semantics its callers store and re-filter on. A query with no clean token bypasses the gate, so the many concept/marker callers are provably unaffected.

Both fields are checked (the library matches both). Truncation to limit is deferred until after the gate (backend queried unbounded on the clean path) so a relevant fact ranked behind a false positive is not dropped before the gate runs — mirroring recall_episodes_ranked. Wildcard/empty queries keep the return-all path. The gate only ever removes false positives — it never adds a fact the backend did not return and never reorders.

Verified empirically that the library treats a hyphenated token as a contiguous substring (goal-node matched only "a goal-node payload", not "goal … node"), matching the raw-token check exactly — so mixed clean+marker queries do not regress. Caller safety: concept/marker callers pass colon/hyphen queries (raw → gate bypassed) or recall under the identical concept a fact was stored under (self word-boundary match → always kept); journal enumeration keeps working (clean journal word-boundary-matches the journal:YYYY-MM-DD concept).

Merge-ready evidence

(1) qa-team scenariotests/gadugi/fact-recall-word-boundary-precision.yaml (mirrors distill-concept-canonicalization.yaml; YAML-validated). Drives:

  • cargo test --locked --lib tests_fact_recall_word_boundary (end-to-end, live in-memory backend)
  • cargo test --locked --lib fact_query_gate_tests (pure gate helpers)
  • cargo test --locked --lib tests_whole_word_episode_recall (episodic-gate regression guard)

New tests (12): 6 unit (library_adapter::fact_query_gate_tests) + 6 integration (cognitive_memory::tests_fact_recall_word_boundary) covering interior/suffix drop, word-boundary + inflectional preservation, concept-field match, marker/concept substring preservation, deferred-truncation limit honouring, and wildcard/empty bypass.

(2) Docsdocs/reference/cognitive-memory-fact-recall.md (new "Word-boundary relevance gate" section) and docs/architecture/cognitive-memory-library-adapter.md (fact-path gate subsection + in-adapter table row); both last_updated bumped.

(3) Quality-audit — ≥3 SEEK→VALIDATE→FIX cycles, ending clean:

  • Edge cases: usize::MAX to the library is safe (established adapter pattern for episodic recall + empirically verified no capacity pre-alloc); limit=0 degenerate-but-correct; " * " behavior unchanged vs. prior code.
  • Library-matching consistency: whitespace-token OR semantics and contiguous-hyphen-substring behavior both empirically confirmed to match the gate → no mixed-query regression.
  • Caller safety: enumerated all search_facts callers; marker/concept/self-identical recalls provably preserved; full suite green confirms none regressed.

(4) CI-equivalent gates (local):

  • cargo fmt --all --check — clean
  • cargo clippy --all-targets --all-features --locked -- -D warnings — clean
  • cargo clippy --release --no-deps -- -D warnings (pre-commit) — clean
  • Full lib suite: 8823 passed, 0 failed, 7 ignored
  • Pre-push release gate (cognitive_memory/bootstrap/memory_ipc/memory_consolidation subset + full clippy): 455 passed, 0 failed; all push-stage gates passed

(6) Focused diff — 6 files (1 source, 1 test module + wiring, 2 docs, 1 qa scenario); +648/−3; no unrelated edits.

Scope

One durable, self-contained improvement toward the standing perpetual cognition goal (recall quality + distillation fact-yield). Supersedes/replaces the earlier redundant #4307 (whose concept-canonicalization change had already landed independently in #4246); this branch was reset onto latest main and targets a distinct, still-open gap on the fact read path.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…recision + fact-yield)

`LibraryCognitiveMemory::search_facts` — the fact-recall seam the OODA
turn/context path (`base_type_turn::prepare_turn_context`) and every
natural-language fact caller reach — delegated matching to the upstream library,
which matches each query token as a RAW case-insensitive SUBSTRING of a fact's
concept OR content. A clean natural-language token therefore floated facts in on
the INTERIOR/SUFFIX of an unrelated word.

Empirically (live in-memory backend), for content "the reactor overheated":

  * search_facts("act")  -> matched "re(act)or" and "artif(act)"  [interior]
  * search_facts("own")  -> matched "d(own)load"                  [interior]
  * search_facts("test") -> matched "la(test)"                    [suffix]

while whole-word ("reactor"), prefix ("react"), and inflectional ("deploy" ->
"deployed") matches were legitimate. Those off-topic facts crowd the CAPPED
working-context recall the OODA cycle feeds to reasoning, dragging fact recall
precision — and effective distillation fact-yield — down. This is the same
defect the EPISODIC recall gate already removed (`recall_episodes_ranked` /
`search_episodes_by_keywords`, PR #4241 lineage); fact recall was never gated.

Fix: apply the analogous marker-safe word-boundary gate to the FACT path,
reusing the existing `shares_word_prefix` helper and mirroring
`search_episodes_by_keywords`'s clean/raw partition:

  * a CLEAN query token (all-alphanumeric) is kept only when it is a prefix of a
    whole word in the concept OR content (word-boundary), dropping interior/suffix
    noise while preserving inflectional recall;
  * a RAW token (any non-alphanumeric char — a hyphenated concept like
    "bug-pattern", or a "journal:"/"goal-edge:"/"sub:" marker) keeps the library's
    exact contiguous-substring semantics its callers store and re-filter on; a
    query with NO clean token bypasses the gate entirely, so the many
    concept/marker callers are provably unaffected.

Both concept AND content are checked (the library matches both). Truncation to
`limit` is deferred until AFTER the gate so a relevant fact ranked behind an
interior-substring false positive is not dropped before the gate runs (mirroring
`recall_episodes_ranked`). Wildcard/empty queries keep the return-all path.

The gate only ever REMOVES interior/suffix false positives — it never adds a
fact the backend did not return and never reorders. Verified empirically that
the library treats a hyphenated token as a contiguous substring (matching the
raw-token check exactly), so mixed clean+marker queries do not regress.

Tests:
  * library_adapter::fact_query_gate_tests — pure helpers (partition_fact_query,
    fact_shares_query_relevance): clean/raw partition, interior-vs-word-boundary,
    inflection, concept-field match, marker substring, mixed query.
  * cognitive_memory::tests_fact_recall_word_boundary — end-to-end over the live
    in-memory backend: interior/suffix dropped, word-boundary + inflectional
    preserved, concept-field match, marker/concept substring preserved, deferred
    truncation honours limit, wildcard/empty bypass.

qa-team: tests/gadugi/fact-recall-word-boundary-precision.yaml drives the
end-to-end + unit tests plus an episodic-gate regression guard.

Docs: docs/reference/cognitive-memory-fact-recall.md (new "Word-boundary
relevance gate" section) and docs/architecture/cognitive-memory-library-adapter.md
(fact-path gate subsection + in-adapter table row).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

📊 Coverage Summary

Generated by cargo llvm-cov --workspace --summary-only (nightly, excluding test files)

Module Lines Covered Coverage
Total 184494 154225 83.6%

Coverage data from CI run. Test files matching tests?/ are excluded from line counts.

@rysweet
rysweet merged commit d074378 into main Jul 18, 2026
18 checks passed
@rysweet
rysweet deleted the engineer/continuously-research-and-improve-your-own-cogn-70ab8541-1784337090-73f124 branch July 18, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant