---
title: "Contributing"
description: "Guidelines for contributing to TraceRTM development"
---

# Contributing to TraceRTM

Thank you for your interest in contributing to TraceRTM! This guide covers everything you need to know to make successful contributions to the project.

## Getting Started

### Prerequisites

Before contributing, ensure you have:

1. **Development environment** set up ([Setup Guide](/docs/development/setup))
2. **Git** configured with your name and email
3. **GitHub account** for pull requests
4. Read and understood the [Code of Conduct](https://github.com/tracertm/tracertm/blob/main/CODE_OF_CONDUCT.md)

### First-Time Contributors

New to TraceRTM? Here's how to get started:

1. **Find a good first issue**: Look for issues labeled [`good first issue`](https://github.com/tracertm/tracertm/labels/good%20first%20issue)
2. **Ask questions**: Comment on the issue to ask for guidance
3. **Start small**: Your first PR doesn't have to be big
4. **Get feedback early**: Open a draft PR if you're unsure about your approach

## Contribution Workflow

### 1. Fork and Clone

```bash
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/tracertm.git
cd tracertm

# Add upstream remote
git remote add upstream https://github.com/tracertm/tracertm.git
```

### 2. Create a Branch

```bash
# Sync with upstream
git fetch upstream
git checkout main
git merge upstream/main

# Create a feature branch
git checkout -b feature/your-feature-name
# Or for bug fixes
git checkout -b fix/bug-description
```

**Branch naming conventions:**

| Prefix | Use Case | Example |
|--------|----------|---------|
| `feature/` | New features | `feature/export-csv` |
| `fix/` | Bug fixes | `fix/sync-race-condition` |
| `docs/` | Documentation | `docs/api-examples` |
| `refactor/` | Code refactoring | `refactor/service-layer` |
| `test/` | Test additions | `test/item-service-coverage` |

### 3. Make Your Changes

```bash
# Make changes, then run quality checks
poe quality

# Run tests
poe test

# Commit your changes
git add .
git commit -m "feat(scope): description of change"
```

### 4. Push and Create PR

```bash
# Push your branch
git push origin feature/your-feature-name

# Create a Pull Request on GitHub
# - Fill out the PR template
# - Link related issues
# - Request reviews
```

## Code Standards

### Python Code Style

We use **Ruff** for formatting and linting, configured in `pyproject.toml`:

```bash
# Format code
poe format

# Check for issues
poe lint

# Auto-fix issues
ruff check --fix src/ tests/
```

**Key style points:**

```python
# Good: Type hints on all functions
async def get_item(session: AsyncSession, item_id: str) -> Item | None:
    ...

# Good: Docstrings on public functions
async def create_item(
    session: AsyncSession,
    project_id: str,
    data: ItemCreate,
) -> Item:
    """Create a new item in the specified project.

    Args:
        session: Database session
        project_id: ID of the parent project
        data: Item creation data

    Returns:
        The created item

    Raises:
        NotFoundError: If project doesn't exist
        ValidationError: If data is invalid
    """
    ...

# Good: Use dataclasses/Pydantic for data structures
@dataclass
class CoverageResult:
    total: int
    covered: int
    percentage: float

# Good: Async context managers for resources
async with get_session() as session:
    item = await item_repo.get(session, item_id)
```

### TypeScript/React Code Style

We use **Biome** for formatting and linting:

```bash
cd frontend/apps/web

# Format and lint
npm run lint:fix

# Type check
npm run typecheck
```

**Key style points:**

```typescript
// Good: Type all props and state
interface ItemListProps {
  projectId: string
  onSelect: (item: Item) => void
}

export function ItemList({ projectId, onSelect }: ItemListProps) {
  // Good: Use TanStack Query for data fetching
  const { data: items, isLoading } = useQuery({
    queryKey: ['items', projectId],
    queryFn: () => api.getItems(projectId),
  })

  // Good: Handle loading and error states
  if (isLoading) return <Spinner />

  return (
    <ul>
      {items?.map(item => (
        <li key={item.id} onClick={() => onSelect(item)}>
          {item.title}
        </li>
      ))}
    </ul>
  )
}
```

### Type Safety

Both Python and TypeScript code must pass strict type checking:

```bash
# Python type checking
poe type-check          # mypy (standard)
poe type-check-strict   # basedpyright (strict)

# TypeScript type checking
npm run typecheck
```

## Testing Requirements

All contributions must include appropriate tests.

### Python Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=src/tracertm

# Run specific test file
pytest tests/unit/services/test_item_service.py

# Run tests matching pattern
pytest -k "test_create_item"
```

**Test structure:**

```
tests/
├── unit/                    # Unit tests (fast, isolated)
│   ├── services/
│   ├── repositories/
│   └── models/
├── integration/             # Integration tests (database required)
│   ├── api/
│   └── storage/
├── e2e/                     # End-to-end tests
└── conftest.py              # Shared fixtures
```

**Writing tests:**

```python
import pytest
from tracertm.services.item_service import ItemService

class TestItemService:
    """Tests for ItemService."""

    @pytest.fixture
    def service(self, mock_item_repo, mock_link_repo):
        """Create service with mock dependencies."""
        return ItemService(mock_item_repo, mock_link_repo)

    async def test_create_item_success(self, service, mock_session):
        """Test successful item creation."""
        # Arrange
        data = ItemCreate(title="Test Item", item_type="feature")

        # Act
        result = await service.create_item(mock_session, "proj-1", data)

        # Assert
        assert result.title == "Test Item"
        assert result.item_type == "feature"

    async def test_create_item_project_not_found(self, service, mock_session):
        """Test item creation with non-existent project."""
        with pytest.raises(NotFoundError, match="Project not found"):
            await service.create_item(mock_session, "invalid-id", data)
```

### Frontend Tests

```bash
cd frontend/apps/web

# Run tests
npm run test

# Run with coverage
npm run test:coverage

# Watch mode
npm run test:watch
```

**Writing tests:**

```typescript
import { render, screen, fireEvent } from '@testing-library/react'
import { ItemList } from './ItemList'

describe('ItemList', () => {
  it('renders items correctly', () => {
    const items = [
      { id: '1', title: 'Feature A' },
      { id: '2', title: 'Feature B' },
    ]

    render(<ItemList items={items} onSelect={jest.fn()} />)

    expect(screen.getByText('Feature A')).toBeInTheDocument()
    expect(screen.getByText('Feature B')).toBeInTheDocument()
  })

  it('calls onSelect when item clicked', () => {
    const onSelect = jest.fn()
    const items = [{ id: '1', title: 'Feature A' }]

    render(<ItemList items={items} onSelect={onSelect} />)
    fireEvent.click(screen.getByText('Feature A'))

    expect(onSelect).toHaveBeenCalledWith(items[0])
  })
})
```

## Commit Messages

We use [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <subject>

[optional body]

[optional footer(s)]
```

**Types:**

| Type | Description |
|------|-------------|
| `feat` | New feature |
| `fix` | Bug fix |
| `docs` | Documentation |
| `style` | Code style (formatting) |
| `refactor` | Refactoring |
| `perf` | Performance improvement |
| `test` | Test changes |
| `build` | Build system changes |
| `ci` | CI/CD changes |
| `chore` | Maintenance |

**Examples:**

```bash
# Feature
git commit -m "feat(api): add project export endpoint"

# Bug fix with issue reference
git commit -m "fix(storage): resolve sync race condition

Fixed race condition in sync engine when multiple agents
update the same item concurrently.

Fixes #234"

# Breaking change
git commit -m "feat(api)!: change error response format

BREAKING CHANGE: Error responses now use RFC 7807 format.
Client applications need to update error handling."
```

## Pull Request Process

### PR Requirements

Before submitting a PR:

- [ ] All tests pass (`poe test`)
- [ ] Code quality checks pass (`poe quality`)
- [ ] New code has test coverage
- [ ] Documentation updated if needed
- [ ] Commit messages follow conventions
- [ ] PR description explains the changes

### PR Template

When creating a PR, fill out the template:

```markdown
## Description
Brief description of changes.

## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation

## How to Test
Steps to test the changes.

## Checklist
- [ ] Tests pass
- [ ] Documentation updated
- [ ] No breaking changes (or documented)

## Related Issues
Closes #123
```

### Review Process

1. **Automated checks**: CI runs tests and linting
2. **Code review**: At least one maintainer reviews
3. **Feedback**: Address review comments
4. **Approval**: Maintainer approves the PR
5. **Merge**: Maintainer merges (usually squash)

### After Merge

After your PR is merged:

1. Delete your branch
2. Sync your fork with upstream
3. Celebrate!

## Documentation

### Code Documentation

**Python docstrings:**

```python
def get_coverage(project_id: str, item_types: list[str] | None = None) -> CoverageResult:
    """Calculate test coverage for a project.

    Analyzes the traceability links between requirements and tests
    to determine what percentage of requirements have associated tests.

    Args:
        project_id: The project to analyze
        item_types: Optional filter for item types to include.
            Defaults to ["feature", "story"] if not specified.

    Returns:
        CoverageResult containing total items, covered items,
        and coverage percentage.

    Raises:
        NotFoundError: If the project doesn't exist.

    Example:
        >>> result = get_coverage("proj-123")
        >>> print(f"Coverage: {result.percentage}%")
        Coverage: 85.5%
    """
```

**TypeScript JSDoc:**

```typescript
/**
 * Fetches items for a project with optional filtering.
 *
 * @param projectId - The project to fetch items from
 * @param options - Optional filter and pagination options
 * @returns Promise resolving to paginated item list
 *
 * @example
 * ```typescript
 * const items = await getItems('proj-123', { type: 'feature' })
 * ```
 */
export async function getItems(
  projectId: string,
  options?: ItemQueryOptions
): Promise<PaginatedResult<Item>> {
  // ...
}
```

### User Documentation

Documentation lives in `docs-site/content/docs/`. To add or modify documentation:

```bash
# Start documentation dev server
cd docs-site
npm run dev

# Build documentation
npm run build
```

Documentation style:

- Use **Markdown** with MDX extensions
- Include **code examples** for all features
- Keep explanations **clear and concise**
- Add **links** to related topics

## Getting Help

### Resources

- **GitHub Discussions**: Ask questions and discuss features
- **Discord**: Real-time chat with the community
- **Issues**: Report bugs or request features

### Contact Maintainers

For sensitive issues or questions:

- Email: maintainers@tracertm.dev
- Security issues: security@tracertm.dev

## Recognition

Contributors are recognized in:

- [CONTRIBUTORS.md](https://github.com/tracertm/tracertm/blob/main/CONTRIBUTORS.md)
- Release notes
- Project documentation

Thank you for contributing to TraceRTM!

## Related Documentation

- [Code Style Guide](/docs/development/contributing/code-style)
- [Commit Message Guidelines](/docs/development/contributing/commit-messages)
- [Testing Guide](/docs/development/contributing/testing)
- [Pull Request Guide](/docs/development/contributing/pull-requests)

