tests — memory

Module: tests-memory Cohesion: 0.80 Members: 0

tests — memory

The tests/memory module contains unit and integration tests for the core memory components of the Code Buddy agent. These components are crucial for the agent's ability to understand project context, learn coding styles, and retain architectural decisions across sessions.

This documentation covers the functionality of the modules being tested, as inferred from their respective test suites.


1. CodingStyleAnalyzer

The CodingStyleAnalyzer is responsible for detecting and profiling the coding style conventions used within a codebase. This allows the agent to adapt its code generation to match the existing project style, ensuring consistency.

Purpose

To automatically identify common coding style patterns (e.g., quote style, indentation, naming conventions, import styles) from source code content and format this information for use in LLM prompts.

Key Concepts

Core Functionality

analyzeContent(content: string, filename: string): CodingStyleProfile

This is the primary method for analyzing a single file's content. It takes the source code as a string and the filename (which can influence certain detections, e.g., test file patterns) and returns a CodingStyleProfile object.

Example Usage (from tests):

const analyzer = new CodingStyleAnalyzer();
const content = `const name = 'hello';`;
const result = analyzer.analyzeContent(content, 'test.ts');
expect(result.quoteStyle).toBe('single');

The analyzer can detect:

buildPromptSnippet(profile: CodingStyleProfile): string

This method takes a CodingStyleProfile object and formats it into a human-readable string, wrapped in XML tags, suitable for inclusion in an LLM prompt. This allows the agent to be explicitly aware of the project's style guidelines.

Example Output Snippet:

<coding_style>
Project coding conventions (auto-detected):
- Quotes: single quotes
- Semicolons: yes
- Indentation: 2 spaces
- Imports: named imports with .js extensions
- Naming:
  - camelCase for variables
  - PascalCase for classs
- Error handling: try-catch
- Testing: describe/it blocks
</coding_style>

Singleton Management

The CodingStyleAnalyzer is managed as a singleton to ensure consistent state and avoid redundant initialization.

Architecture

graph TD
    A[Source Code Content] --> B{CodingStyleAnalyzer.analyzeContent}
    B --> C[CodingStyleProfile Object]
    C --> D{CodingStyleAnalyzer.buildPromptSnippet}
    D --> E[LLM Prompt Snippet <coding_style>...</coding_style>]

2. DecisionMemory

The DecisionMemory module is designed to capture, store, and recall architectural and design decisions made during the agent's operation. This allows the agent to maintain context and consistency in its choices over time.

Purpose

To enable the AI agent to explicitly record and retrieve significant decisions, their rationale, alternatives, and context, making these decisions available for future reasoning and prompt generation.

Key Concepts

Core Functionality

extractDecisions(input: string): { decisions: Decision[], rawText: string }

This method parses raw text (typically LLM output) to identify and extract structured decision blocks. Decisions are expected to be formatted within XML tags, with sub-tags for choice, alternatives, rationale, context, confidence, and tags. It generates a unique ID and timestamp for each extracted decision.

Example Input (from tests):

<decision>
  <choice>Use PostgreSQL</choice>
  <alternatives>MySQL, SQLite</alternatives>
  <rationale>Better JSON support</rationale>
  <context>Database selection</context>
  <confidence>0.85</confidence>
  <tags>database, backend</tags>
</decision>

persistDecisions(decisions: Decision[]): Promise

Takes an array of Decision objects and stores them in the underlying EnhancedMemory system. Each decision is stored as a memory item with type: 'decision' and relevant tags.

findRelevantDecisions(query: string, limit: number = 5): Promise

Queries the EnhancedMemory for decisions relevant to the given query. It retrieves memory items of type: 'decision' and maps them back into Decision objects.

buildDecisionContext(query: string): Promise

This method combines findRelevantDecisions with formatting. It queries for relevant decisions and, if any are found, formats them into an XML block (...) suitable for inclusion in an LLM prompt. If no relevant decisions are found, it returns null.

Example Output Snippet:

<decisions_context>
  <decision>
    <choice>Use REST</choice>
    <alternatives>GraphQL, gRPC</alternatives>
    <rationale>Simplicity</rationale>
    <context>API design</context>
    <confidence>0.8</confidence>
  </decision>
</decisions_context>

getDecisionPromptEnhancement(): string

Returns a string containing instructions for the LLM on how to format new decisions using the XML structure. This guides the LLM to produce parsable output.

Integration with EnhancedMemory

DecisionMemory relies heavily on EnhancedMemory for its persistence and retrieval capabilities. It acts as an abstraction layer, translating structured Decision objects into generic memory items for storage and vice-versa.

graph TD
    A[LLM Output (Raw Text)] --> B{DecisionMemory.extractDecisions}
    B --> C[Decision Objects]
    C --> D{DecisionMemory.persistDecisions}
    D -- Stores --> E[EnhancedMemory]

    F[User Query] --> G{DecisionMemory.findRelevantDecisions}
    G -- Recalls from --> E
    E --> H[Memory Items]
    H --> I[Decision Objects]
    I --> J{DecisionMemory.buildDecisionContext}
    J --> K[LLM Prompt Context <decisions_context>...</decisions_context>]

Singleton Management

Similar to CodingStyleAnalyzer, DecisionMemory is managed as a singleton.


3. PersistentMemoryManager

The PersistentMemoryManager provides a simple, file-based key-value store for general project and user-specific information. This allows the agent to remember arbitrary facts, configurations, or preferences across different runs.

Purpose

To store and retrieve simple key-value pairs persistently in Markdown files, categorized by scope (project/user) and optionally by category, making this information available to the agent.

Key Concepts

Core Functionality

initialize(): Promise

Ensures that the project_memory.md and user_memory.md files exist at their configured paths. If they don't, it creates them with a basic template structure.

remember(key: string, value: string, options: { scope: 'project' | 'user', category?: string }): Promise

Stores a key-value pair in the specified scope and optional category. If the key already exists, its value is updated. The memory is written to the corresponding Markdown file.

Example:

await manager.remember(&#39;build-cmd&#39;, &#39;npm run build&#39;, { scope: &#39;project&#39;, category: &#39;Project Context&#39; });

recall(key: string): string | null

Retrieves the value associated with a given key from either the project or user memory. Returns null if the key is not found.

forget(key: string, scope: 'project' | 'user'): Promise

Removes a key-value pair from the specified scope. Returns true if the memory was found and deleted, false otherwise.

getRelevantMemories(keyword: string): { key: string, value: string, scope: 'project' | 'user' }[]

Searches through all stored memories (both project and user) and returns an array of memory objects whose key or value contains the specified keyword.

getContextForPrompt(): string

Aggregates all stored memories (project and user) into a single formatted string, wrapped in --- PERSISTENT MEMORY --- delimiters, suitable for inclusion in an LLM prompt. This provides the LLM with a comprehensive overview of known facts.

Example Output Snippet:

--- PERSISTENT MEMORY ---
Project Context:
- framework: React
User Preferences:
- indent: 2 spaces
--- END PERSISTENT MEMORY ---

Architecture

graph TD
    A[PersistentMemoryManager] --> B{initialize}
    B --> C[project_memory.md]
    B --> D[user_memory.md]

    E[remember(key, value, scope, category)] --> A
    A -- Writes to --> C
    A -- Writes to --> D

    F[recall(key)] --> A
    A -- Reads from --> C
    A -- Reads from --> D
    A --> G[Value | null]

    H[getContextForPrompt] --> A
    A -- Reads all from --> C
    A -- Reads all from --> D
    A --> I[Formatted Prompt String]