Metadata-Version: 2.4
Name: tracemap-pr
Version: 0.1.0
Summary: Deterministic PR blast-radius map for backend changes
Project-URL: Homepage, https://github.com/balyakin/tracemap-pr
Project-URL: Documentation, https://github.com/balyakin/tracemap-pr#readme
Project-URL: Repository, https://github.com/balyakin/tracemap-pr
Project-URL: Issues, https://github.com/balyakin/tracemap-pr/issues
License: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: aiosqlite<1.0,>=0.20
Requires-Dist: alembic<2.0,>=1.14
Requires-Dist: asyncpg<1.0,>=0.29
Requires-Dist: defusedxml<1.0,>=0.7
Requires-Dist: fastapi<1.0,>=0.128
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: jinja2<4.0,>=3.1
Requires-Dist: orjson<4.0,>=3.10
Requires-Dist: pydantic-settings<3.0,>=2.6
Requires-Dist: pydantic<3.0,>=2.10
Requires-Dist: python-multipart<1.0,>=0.0.20
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: rich<14.0,>=13.7
Requires-Dist: sqlalchemy[asyncio]<3.0,>=2.0
Requires-Dist: taskiq-redis<2.0,>=1.0
Requires-Dist: taskiq<1.0,>=0.11
Requires-Dist: typer<1.0,>=0.12
Requires-Dist: uvicorn<1.0,>=0.35
Provides-Extra: dev
Requires-Dist: bandit<2.0,>=1.7; extra == 'dev'
Requires-Dist: hypothesis<7.0,>=6.100; extra == 'dev'
Requires-Dist: mypy<2.0,>=1.10; extra == 'dev'
Requires-Dist: pip-audit<3.0,>=2.7; extra == 'dev'
Requires-Dist: pytest-asyncio<2.0,>=1.0; extra == 'dev'
Requires-Dist: pytest-cov<7.0,>=5.0; extra == 'dev'
Requires-Dist: pytest<10.0,>=9.0.3; extra == 'dev'
Requires-Dist: respx<1.0,>=0.21; extra == 'dev'
Requires-Dist: ruff<1.0,>=0.8; extra == 'dev'
Description-Content-Type: text/markdown

# TraceMap PR

Deterministic pull request impact reports for backend teams.

[![CI][badge-ci]][ci]
[![PyPI][badge-pypi]][pypi]
[![Python 3.12][badge-python]][python]
[![Coverage gate][badge-coverage]][ci]
[![Checks][badge-checks]][ci]
[![License: MIT][badge-license]][license]

TraceMap PR reads the evidence a service already produces: `git diff`, OpenAPI, coverage,
per-test coverage, traces, and a small Python static scan. It turns that into a conservative
review comment showing which endpoints, background jobs, database tables, external services,
and tests may be touched by a change.

It does not call LLMs, embedding APIs, or external AI services. Every item in the report is tied
to concrete evidence and a confidence score. When TraceMap does not know enough, it says so.

![TraceMap PR report screenshot][screenshot]

The screenshot above is based on the checked-in FastAPI demo fixture. It shows the main product
surface: a pull request comment that reviewers can read without opening another tool.

## Why It Exists

Backend pull requests often look smaller than they are. A two-file diff can move an API path,
a queue task, a billing table, and a third-party call. Reviewers usually rebuild that map in their
heads from code search, test names, traces, and memory.

TraceMap PR makes that map explicit. It is not proof that a change is safe. It is a fast,
repeatable way to see the likely blast radius and the places where the available evidence is thin.

## What You Get

- A Markdown report that can be posted as a GitHub PR comment.
- A JSON report for bots, dashboards, and follow-up automation.
- A local CLI that works without a server, database, account, or network call.
- A GitHub composite action for pull request workflows.
- A FastAPI server mode for artifact history, project-scoped tokens, and async report generation.
- A pytest plugin that writes per-test coverage in TraceMap's expected format.

## Quickstart

Install the CLI and create a config in your backend repository:

```bash
uv tool install tracemap-pr
tracemap init --auto
tracemap doctor
tracemap impact --base origin/main --head HEAD --out tracemap-report.md || test "$?" = "1"
```

To try the checked-in demo from source:

```bash
uv sync --extra dev
uv run tracemap impact \
  --repo-root tests/fixtures/fastapi_demo \
  --config tests/fixtures/fastapi_demo/tracemap.yml \
  --diff-file tests/fixtures/repo_diff/diff_billing.patch \
  --out /tmp/tracemap-report.md || test "$?" = "1"
sed -n '1,120p' /tmp/tracemap-report.md
```

The `impact` command exits with code `1` after writing a report if it found visible unknown zones.
That is useful in CI, but surprising the first time you run it locally.

For better test signal, run pytest with coverage contexts and the TraceMap plugin:

```bash
uv add --dev tracemap-pr
uv run pytest --cov --cov-context=test \
  --tracemap-coverage-out .tracemap/per_test_coverage.json
```

## Signals TraceMap Understands

TraceMap gets better as you give it more artifacts, but it is useful before everything is wired up.

| Signal | Supported inputs | What it helps answer |
|---|---|---|
| Diff | `git diff` or a unified patch file | Which files and lines changed? |
| OpenAPI | JSON or YAML specs | Which HTTP operations may be involved? |
| Coverage | Cobertura XML, `coverage.py` JSON | Are changed lines covered at all? |
| Per-test coverage | TraceMap pytest plugin JSON | Which tests touch the changed code? |
| Traces | normalized NDJSON, limited OTLP HTTP JSON | Which DB tables, queues, and external services appear near the code path? |
| Static scan | FastAPI routes, Taskiq tasks, SQLAlchemy declarative models | What can be mapped without runtime artifacts? |

Unsupported stacks still run in poor mode. The report will be less rich, and the missing pieces show up as warnings or unknown zones instead of being hidden.

## GitHub Actions

Use `pull_request`, not `pull_request_target`. The action reads code and artifacts from the PR
checkout, so it should run with the normal pull request security model.

```yaml
on:
  pull_request:

jobs:
  tracemap:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: balyakin/tracemap-pr@v0.1.0
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
```

Pin the action to a full commit SHA when your supply-chain policy requires immutable references.

## Local CLI

Common commands:

```bash
tracemap init --auto
tracemap doctor
tracemap scan --base origin/main --head HEAD
tracemap impact --base origin/main --head HEAD --format markdown --out tracemap-report.md
tracemap impact --base origin/main --head HEAD --format json --out tracemap-report.json
```

Exit codes:

| Code | Meaning |
|---:|---|
| `0` | Report built and no visible unknown zones crossed the configured threshold. |
| `1` | Report built, but visible unknown zones were found. |
| `2` | Configuration, parsing, storage, graph, or report build error. |
| `3` | Git diff command or diff parsing error. |

## Server Mode

The CLI is the primary path. Server mode is for teams that want history, uploaded artifacts, project-scoped API tokens, and async report generation.

```bash
docker compose up --build
```

The API listens on `http://localhost:8080`. The included dashboard is server-rendered HTML on purpose; there is no SPA build step in the MVP.

Production server mode should use PostgreSQL, Redis for async work, a non-empty bootstrap token hash,
and private artifact storage. See [docs/SECURITY.md][security] before exposing it outside
localhost.

## Configuration

`tracemap init --auto` writes `tracemap.yml`. A fuller example is available in
[tracemap.example.yml][example-config].

The most important sections are:

- `scan`: source globs for Python static analysis.
- `openapi`: OpenAPI JSON/YAML files.
- `coverage`: Cobertura, coverage.py JSON, and per-test coverage files.
- `traces`: normalized TraceMap traces and the supported OTLP JSON subset.
- `privacy`: header, query string, and attribute scrubbing.
- `impact` and `scoring`: traversal limits, unknown-zone threshold, and confidence weights.

## Design Principles

- Deterministic first. The same inputs should produce the same report.
- Evidence is visible. A confidence score without a reason is not useful in review.
- Unknown zones stay visible. A short report is not better if it hides risk.
- The core pipeline is shared. CLI, API, and worker all call `tracemap_core`.
- Local use stays simple. PostgreSQL, Redis, and server mode are optional.

## Project Layout

```text
src/tracemap_core/      artifact parsing, graph building, scoring, reports
src/tracemap_cli/       Typer CLI and GitHub comment publishing
src/pytest_tracemap/    pytest plugin for per-test coverage output
src/tracemap_api/       FastAPI server, dashboard, API routes
src/tracemap_worker/    Taskiq worker entrypoint
tests/fixtures/         demo service, golden report, patch fixtures
docs/adr/               short architecture decisions
```

## Current Scope

TraceMap PR is intentionally narrow today: Python 3.12, FastAPI, Taskiq, SQLAlchemy, GitHub PR
comments, and self-hosted server mode. Other languages and CI providers can still use poor mode,
but first-class static scanners are not there yet.

That tradeoff is deliberate. The project would rather be honest about a smaller set of signals than pretend to understand every stack.

## License

MIT. See [LICENSE][license].

## Development

```bash
uv sync --extra dev
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run pytest
uv run bandit -r src -ll
uv run pip-audit
uv build
```

The full CI checklist is documented in [docs/CI.md][ci-docs].

This project was developed with AI assistance and is maintained by the author.

[badge-ci]: https://github.com/balyakin/tracemap-pr/actions/workflows/ci.yml/badge.svg
[badge-pypi]: https://img.shields.io/pypi/v/tracemap-pr.svg
[badge-python]: https://img.shields.io/badge/python-3.12-blue
[badge-coverage]: https://img.shields.io/badge/coverage%20gate-85%25-brightgreen
[badge-checks]: https://img.shields.io/badge/checks-ruff%20%7C%20mypy%20%7C%20pytest-brightgreen
[badge-license]: https://img.shields.io/badge/license-MIT-green.svg
[ci]: https://github.com/balyakin/tracemap-pr/actions/workflows/ci.yml
[ci-docs]: https://github.com/balyakin/tracemap-pr/blob/main/docs/CI.md
[example-config]: https://github.com/balyakin/tracemap-pr/blob/main/tracemap.example.yml
[license]: https://github.com/balyakin/tracemap-pr/blob/main/LICENSE
[pypi]: https://pypi.org/project/tracemap-pr/
[python]: https://www.python.org/downloads/
[screenshot]: https://raw.githubusercontent.com/balyakin/tracemap-pr/main/docs/assets/tracemap-pr-report.svg
[security]: https://github.com/balyakin/tracemap-pr/blob/main/docs/SECURITY.md
