Thank you for your interest in contributing to RMAgent! This guide will help you get started.
- Code of Conduct
- Getting Started
- Development Setup
- Development Workflow
- Coding Standards
- Testing Guidelines
- Documentation
- Pull Request Process
- Issue Reporting
We pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
Positive behavior:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Unacceptable behavior:
- Harassment, trolling, or discriminatory comments
- Publishing others' private information
- Other conduct which could reasonably be considered inappropriate
- Python 3.11 or higher
- uv (recommended) or pip
- Git
- Text editor or IDE
- RootsMagic 11 database for testing
-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/rmagent.git cd rmagent -
Add upstream remote:
git remote add upstream https://github.com/miams/rmagent.git
-
Verify remotes:
git remote -v # origin https://github.com/YOUR_USERNAME/rmagent.git (fetch) # origin https://github.com/YOUR_USERNAME/rmagent.git (push) # upstream https://github.com/miams/rmagent.git (fetch) # upstream https://github.com/miams/rmagent.git (push)
# With uv (recommended)
uv sync --extra dev
# With pip
pip install -e ".[dev]"This installs:
- Core dependencies
- Testing tools (pytest, pytest-cov, pytest-mock)
- Code quality tools (black, ruff, mypy)
# Copy example configuration
cp config/.env.example config/.env
# Edit with your settings
nano config/.envFor development, you can use Ollama (free, local) or get test API keys.
# Run tests
uv run pytest
# Check code formatting
uv run black --check .
# Check linting
uv run ruff check .
# Type checking
uv run mypy rmagent/# Update main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/your-feature-nameBranch naming conventions:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changestest/- Test improvementsrefactor/- Code refactoring
- Write code following Coding Standards
- Add tests for new functionality
- Update documentation as needed
- Commit frequently with clear messages
Follow Conventional Commits:
git add .
git commit -m "feat: add support for custom timeline phases"
git commit -m "fix: resolve database connection timeout"
git commit -m "docs: update installation instructions"
git commit -m "test: add integration tests for export command"Commit types:
feat: New featurefix: Bug fixdocs: Documentation onlytest: Adding or updating testsrefactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementstyle: Code style changes (formatting, missing semi-colons, etc.)chore: Changes to build process or auxiliary tools
# Fetch upstream changes
git fetch upstream
# Rebase on upstream/main
git rebase upstream/main
# Resolve conflicts if any
# Then push to your fork
git push origin feature/your-feature-name# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=rmagent --cov-report=html
# Format code
uv run black .
# Check linting
uv run ruff check .
# Type checking
uv run mypy rmagent/All checks must pass before submitting PR.
See Pull Request Process below.
We follow PEP 8 with these tools:
- black - Code formatting (line length: 100)
- ruff - Fast Python linter
- mypy - Static type checking
# Format all code
uv run black .
# Check formatting without changes
uv run black --check .Black configuration (pyproject.toml):
[tool.black]
line-length = 100
target-version = ["py311"]# Check for linting issues
uv run ruff check .
# Auto-fix issues
uv run ruff check --fix .- Use type hints for all function signatures
- Use type hints for complex variables
- Run mypy before committing
# Good
def get_person(person_id: int) -> Person | None:
"""Get person by ID."""
return db.query_one("SELECT * FROM PersonTable WHERE PersonID = ?", (person_id,))
# Bad (no type hints)
def get_person(person_id):
return db.query_one("SELECT * FROM PersonTable WHERE PersonID = ?", (person_id,))Use Google-style docstrings:
def generate_biography(
person_id: int,
length: BiographyLength = BiographyLength.STANDARD,
citation_style: CitationStyle = CitationStyle.FOOTNOTE,
) -> Biography:
"""Generate biographical narrative for a person.
Args:
person_id: PersonID from RootsMagic database
length: Biography length (short, standard, comprehensive)
citation_style: Citation format (footnote, parenthetical, narrative)
Returns:
Biography object with text, sources, and metadata
Raises:
PersonNotFoundError: If person_id doesn't exist
DatabaseError: If database query fails
"""
passOrder imports as:
- Standard library
- Third-party packages
- Local imports
# Standard library
import json
import logging
from pathlib import Path
from typing import Any
# Third-party
from pydantic import BaseModel
import click
# Local
from rmagent.rmlib.database import RMDatabase
from rmagent.rmlib.queries import QueryService
from rmagent.agent.llm_provider import get_provider# Use specific exceptions
try:
person = db.query_one("SELECT * FROM PersonTable WHERE PersonID = ?", (person_id,))
except sqlite3.OperationalError as e:
logger.error(f"Database query failed: {e}")
raise DatabaseError(f"Failed to query person {person_id}") from e
# Provide helpful error messages
if person is None:
raise PersonNotFoundError(
f"Person with ID {person_id} not found in database. "
f"Use 'rmagent search --name' to find PersonIDs."
)See TESTING.md for complete testing documentation.
- All new features must have tests
- Bug fixes must include regression tests
- Maintain 80%+ code coverage on new code
- All tests must pass before PR is merged
# Run all tests
uv run pytest
# Run specific test file
uv run pytest tests/unit/test_database.py
# Run with coverage
uv run pytest --cov=rmagent --cov-report=html
# Run integration tests (requires API keys)
uv run pytest tests/integration/ -m ""import pytest
from rmagent.rmlib.database import RMDatabase
def test_database_connection():
"""Test database connects successfully."""
with RMDatabase("data/Iiams.rmtree") as db:
result = db.query_value("SELECT COUNT(*) FROM PersonTable")
assert result > 0
def test_person_not_found():
"""Test PersonNotFoundError is raised."""
with pytest.raises(PersonNotFoundError):
query_service.get_person_with_primary_name(99999999)- Update README.md if adding major features
- Update USAGE.md if adding CLI commands or options
- Update CONFIGURATION.md if adding config options
- Add docstrings to all public functions and classes
- Update CHANGELOG.md with your changes
README.md- Project overview and quick startINSTALL.md- Installation instructionsUSAGE.md- CLI command referenceCONFIGURATION.md- Configuration guideFAQ.md- Common questionsEXAMPLES.md- Real-world usage examplesCHANGELOG.md- Version history
class BiographyGenerator:
"""Generate biographical narratives from RootsMagic data.
The BiographyGenerator extracts person information from a RootsMagic
database and generates structured biographical narratives using
either template-based or AI-powered approaches.
Attributes:
db_path: Path to RootsMagic database file
agent: Optional GenealogyAgent for AI generation
respect_private: Honor IsPrivate flags in database
Example:
>>> generator = BiographyGenerator(db_path="data/family.rmtree")
>>> bio = generator.generate(person_id=1, length=BiographyLength.STANDARD)
>>> print(bio.render_markdown())
"""
pass-
✅ All tests pass:
uv run pytest
-
✅ Code is formatted:
uv run black . -
✅ No linting errors:
uv run ruff check . -
✅ Type checking passes:
uv run mypy rmagent/
-
✅ Documentation updated
-
✅ CHANGELOG.md updated
-
Push your branch:
git push origin feature/your-feature-name
-
Open PR on GitHub
-
Fill out PR template:
- Description of changes
- Related issue numbers (#123)
- Testing performed
- Breaking changes (if any)
## Description
Brief description of what this PR does.
## Related Issues
Fixes #123
Closes #456
## Type of Change
- [ ] Bug fix (non-breaking change fixing an issue)
- [ ] New feature (non-breaking change adding functionality)
- [ ] Breaking change (fix or feature causing existing functionality to change)
- [ ] Documentation update
## Testing Performed
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed
- [ ] All tests passing
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review performed
- [ ] Documentation updated
- [ ] CHANGELOG.md updated
- [ ] Tests added for new functionality- Automated checks run (tests, linting, type checking)
- Maintainer reviews code
- Feedback addressed (if any)
- PR approved and merged
-
Delete your feature branch:
git branch -d feature/your-feature-name git push origin --delete feature/your-feature-name
-
Update your main:
git checkout main git pull upstream main
- Search existing issues - Your issue may already be reported
- Check FAQ.md - Common issues are documented there
- Try latest version - Issue may be fixed in recent release
Use the bug report template:
**Describe the bug**
A clear description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Run command '...'
2. See error
**Expected behavior**
What you expected to happen.
**Environment**
- RMAgent version: [e.g., 0.2.0]
- Python version: [e.g., 3.11.5]
- OS: [e.g., macOS 14.0, Ubuntu 22.04]
- LLM provider: [e.g., Anthropic Claude]
**Error message**Full error message here
**Additional context**
Any other relevant information.
Use the feature request template:
**Is your feature request related to a problem?**
A clear description of the problem.
**Describe the solution you'd like**
What you want to happen.
**Describe alternatives you've considered**
Other approaches you've thought about.
**Additional context**
Any other relevant information.rmagent/
├── rmagent/ # Main package
│ ├── rmlib/ # Core library (database, parsers, queries)
│ ├── agent/ # AI agent (LLM providers, prompts)
│ ├── generators/ # Output generators
│ ├── cli/ # Command-line interface
│ └── config/ # Configuration
├── tests/ # Test suite
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
├── docs/ # Documentation
└── data_reference/ # Schema documentation
- rmlib/ - No dependencies on other rmagent modules (core library)
- agent/ - Depends on rmlib
- generators/ - Depends on rmlib and agent
- cli/ - Depends on all other modules
- Start with tests (TDD approach)
- Implement core functionality in rmlib/
- Add AI integration in agent/ (if needed)
- Add generator in generators/ (if creating output)
- Add CLI command in cli/ (if user-facing)
- Update documentation
- Documentation: Check README.md, INSTALL.md, USAGE.md, FAQ.md
- Issues: https://github.com/miams/rmagent/issues
- Discussions: https://github.com/miams/rmagent/discussions
Thank you for contributing to RMAgent! 🎉