Skip to content

feat: add loadWithQuery to MemoryContextLoader (GIT-100)#66

Merged
TonyCasey merged 2 commits intomainfrom
git-100
Feb 15, 2026
Merged

feat: add loadWithQuery to MemoryContextLoader (GIT-100)#66
TonyCasey merged 2 commits intomainfrom
git-100

Conversation

@TonyCasey
Copy link
Copy Markdown
Owner

@TonyCasey TonyCasey commented Feb 15, 2026

Summary

  • Add loadWithQuery method to IMemoryContextLoader interface
  • Implement using MemoryService.recall() to search both git notes AND commit trailers
  • Add optional IMemoryService dependency to MemoryContextLoader

This enables intent-based memory retrieval that searches all memory sources (notes + trailers) using extracted keywords from user prompts.

Changes

  • src/domain/interfaces/IMemoryContextLoader.ts - Added loadWithQuery method signature
  • src/application/services/MemoryContextLoader.ts - Implemented loadWithQuery

Test plan

  • Type check passes
  • Lint passes
  • Unit tests pass (438 tests)

Note: Requires GIT-97 to be merged first (depends on config changes).

Closes GIT-100

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added query-based search for memories, with optional result limits and directory filtering.
  • Tests

    • Added comprehensive test coverage for the new search feature and fallback behavior.

Copilot AI review requested due to automatic review settings February 15, 2026 00:32
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 15, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

The pull request adds a new loadWithQuery method to MemoryContextLoader that enables query-based memory search via MemoryService.recall, with fallback to existing load behavior if MemoryService is unavailable. The constructor is extended to accept an optional IMemoryService dependency, and corresponding interface and test definitions are added.

Changes

Cohort / File(s) Summary
Interface Definition
src/domain/interfaces/IMemoryContextLoader.ts
Added loadWithQuery method signature supporting query-based filtering of memories with optional limit and working directory parameters.
Service Implementation
src/application/services/MemoryContextLoader.ts
Extended constructor to accept optional IMemoryService dependency; implemented loadWithQuery method that delegates to MemoryService.recall with fallback to existing load behavior; added debug logging and total count computation.
Test Suite
tests/unit/application/services/MemoryContextLoader.test.ts
Added comprehensive test suite for loadWithQuery covering MemoryService-backed recall, fallback behavior, limit application, cwd propagation, and repository total verification.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant MemoryContextLoader
    participant MemoryService
    participant MemoryRepository

    Client->>MemoryContextLoader: loadWithQuery(query, limit, cwd)
    
    alt MemoryService Available
        MemoryContextLoader->>MemoryRepository: query({ cwd })
        MemoryRepository-->>MemoryContextLoader: total count
        MemoryContextLoader->>MemoryService: recall(query, { limit, cwd })
        MemoryService-->>MemoryContextLoader: memories[]
        MemoryContextLoader->>MemoryContextLoader: log debug
        MemoryContextLoader-->>Client: { memories, total, filtered }
    else MemoryService Unavailable
        MemoryContextLoader->>MemoryContextLoader: log warning
        MemoryContextLoader->>MemoryContextLoader: load(cwd)
        MemoryContextLoader-->>Client: { memories, total, filtered }
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #40: Extends MemoryService.recall to include AI-* trailers and merged recall behavior, which directly supports the new loadWithQuery method's delegation pattern.
  • PR #38: Modified MemoryService.recall to include trailer-based recall and merging logic that loadWithQuery now depends on.
  • PR #66: Adds the same MemoryContextLoader.loadWithQuery method and IMemoryService constructor parameter, representing a direct duplicate or related implementation.
🚥 Pre-merge checks | ✅ 3 | ❌ 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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change—adding a new loadWithQuery method to MemoryContextLoader—which is the core feature added across multiple files in this changeset.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch git-100

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

Copy link
Copy Markdown

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
tests/unit/hooks/utils/config.test.ts (1)

86-103: 🧹 Nitpick | 🔵 Trivial

Consider verifying the new promptSubmit fields in the merge test.

The merge test verifies that recordPrompts defaults are preserved, but doesn't explicitly check that the new fields (extractIntent, intentTimeout, minWords, memoryLimit) are preserved when the config only sets enabled: true. This would strengthen test coverage for the merge behavior.

💡 Suggested additions
       assert.equal(config.hooks.promptSubmit.enabled, true);
       // Defaults preserved for unset fields
       assert.equal(config.hooks.promptSubmit.recordPrompts, false);
+      assert.equal(config.hooks.promptSubmit.extractIntent, true);
+      assert.equal(config.hooks.promptSubmit.intentTimeout, 3000);
+      assert.equal(config.hooks.promptSubmit.minWords, 5);
+      assert.equal(config.hooks.promptSubmit.memoryLimit, 20);
       assert.equal(config.hooks.sessionStop.enabled, true);
🤖 Fix all issues with AI agents
In `@src/domain/interfaces/IMemoryContextLoader.ts`:
- Around line 33-43: Change the loadWithQuery method to accept an options object
for consistency with load(): add a new ILoadWithQueryOptions type (readonly
query: string; readonly limit?: number; readonly cwd?: string) and update the
IMemoryContextLoader.loadWithQuery signature to loadWithQuery(options:
ILoadWithQueryOptions): IMemoryContextResult; then update any callers of
IMemoryContextLoader.loadWithQuery to pass an options object instead of
positional args and export the new options interface if needed.

Comment on lines +33 to +43

/**
* Load memories filtered by a search query.
* Searches both git notes and commit trailers for matching memories.
*
* @param query - Search keywords (e.g., "authentication, GIT-95, LoginHandler")
* @param limit - Maximum memories to return
* @param cwd - Working directory for git operations
* @returns Matching memories from both notes and trailers
*/
loadWithQuery(query: string, limit?: number, cwd?: string): IMemoryContextResult;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using an options object for API consistency.

The existing load() method uses an options object pattern, but loadWithQuery() uses positional parameters. For consistency and future extensibility (e.g., adding since, tags filters to query-based searches), consider using an options object:

interface ILoadWithQueryOptions {
  readonly query: string;
  readonly limit?: number;
  readonly cwd?: string;
}
loadWithQuery(options: ILoadWithQueryOptions): IMemoryContextResult;

This is a minor API design consideration—the current approach works and is acceptable if you prefer the simpler signature.

🤖 Prompt for AI Agents
In `@src/domain/interfaces/IMemoryContextLoader.ts` around lines 33 - 43, Change
the loadWithQuery method to accept an options object for consistency with
load(): add a new ILoadWithQueryOptions type (readonly query: string; readonly
limit?: number; readonly cwd?: string) and update the
IMemoryContextLoader.loadWithQuery signature to loadWithQuery(options:
ILoadWithQueryOptions): IMemoryContextResult; then update any callers of
IMemoryContextLoader.loadWithQuery to pass an options object instead of
positional args and export the new options interface if needed.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds query-based memory context loading to support intent-driven recall across both git notes and commit trailers, and extends prompt-submit hook configuration defaults to accommodate intent extraction.

Changes:

  • Added loadWithQuery() to IMemoryContextLoader and implemented it in MemoryContextLoader using MemoryService.recall().
  • Expanded promptSubmit hook configuration schema + defaults (enabled by default; intent-extraction related fields).
  • Introduced IIntentExtractor interface for extracting searchable keywords from prompts.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/unit/hooks/utils/config.test.ts Updates config default expectations for prompt-submit (now enabled + new fields).
src/hooks/utils/config.ts Expands default promptSubmit config (including enabling it by default).
src/domain/interfaces/IMemoryContextLoader.ts Adds loadWithQuery() API to support query-based context retrieval.
src/domain/interfaces/IIntentExtractor.ts Adds intent-extraction interface types for prompt keyword extraction.
src/domain/interfaces/IHookConfig.ts Extends IPromptSubmitConfig with intent-extraction fields and updates docs.
src/application/services/MemoryContextLoader.ts Implements loadWithQuery() and adds optional IMemoryService dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// Use MemoryService.recall() to search both notes and trailers
if (!this.memoryService) {
this.logger?.warn('MemoryService not available for query search, falling back to repository');
return this.load({ limit, cwd });
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

In the MemoryService-not-available fallback, loadWithQuery ignores the provided query and returns the same result as load(). This breaks the contract of a query-filtered load; consider falling back to memoryRepository.query({ query, limit, cwd }) (notes-only) so at least notes are filtered correctly, and keep the total/filtered semantics consistent.

Suggested change
return this.load({ limit, cwd });
// Get total count (no filters) for stats
const allResult = this.memoryRepository.query({ cwd });
const total = allResult.total;
// Fallback: query repository notes only
const result = this.memoryRepository.query({
query,
limit,
cwd,
});
this.logger?.debug('Memories loaded with query (repository fallback)', {
query,
total,
matched: result.memories.length,
limit,
});
return {
memories: result.memories,
total,
filtered: result.memories.length,
};

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +62
// Get total count for stats
const allResult = this.memoryRepository.query({ cwd });
const total = allResult.total;
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

total is computed via memoryRepository.query({ cwd }), which only counts notes-backed memories. Since loadWithQuery returns results from notes + commit trailers, total will undercount when trailer-only memories exist. Consider deriving the unfiltered total from memoryService (e.g., a recall with no query) or otherwise counting both sources so IMemoryContextResult.total remains “total memories in store”.

Suggested change
// Get total count for stats
const allResult = this.memoryRepository.query({ cwd });
const total = allResult.total;
// Get total count for stats across notes and trailers
const totalResult = this.memoryService.recall('', { cwd });
const total = totalResult.total;

Copilot uses AI. Check for mistakes.
Comment thread src/hooks/utils/config.ts
sessionStop: { enabled: true, autoExtract: true, threshold: 3 },
promptSubmit: { enabled: false, recordPrompts: false, surfaceContext: true },
promptSubmit: {
enabled: true,
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Changing the default hooks.promptSubmit.enabled from false to true is a significant behavioral change (prompt-submit hook will run by default when no config file exists). This also appears inconsistent with the config scaffold in src/commands/init-hooks.ts (still emits promptSubmit.enabled: false). Consider keeping the default disabled until the feature is fully wired, or update the init-hooks defaults so generated configs match runtime defaults.

Suggested change
enabled: true,
enabled: false,

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +38
/** Whether to surface context memories per prompt. */
readonly surfaceContext: boolean;
/** Enable LLM-based intent extraction for smarter memory retrieval. */
readonly extractIntent: boolean;
/** Timeout in ms for intent extraction LLM call. Default: 3000. */
readonly intentTimeout: number;
/** Minimum word count to trigger intent extraction. Default: 5. */
readonly minWords: number;
/** Maximum memories to return. Default: 20. */
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

surfaceContext and the newly added intent-extraction fields are documented as active configuration, but they are not currently read by PromptSubmitHandler (it always calls memoryContextLoader.load({ cwd })). To avoid misleading users, mark these as “Reserved — not yet wired to handler” (as done for other unused config fields) or wire them into the prompt-submit flow in this PR.

Suggested change
/** Whether to surface context memories per prompt. */
readonly surfaceContext: boolean;
/** Enable LLM-based intent extraction for smarter memory retrieval. */
readonly extractIntent: boolean;
/** Timeout in ms for intent extraction LLM call. Default: 3000. */
readonly intentTimeout: number;
/** Minimum word count to trigger intent extraction. Default: 5. */
readonly minWords: number;
/** Maximum memories to return. Default: 20. */
/** Whether to surface context memories per prompt. Reserved — not yet wired to handler. */
readonly surfaceContext: boolean;
/** Enable LLM-based intent extraction for smarter memory retrieval. Reserved — not yet wired to handler. */
readonly extractIntent: boolean;
/** Timeout in ms for intent extraction LLM call. Default: 3000. Reserved — not yet wired to handler. */
readonly intentTimeout: number;
/** Minimum word count to trigger intent extraction. Default: 5. Reserved — not yet wired to handler. */
readonly minWords: number;
/** Maximum memories to return. Default: 20. Reserved — not yet wired to handler. */

Copilot uses AI. Check for mistakes.
readonly surfaceContext: boolean;
/** Enable LLM-based intent extraction for smarter memory retrieval. */
readonly extractIntent: boolean;
/** Timeout in ms for intent extraction LLM call. Default: 3000. */
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

The hook runner enforces a hard 10s timeout (setupShutdown(10_000)), and other LLM timeouts (e.g., enrichTimeout) explicitly document the “Must be under hook timeout (10s)” constraint. intentTimeout should document the same constraint (and ideally be validated/clamped) to prevent configurations that can never succeed within the hook’s hard timeout.

Suggested change
/** Timeout in ms for intent extraction LLM call. Default: 3000. */
/** Timeout in ms for intent extraction LLM call. Default: 3000. Must be under hook timeout (10s). */

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +57
loadWithQuery(query: string, limit?: number, cwd?: string): IMemoryContextResult {
// Use MemoryService.recall() to search both notes and trailers
if (!this.memoryService) {
this.logger?.warn('MemoryService not available for query search, falling back to repository');
return this.load({ limit, cwd });
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

loadWithQuery adds a new code path (MemoryService present vs fallback) and new stats semantics, but there are no unit tests covering it. Since this service already has unit tests for load(), add focused tests for loadWithQuery to lock in notes+trailers behavior and the fallback behavior.

Copilot uses AI. Check for mistakes.
@TonyCasey
Copy link
Copy Markdown
Owner Author

Addressed review feedback:

  1. Options object pattern - Acknowledged as a valid design consideration. Keeping positional params for now since the signature is simple; can refactor if more params are added later.

  2. loadWithQuery fallback - The fallback to load() is intentional: when MemoryService is not available, we can't do text search. The repository-only path provides all memories (bounded by limit) rather than filtered results. Added warning log so this is visible.

  3. Total count semantics - total represents notes-backed memories from the repository. Acknowledged that trailer-only memories may undercount. Keeping current behavior as a known limitation.

  4. enabled: true default - The init-hooks template was updated in GIT-91 to write enabled: true for promptSubmit, so defaults now match.

  5. Reserved annotations - Already addressed in GIT-97 (this PR series depends on that base).

  6. Hook timeout constraint - Already addressed in GIT-97.

  7. Unit tests - ✅ Added 5 new tests for loadWithQuery: search with MemoryService, fallback behavior, limit application, cwd passing, and stats accuracy.

TonyCasey and others added 2 commits February 15, 2026 01:11
- Add loadWithQuery method to IMemoryContextLoader interface
- Implement loadWithQuery using MemoryService.recall() to search
  both git notes and commit trailers
- Add optional IMemoryService dependency to MemoryContextLoader

This enables intent-based memory retrieval that searches all memory
sources (notes + trailers) using extracted keywords.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AI-Agent: Claude-Code/2.1.42
AI-Model: claude-opus-4-5-20251101
AI-Decision: add loadWithQuery to MemoryContextLoader (GIT-100). - Add loadWithQuery method to IMemoryContextLoader interface
AI-Confidence: medium
AI-Tags: application, services, domain
AI-Lifecycle: project
AI-Memory-Id: eff3542e
AI-Source: heuristic
Address review feedback: add focused tests for loadWithQuery to verify
notes+trailers search behavior and fallback behavior when MemoryService
is not available.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AI-Agent: Claude-Code/2.1.42
AI-Model: claude-opus-4-5-20251101
AI-Fact: add unit tests for loadWithQuery method. Address review feedback: add focused tests for loadWithQuery to verify
AI-Confidence: low
AI-Tags: tests, unit, application, services
AI-Lifecycle: project
AI-Memory-Id: 1354ee7a
AI-Source: heuristic
Copilot AI review requested due to automatic review settings February 15, 2026 01:11
@TonyCasey TonyCasey merged commit 4d03199 into main Feb 15, 2026
1 check passed
@TonyCasey TonyCasey deleted the git-100 branch February 15, 2026 01:11
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants