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
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
Anytypes -- 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 featuresfix/description-- Bug fixesdocs/description-- Documentation changesrefactor/description-- Code refactoringtest/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
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.