Skip to content

Contributing to TraceKit

First off, thank you for considering contributing to TraceKit! It's people like you that make TraceKit such a great tool.

Documentation Philosophy

TraceKit follows a "demos as documentation" approach:

  • Learn by Example: All capabilities are demonstrated in demos/ with working code
  • Demo READMEs: Each demo category has a comprehensive README explaining concepts
  • API Reference: Generated documentation at docs/api/

When adding new capabilities:

  1. Implement the feature
  2. Add working demo in appropriate category
  3. Update demo README to explain the capability
  4. Ensure docstrings are complete (for API docs generation)

Do NOT create separate user guides or tutorials - they will drift out of sync. Demos are the source of truth.

Versioning and Compatibility

TraceKit follows Semantic Versioning (SemVer):

  • MAJOR version for incompatible API changes
  • MINOR version for backwards-compatible functionality additions
  • PATCH version for backwards-compatible bug fixes

Stability Commitment:

  • Backwards compatibility - Maintained within major versions
  • Deprecation warnings - Added before removing features
  • Migration guides - Provided for major version upgrades
  • Semantic versioning - Strictly followed for all releases

Code of Conduct

How Can I Contribute?

Reporting Bugs

Before creating bug reports, please check existing issues to avoid duplicates. When you create a bug report, include as many details as possible:

  • Use a clear and descriptive title
  • Describe the exact steps to reproduce the problem
  • Provide specific examples (code snippets, waveform files, etc.)
  • Describe the behavior you observed and what you expected
  • Include your environment details (Python version, OS, TraceKit version)

Suggesting Enhancements

Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion:

  • Use a clear and descriptive title
  • Provide a step-by-step description of the suggested enhancement
  • Explain why this enhancement would be useful
  • List any alternatives you've considered

Pull Requests

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Commit your changes using conventional commits
  5. Pre-commit hooks run automatically (lint, format, type check)
  6. Run local CI verification (./scripts/pre-push.sh)
  7. This is AUTOMATIC if you installed hooks via ./scripts/setup/install-hooks.sh
  8. Verifies your code against the full CI pipeline locally
  9. Push to your branch (git push origin feature/amazing-feature)
  10. Pre-push hook runs automatically (if installed)
  11. Open a Pull Request

CRITICAL: Steps 4-5 must pass BEFORE step 6. If you skip verification, your PR will fail CI.

Development Setup

Prerequisites

  • Python 3.12+
  • uv package manager
  • Node.js 18+ (for markdownlint)

Installation

# Clone your fork
git clone https://github.com/YOUR-USERNAME/tracekit.git
cd tracekit

# Install all dependencies (REQUIRED)
uv sync --all-extras

# Install git hooks (REQUIRED - prevents CI failures)
./scripts/setup/install-hooks.sh

# Verify setup
uv run pytest tests/unit -x --maxfail=5

IMPORTANT: The install-hooks.sh script installs BOTH pre-commit and pre-push hooks. These hooks are REQUIRED to prevent CI failures. Do not skip this step!

Development Workflow

Quick Reference

# 1. Make your changes

# 2. Quick verification during development
./scripts/setup/verify.sh         # Fast: lint + format check
./scripts/setup/verify.sh --fix   # Auto-fix issues

# 3. Run comprehensive checks
./scripts/check.sh                # Lint + typecheck
./scripts/fix.sh                  # Auto-fix all issues
./scripts/test.sh                 # Run tests (optimal config)
./scripts/test.sh --fast          # Quick tests without coverage

# 4. Before pushing - full CI verification
./scripts/pre-push.sh             # Full CI verification (10-15 min)
./scripts/pre-push.sh --quick     # Fast mode (2 min)

# 5. Commit and push
git add .
git commit -m "feat: your change"  # Pre-commit hook runs automatically
git push                           # Pre-push hook runs automatically

Verification Scripts

Script Purpose Duration
./scripts/setup/verify.sh Quick lint/format check ~30s
./scripts/check.sh Lint + typecheck ~1m
./scripts/fix.sh Auto-fix all issues ~30s
./scripts/test.sh Optimal test execution ~8-10m
./scripts/test.sh --fast Quick tests (no coverage) ~5-7m
./scripts/pre-push.sh Full CI verification ~10-15m

Always use these validated scripts instead of manual commands. They provide optimal configuration and are battle-tested through CI/CD.

What Pre-Push Verifies

The pre-push.sh script mirrors the GitHub Actions CI pipeline:

Stage 1 - Fast Checks: - Pre-commit hooks (ruff, format, yaml, markdown, etc.) - Ruff lint and format verification - MyPy type checking - Config validation (SSOT, orchestration)

Stage 2 - Tests: - Test marker validation - Unit tests (parallelized) - Integration tests - Compliance tests

Stage 3 - Build Verification: - MkDocs documentation build (--strict) - Package build (uv build) - CLI command verification - Docstring coverage check

Git Hooks

TraceKit uses two types of git hooks to prevent CI failures:

  1. Pre-commit hooks (via pre-commit framework) - Run quality checks on every commit
  2. Pre-push hooks (custom) - Run comprehensive CI verification before push

Bypassing hooks: Only bypass hooks when you have a good reason (e.g., WIP branch):

git commit --no-verify    # Skip pre-commit (use sparingly)
git push --no-verify      # Skip pre-push (DANGEROUS - only for emergencies)

Running Tests

Recommended: Use the optimized test script:

./scripts/test.sh              # Full tests with coverage (8-10 min)
./scripts/test.sh --fast       # Quick tests without coverage (5-7 min)

Manual test commands (only if needed for specific scenarios):

# Run unit tests
uv run pytest tests/unit -v --timeout=90

# Run tests with coverage
uv run pytest tests/unit --cov=src/tracekit --cov-report=term-missing

# Run specific module tests
uv run pytest tests/unit/analyzers -v
uv run pytest tests/unit/protocols -v

# Run in parallel
uv run pytest tests/unit -n auto

Coding Standards

Style Guide

  • Follow PEP 8 (enforced by ruff)
  • Use type hints for all function signatures
  • Write docstrings for all public functions and classes
  • Keep functions focused and small

Commit Messages

We use Conventional Commits:

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

<body>

<footer>

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation only
  • style: Code style (formatting, missing semi-colons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • test: Adding missing tests
  • chore: Maintenance tasks

Examples:

feat(protocols): add FlexRay decoder support
fix(loaders): correct Tektronix WFM channel parsing
docs(api): add spectral analysis examples
test(analyzers): increase rise time test coverage

Testing

  • Write tests for all new features
  • Maintain or improve test coverage
  • Use descriptive test names that explain the scenario
  • Follow the existing test structure

Documentation

  • Update demo README for any user-facing changes
  • Add docstrings to all public functions
  • Include code examples where helpful
  • Demos are the primary documentation

IEEE Compliance Guidelines

When implementing measurement functions, follow IEEE standards:

  • IEEE 181-2011: Pulse measurements (rise/fall time, slew rate)
  • IEEE 1241-2010: ADC testing (SNR, SINAD, ENOB)
  • IEEE 2414-2020: Jitter measurements (TIE, period jitter)

Include references to specific standard sections in docstrings:

def rise_time(trace: TraceData, low: float = 0.1, high: float = 0.9) -> float:
    """Calculate rise time per IEEE 181-2011 Section 5.2.

    The rise time is the interval between the reference level instants
    when the signal crosses the specified low and high percentage levels.

    Args:
        trace: Input waveform trace.
        low: Low reference level (0-1). Default 10%.
        high: High reference level (0-1). Default 90%.

    Returns:
        Rise time in seconds.

    References:
        IEEE 181-2011 Section 5.2 "Rise Time and Fall Time"
    """

Documentation Checklist

Before submitting a PR that includes new code, ensure:

  • [ ] All new public functions have docstrings
  • [ ] Docstrings follow NumPy style format
  • [ ] Args section lists all parameters with descriptions
  • [ ] Returns section describes the return value
  • [ ] Raises section documents all exceptions (if applicable)
  • [ ] Examples are included for complex functionality
  • [ ] Demo README updated if behavior changes
  • [ ] CHANGELOG.md updated for user-visible changes
  • [ ] IEEE references included for measurement functions
  • [ ] Local verification passes (./scripts/pre-push.sh)

Docstring Format

Use NumPy-style docstrings:

def example_function(param1: str, param2: int = 0) -> bool:
    """Brief one-line description.

    Extended description if needed. Can span multiple lines
    and provide additional context.

    Parameters
    ----------
    param1 : str
        Description of first parameter.
    param2 : int, optional
        Description of second parameter. Default is 0.

    Returns
    -------
    bool
        Description of return value.

    Raises
    ------
    ValueError
        When param1 is empty.
    TypeError
        When param2 is not an integer.

    Examples
    --------
    >>> example_function("value", 10)
    True

    Notes
    -----
    Additional implementation notes if needed.

    References
    ----------
    IEEE 181-2011 Section X.X (if applicable)
    """

Project Structure

tracekit/
├── demos/                  # Primary documentation (working examples)
│   ├── 01_waveform_analysis/       # Waveform loading and analysis
│   ├── 02_file_format_io/          # CSV, HDF5, NumPy formats
│   ├── 03_custom_daq/              # Custom DAQ loaders
│   ├── 04_serial_protocols/        # UART, SPI, I2C basics
│   ├── 05_protocol_decoding/       # Multi-protocol decoding
│   ├── 06_udp_packet_analysis/     # Network packet analysis
│   ├── 07_protocol_inference/      # Unknown protocol inference
│   ├── 08_automotive_protocols/    # CAN, OBD-II, J1939
│   ├── 09_automotive/              # Advanced automotive
│   ├── 10_timing_measurements/     # Timing and jitter
│   ├── 11_mixed_signal/            # Mixed signal validation
│   ├── 12_spectral_compliance/     # Spectral analysis (IEEE 1241)
│   ├── 13_jitter_analysis/         # Jitter (IEEE 2414)
│   ├── 14_power_analysis/          # Power quality (IEEE 1459)
│   ├── 15_signal_integrity/        # Signal integrity metrics
│   ├── 16_emc_compliance/          # EMC compliance testing
│   ├── 17_signal_reverse_engineering/  # Signal RE workflows
│   ├── 18_advanced_inference/      # Advanced inference
│   └── 19_complete_workflows/      # End-to-end workflows
├── docs/                   # API reference & technical docs
│   ├── api/                    # Generated API reference
│   └── testing/                # Testing documentation
├── src/tracekit/           # Source code
│   ├── core/               # Data types, exceptions, configuration
│   ├── loaders/            # File format loaders
│   ├── analyzers/          # Signal analysis modules
│   ├── protocols/          # Protocol decoders
│   ├── inference/          # Protocol inference
│   ├── exporters/          # Data export formats
│   └── visualization/      # Plotting utilities
├── scripts/                # Development utilities
│   ├── setup/              # Setup and installation
│   │   ├── install-hooks.sh    # Install git hooks (REQUIRED)
│   │   └── verify.sh           # Quick verification
│   ├── quality/            # Quality checks
│   │   ├── lint.sh             # Linting only
│   │   └── format.sh           # Formatting only
│   ├── testing/            # Test utilities
│   │   └── run_coverage.sh     # Coverage report
│   ├── pre-push.sh         # Full CI verification (use before push)
│   ├── check.sh            # Lint + typecheck (use frequently)
│   ├── fix.sh              # Auto-fix all issues
│   └── test.sh             # Optimal test execution (SSOT)
└── tests/                  # Test suite
    ├── unit/               # Unit tests
    ├── integration/        # Integration tests
    └── conftest.py         # Test fixtures and configuration

Troubleshooting CI Failures

If CI fails after push, here's how to debug:

1. Run Local Verification First

# This should catch most issues
./scripts/pre-push.sh

# If tests fail locally, get detailed output
uv run pytest <failing_test> -v --tb=long

2. Common CI Failure Causes

Failure Local Check Fix
Ruff lint ./scripts/quality/lint.sh ./scripts/fix.sh
Ruff format ./scripts/quality/format.sh ./scripts/fix.sh
MyPy uv run mypy src/ Fix type errors
Pre-commit pre-commit run --all-files Follow error messages
MkDocs uv run mkdocs build --strict Fix broken links/warnings
Docstrings uv run interrogate src/tracekit -f 95 Add missing docstrings

3. Environment Differences

CI runs on Ubuntu with Python 3.12 and 3.13. If tests pass locally but fail in CI:

# Check Python version
python --version

# Run tests with strict markers (like CI)
uv run pytest tests/unit -v --strict-markers --strict-config

Getting Help

  • GitHub Discussions: For questions and discussions
  • GitHub Issues: For bugs and feature requests

Recognition

Contributors are recognized in:

  • The CHANGELOG.md for significant contributions
  • The GitHub contributors page
  • Special thanks in release notes for major features

License

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


Thank you for contributing to TraceKit!