Skip to content

feat(visibility): surface insights + semantic facts in mem::context and smart-search#591

Closed
kmariunas wants to merge 1 commit into
rohitg00:mainfrom
kmariunas:feat/insights-semantic-context-search
Closed

feat(visibility): surface insights + semantic facts in mem::context and smart-search#591
kmariunas wants to merge 1 commit into
rohitg00:mainfrom
kmariunas:feat/insights-semantic-context-search

Conversation

@kmariunas
Copy link
Copy Markdown

@kmariunas kmariunas commented May 21, 2026

Closes #590. Same pattern as #458 + #473, applied to KV.insights and KV.semantic.

smart-search: new includeInsights (default true), parallel mem::insight-search, returns insights field — direct mirror of the lesson piggyback in #473.

mem::context: reads KV.insights + KV.semantic in parallel with existing reads.

  • Insights filtered identically to lessons (!deleted && (!project || project === current)), ranked (matching ? 1.5 : 1) × confidence, top 10, ## Distilled Insights block.
  • Semantic project membership derived from sourceSessionIds via the already-fetched allSessions map. Cross-project facts surface as global; sources entirely in other projects are excluded. Ranked strength × confidence × boost, top 10, ## Architectural Facts block.

+18 tests (smart-search +6, new test/context-insights-semantic.test.ts +12). All pass. No existing test broken.

…nd smart-search (rohitg00#590)

Closes rohitg00#590. Same trust-shock pattern fixed for lessons in rohitg00#458 + rohitg00#473:
KV.insights and KV.semantic are produced by consolidate-pipeline/reflect
but had no agent-facing surface in v0.9.21.

## smart-search (mirrors rohitg00#473)

- New `includeInsights` param (default true)
- Delegates to existing `mem::insight-search` via `sdk.trigger` — no
  duplicate scoring logic, future tweaks auto-propagate
- Insights come back in a separate `insights` field, not merged into
  `results`. Existing consumers reading `result.results` / `result.lessons`
  are unaffected
- Content truncated to 240 chars for compact preview (same convention
  as lessons)
- Best-effort: catches + warns on failure, falls back to empty list

## mem::context (mirrors rohitg00#458)

- Reads `KV.insights` and `KV.semantic` in parallel with existing
  slots/profile/lessons reads
- **Insights** filtered identically to lessons (`!deleted && (!project ||
  project === current)`), ranked `(matching ? 1.5 : 1) × confidence`,
  capped at top 10, rendered as `## Distilled Insights` block
- **Semantic facts** have no direct `project` field; membership derived
  from `sourceSessionIds` via the already-fetched `allSessions` map.
  Filter logic: include when any source session matches the current
  project OR when the fact has no resolvable source sessions
  (cross-project knowledge / global). Excludes facts whose sources are
  entirely in other projects. Ranks `strength × confidence ×
  project-relevance-boost`, capped at top 10, rendered as
  `## Architectural Facts` block
- Block recency tracks `lastReinforcedAt || updatedAt` so hot entries
  survive when budget tightens (same pattern as the lessons block)

## Tests

- `test/smart-search.test.ts` — 6 new cases under `insight inclusion (rohitg00#590)`
  mirroring the lesson inclusion suite: payload shape, content
  truncation, `includeInsights:false` opt-out, project forwarding, error
  tolerance, non-success response tolerance
- `test/context-insights-semantic.test.ts` — 12 new cases split across
  two `describe` blocks: insight block injection (presence, absence,
  project ranking, cross-project isolation, deleted, top-10 cap,
  confidence rendering) + semantic block injection (project-source
  inclusion, global inclusion, cross-project exclusion, project-boost
  ranking, top-10 cap)

Empirical motivation: on a local stack with consolidation working,
109 semantic facts + 58 insights accumulated over a day's sessions,
but none were retrievable by an agent during a session — only via
direct REST calls. The patch closes that loop.

Signed-off-by: Karolis Mariunas <kmariunass@gmail.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

@kmariunas is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

The PR adds insights and semantic memories to mem::context and mem::smart-search. A new CompactInsightResult type defines the shape. Context loads both sources in parallel, filters and ranks by project relevance and score/confidence, caps each to 10, and injects them as memory blocks. Smart-search recalls insights in parallel with observations and lessons, truncates content for preview, and includes results conditionally in the compact response.

Changes

Insights and Semantic Facts Integration

Layer / File(s) Summary
Type contract for compact insight results
src/types.ts
Adds CompactInsightResult interface with insightId, title, content, confidence, score, createdAt, optional project, and tags fields.
Context insights and semantic facts injection
src/functions/context.ts
Extends KV loading to fetch insights and semantic memories in parallel; filters, ranks (by project relevance and confidence/strength), and caps insights to 10 for a Distilled Insights block; similarly processes semantic facts into an Architectural Facts block with tokens, recency, and source IDs.
Smart search insight recall implementation
src/functions/smart-search.ts
Adds includeInsights input flag and insights response field; implements recallInsights helper that calls mem::insight-search, maps results into CompactInsightResult, truncates content, and handles errors gracefully; executes insight recall in parallel with observation search and lesson recall.
Comprehensive test suite for context and smart search
test/context-insights-semantic.test.ts, test/smart-search.test.ts
Adds Vitest suites validating context injection of Distilled Insights and Architectural Facts (project scoping, ranking, confidence/score caps, exclusion rules), and smart-search insight inclusion in compact mode (field mapping, truncation, conditional omission, error resilience).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #590: This PR implements the exact changes requested—adding KV insights and semantic memory handling to context, introducing smart-search insight recall, and defining the new type contract and test coverage.

Poem

🐰 Insights now flow through memory's halls,
Semantic facts dance in parallel calls,
Project-scoped wisdom, ranked and refined,
A rabbit has woven the context you'll find!
Context and search, now speaking as one,
The insights have arrived—the feature is done! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: surfacing insights and semantic facts in two key functions (mem::context and smart-search), which aligns with the core objective of exposing KV.insights and KV.semantic to agent-facing surfaces.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/smart-search.test.ts (1)

36-52: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align test/smart-search.test.ts SDK mocking with vi.mock("iii-sdk").

test/smart-search.test.ts defines a local mockSdk() shim (function mockSdk() { ... }) and assigns sdk = mockSdk();, but it never uses the mandated vi.mock("iii-sdk") approach. Update the test to mock iii-sdk via vi.mock("iii-sdk"), providing a mock sdk.trigger and kv.get/set/list instead of the custom shim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/smart-search.test.ts` around lines 36 - 52, Replace the local shim
mockSdk() and any direct assignment sdk = mockSdk() with a vi.mock("iii-sdk")
call that returns the mocked module shape used in tests: export an sdk object
with trigger (async function) and a kv namespace implementing get, set, and
list; ensure the mocked trigger behavior matches the previous mockSdk.trigger
contract and that tests import/require the module so they use the vi.mock
implementation rather than the local mockSdk function; update references to
registerFunction/registerTrigger if present to instead drive behavior via the
mocked sdk.trigger and kv.get/set/list implementations.
🧹 Nitpick comments (2)
src/functions/context.ts (1)

142-147: ⚡ Quick win

Remove WHAT-level explanatory comments and rely on naming.

Line 142-147 and Line 244-250 add narrative behavior comments. In src/ this should be expressed through naming/extraction instead of explanatory WHAT-comments.

As per coding guidelines, src/**/*.{ts,tsx}: Avoid code comments explaining WHAT — use clear naming instead.

Also applies to: 244-250

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/functions/context.ts` around lines 142 - 147, Remove the WHAT-level
narrative comments around the insights logic (the block mentioning "Insights —
mirrors the lessons round-trip closure" and the similar comment at the later
block) and encode the behavior in names or small extracted helpers instead;
e.g., rename the variable/constant or wrap the logic in a clearly named function
like computeProjectScopedInsights or rankAndCapInsights (references:
mem::reflect, memory_insight_list, and the insights-ranking logic) so the code
reads self-descriptively without explanatory WHAT-comments.
src/functions/smart-search.ts (1)

90-95: ⚡ Quick win

Drop WHAT-level inline commentary in src/ code.

Line 90-95 explains behavior rather than encoding intent in code structure/naming.

As per coding guidelines, src/**/*.{ts,tsx}: Avoid code comments explaining WHAT — use clear naming instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/functions/smart-search.ts` around lines 90 - 95, The inline comment
describing WHAT the block does should be removed and its intent encoded in code:
extract the parallel side-channel work into a clearly named helper like
runBestEffortSideChannelLookups (or runSideChannelLookupsInParallel) that
invokes hybridSearch, lessonRecall, and insightSearch, returns empty fallbacks
on errors, and documents only WHY if needed; replace the comment with that
function call so the code's name and return shape communicate the behavior
instead of the inline WHAT-level commentary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/functions/smart-search.ts`:
- Around line 33-34: Validate includeInsights and includeLessons immediately at
the handler boundary by checking their types explicitly (e.g., const
insightsEnabled = typeof includeInsights === 'boolean' ? includeInsights : false
and const lessonsEnabled = typeof includeLessons === 'boolean' ? includeLessons
: false) and use insightsEnabled / lessonsEnabled for all subsequent branching
instead of trusting the raw params; update the handler parameter processing and
any branches that currently read includeInsights or includeLessons so only a
literal boolean true enables the feature.

In `@test/context-insights-semantic.test.ts`:
- Around line 33-43: The test currently fabricates an SDK object and force-casts
it to import("iii-sdk").ISdk in wireContext; instead, call vi.mock("iii-sdk") at
top of the test file and use the mocked SDK to set up registerFunction and
trigger behaviours, then pass that mocked SDK into registerContextFunction
(instead of the casted object). Specifically: remove the "as unknown as
import('iii-sdk').ISdk" cast and the handcrafted sdk object, replace with the
vi.mock'd module’s mock (set registerFunction = vi.fn(...) to capture the
ContextHandler like you do now, and add a mock implementation for sdk.trigger),
ensure the mockKV provides get/set/list and is passed in unchanged, then call
registerContextFunction(sdkMock, kv, budget) and use the captured handler; this
follows the repo guideline and enables proper testing of sdk.trigger and kv
interactions.

---

Outside diff comments:
In `@test/smart-search.test.ts`:
- Around line 36-52: Replace the local shim mockSdk() and any direct assignment
sdk = mockSdk() with a vi.mock("iii-sdk") call that returns the mocked module
shape used in tests: export an sdk object with trigger (async function) and a kv
namespace implementing get, set, and list; ensure the mocked trigger behavior
matches the previous mockSdk.trigger contract and that tests import/require the
module so they use the vi.mock implementation rather than the local mockSdk
function; update references to registerFunction/registerTrigger if present to
instead drive behavior via the mocked sdk.trigger and kv.get/set/list
implementations.

---

Nitpick comments:
In `@src/functions/context.ts`:
- Around line 142-147: Remove the WHAT-level narrative comments around the
insights logic (the block mentioning "Insights — mirrors the lessons round-trip
closure" and the similar comment at the later block) and encode the behavior in
names or small extracted helpers instead; e.g., rename the variable/constant or
wrap the logic in a clearly named function like computeProjectScopedInsights or
rankAndCapInsights (references: mem::reflect, memory_insight_list, and the
insights-ranking logic) so the code reads self-descriptively without explanatory
WHAT-comments.

In `@src/functions/smart-search.ts`:
- Around line 90-95: The inline comment describing WHAT the block does should be
removed and its intent encoded in code: extract the parallel side-channel work
into a clearly named helper like runBestEffortSideChannelLookups (or
runSideChannelLookupsInParallel) that invokes hybridSearch, lessonRecall, and
insightSearch, returns empty fallbacks on errors, and documents only WHY if
needed; replace the comment with that function call so the code's name and
return shape communicate the behavior instead of the inline WHAT-level
commentary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5f3ae1e3-a17c-4a2e-aa74-ef7b775ebbd9

📥 Commits

Reviewing files that changed from the base of the PR and between bc64107 and b5c163f.

📒 Files selected for processing (5)
  • src/functions/context.ts
  • src/functions/smart-search.ts
  • src/types.ts
  • test/context-insights-semantic.test.ts
  • test/smart-search.test.ts

Comment on lines +33 to 34
includeInsights?: boolean;
}) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate includeInsights as a boolean at the handler boundary.

Line 88 treats every value except literal false as enabled (e.g., "false" or 0 still enables insights). Add an explicit type guard for includeInsights (and ideally includeLessons) before branching.

As per coding guidelines, src/**/*.{ts,tsx}: Perform input validation at system boundaries (MCP handlers and REST endpoints).

Also applies to: 87-89

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/functions/smart-search.ts` around lines 33 - 34, Validate includeInsights
and includeLessons immediately at the handler boundary by checking their types
explicitly (e.g., const insightsEnabled = typeof includeInsights === 'boolean' ?
includeInsights : false and const lessonsEnabled = typeof includeLessons ===
'boolean' ? includeLessons : false) and use insightsEnabled / lessonsEnabled for
all subsequent branching instead of trusting the raw params; update the handler
parameter processing and any branches that currently read includeInsights or
includeLessons so only a literal boolean true enables the feature.

Comment on lines +33 to +43
function wireContext(kv: ReturnType<typeof mockKV>, budget = 4000) {
let handler: ContextHandler | undefined;
const sdk = {
registerFunction: vi.fn((id: string, cb: ContextHandler) => {
if (id === "mem::context") handler = cb;
}),
} as unknown as import("iii-sdk").ISdk;
registerContextFunction(sdk, kv as never, budget);
if (!handler) throw new Error("mem::context not registered");
return handler;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify required iii-sdk mock pattern in changed tests
rg -n --type=ts 'vi\.mock\("iii-sdk"\)' test/context-insights-semantic.test.ts test/smart-search.test.ts
rg -n --type=ts 'as unknown as import\("iii-sdk"\)\.ISdk|function mockSdk\(' test/context-insights-semantic.test.ts test/smart-search.test.ts

Repository: rohitg00/agentmemory

Length of output: 198


Use vi.mock("iii-sdk") in test/context-insights-semantic.test.ts (avoid ISdk casting).

test/context-insights-semantic.test.ts casts a handcrafted object to import("iii-sdk").ISdk (as unknown as import("iii-sdk").ISdk at line 39), and it doesn’t use the required vi.mock("iii-sdk") test mocking pattern for sdk.trigger / kv.get/set/list. Refactor the test to mock iii-sdk via vi.mock("iii-sdk") like the repo’s guideline expects.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/context-insights-semantic.test.ts` around lines 33 - 43, The test
currently fabricates an SDK object and force-casts it to import("iii-sdk").ISdk
in wireContext; instead, call vi.mock("iii-sdk") at top of the test file and use
the mocked SDK to set up registerFunction and trigger behaviours, then pass that
mocked SDK into registerContextFunction (instead of the casted object).
Specifically: remove the "as unknown as import('iii-sdk').ISdk" cast and the
handcrafted sdk object, replace with the vi.mock'd module’s mock (set
registerFunction = vi.fn(...) to capture the ContextHandler like you do now, and
add a mock implementation for sdk.trigger), ensure the mockKV provides
get/set/list and is passed in unchanged, then call
registerContextFunction(sdkMock, kv, budget) and use the captured handler; this
follows the repo guideline and enables proper testing of sdk.trigger and kv
interactions.

@kmariunas kmariunas closed this May 22, 2026
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.

mem::context and smart-search skip KV.insights and KV.semantic

1 participant