Skip to main content

Contributing

Thank you for your interest in contributing to Kore Memory. This guide covers setting up a development environment, running tests, code style, and the pull request process.

Getting Started

Prerequisites

  • Python 3.11+ (3.12 recommended)
  • Git
  • pip or uv (recommended for faster dependency resolution)

Clone and Install

git clone https://github.com/auriti-web-design/kore-memory.git
cd kore-memory

# Install with all extras including dev dependencies
pip install -e ".[semantic,mcp,dev]"

Or with uv (faster):

uv pip install -e ".[semantic,mcp,dev]"

Verify Setup

# Run the test suite
pytest

# Start the server locally
kore

# Check health
curl http://localhost:8765/health

Project Structure

kore-memory/
├── src/
│ └── kore_memory/
│ ├── __init__.py # Package exports
│ ├── server.py # FastAPI application
│ ├── models.py # Pydantic models
│ ├── database.py # SQLite operations
│ ├── decay.py # Ebbinghaus decay engine
│ ├── embeddings.py # Sentence-transformer wrapper
│ ├── importance.py # Auto-importance scorer
│ ├── compression.py # Memory compression
│ ├── security.py # Auth, rate limiting, headers
│ ├── mcp_server.py # MCP protocol server
│ ├── client.py # Sync Python SDK
│ └── async_client.py # Async Python SDK
├── tests/
│ ├── test_server.py # API endpoint tests
│ ├── test_decay.py # Decay engine tests
│ ├── test_embeddings.py # Embedding tests
│ ├── test_importance.py # Importance scorer tests
│ ├── test_compression.py # Compression tests
│ ├── test_security.py # Security tests
│ └── test_client.py # SDK tests
├── pyproject.toml # Package configuration
├── README.md # Project README
└── LICENSE # MIT License

Running Tests

Full Test Suite

pytest

With Coverage Report

pytest --cov=kore_memory --cov-report=html
open htmlcov/index.html

Specific Test File

pytest tests/test_decay.py

Specific Test

pytest tests/test_decay.py::test_ebbinghaus_formula -v

Run Tests in Parallel

pytest -n auto
tip

Tests use an in-memory SQLite database by default. No cleanup is needed between runs.

Code Style

Linting

Kore Memory uses ruff for linting and formatting:

# Check for issues
ruff check .

# Auto-fix issues
ruff check --fix .

# Format code
ruff format .

Type Checking

mypy src/kore_memory

Style Guidelines

  • Type hints everywhere -- All function signatures must have complete type annotations
  • Docstrings -- All public functions and classes must have docstrings (Google style)
  • No Any types -- Use specific types. If you need flexibility, use generics or unions
  • Pydantic models -- All API input/output uses Pydantic v2 models
  • Error messages -- User-facing error messages must be clear and actionable

Example

def calculate_decay(
elapsed_days: float,
half_life_days: float,
) -> float:
"""Calculate memory decay using the Ebbinghaus forgetting curve.

Args:
elapsed_days: Time since last access in days.
half_life_days: Half-life of the memory in days.

Returns:
Decay score between 0.0 and 1.0.

Raises:
ValueError: If half_life_days is not positive.
"""
if half_life_days <= 0:
raise ValueError(f"half_life_days must be positive, got {half_life_days}")
return math.exp(-elapsed_days * math.log(2) / half_life_days)

Writing Tests

Test Structure

Tests follow the Arrange-Act-Assert pattern:

def test_save_memory_with_auto_importance(client):
"""Save a memory and verify auto-importance scoring."""
# Arrange
payload = {
"content": "Always use parameterized SQL queries to prevent injection",
"category": "decision",
}

# Act
response = client.post("/save", json=payload)

# Assert
assert response.status_code == 201
data = response.json()
assert data["importance"] >= 3 # Should be scored high due to "always" + security context
assert data["decay_score"] == 1.0

Test Fixtures

Common fixtures are defined in conftest.py:

import pytest
from fastapi.testclient import TestClient
from kore_memory.server import app

@pytest.fixture
def client():
"""Create a test client with a fresh in-memory database."""
with TestClient(app) as client:
yield client

@pytest.fixture
def saved_memory(client):
"""Save a test memory and return its data."""
response = client.post("/save", json={
"content": "Test memory for fixtures",
"category": "general",
})
return response.json()

What to Test

  • Happy path -- Normal operations work as expected
  • Edge cases -- Minimum/maximum content length, empty tags, zero results
  • Error cases -- Invalid input, missing fields, nonexistent IDs
  • Security -- SQL injection attempts, XSS payloads, auth bypass
  • Decay math -- Verify formula output at known time points

Pull Request Process

1. Create a Branch

git checkout -b feature/your-feature-name

Branch naming conventions:

  • feature/description -- New features
  • fix/description -- Bug fixes
  • docs/description -- Documentation changes
  • refactor/description -- Code refactoring
  • test/description -- Test additions or changes

2. Make Your Changes

  • Write code following the style guidelines above
  • Add or update tests for your changes
  • Run the full test suite and ensure it passes
  • Run linting and type checking

3. Commit

Write clear, descriptive commit messages:

# Good
git commit -m "Add TTL support for auto-expiring memories"
git commit -m "Fix decay calculation when half-life is extended by retrieval"

# Bad
git commit -m "Update code"
git commit -m "Fix bug"

4. Push and Create PR

git push origin feature/your-feature-name

Then create a pull request on GitHub. Your PR description should include:

  • What -- A brief description of the change
  • Why -- The motivation or issue being fixed
  • How -- Key implementation details
  • Testing -- How the change was tested

5. Review Process

  • All PRs require at least one review before merging
  • CI must pass (tests, linting, type checking)
  • Keep PRs focused -- one feature or fix per PR
  • Respond to review feedback promptly
info

For large features, consider opening a draft PR early to get feedback on your approach before investing significant time.

Reporting Issues

Open an issue on GitHub with:

  • Description -- What happened vs. what you expected
  • Reproduction steps -- Minimal steps to reproduce the issue
  • Environment -- Python version, OS, Kore Memory version (kore --version)
  • Logs -- Relevant error messages or stack traces

Development Tips

Quick Iteration Loop

# Terminal 1: Run server with auto-reload
KORE_LOG_LEVEL=debug kore

# Terminal 2: Run specific tests on save
pytest tests/test_server.py -v --tb=short -x

Testing with a Fresh Database

rm -f data/memory.db
kore

Inspecting the Database

sqlite3 data/memory.db ".tables"
sqlite3 data/memory.db "SELECT id, content, importance, decay_score FROM memories LIMIT 10;"

Profiling

python -m cProfile -o profile.out -m kore_memory.server &
# Run your workload, then:
python -c "import pstats; p = pstats.Stats('profile.out'); p.sort_stats('cumulative'); p.print_stats(20)"

License

By contributing to Kore Memory, you agree that your contributions will be licensed under the MIT License.