Metadata-Version: 2.5
Name: codepulse-cli
Version: 0.1.3
Summary: Reveal a codebase's health from its git history — hotspots, bus factor, hidden coupling, and a CI risk gate.
Project-URL: Homepage, https://github.com/Mehouelley/codepulse
Project-URL: Repository, https://github.com/Mehouelley/codepulse
Project-URL: Issues, https://github.com/Mehouelley/codepulse/issues
Author-email: Mehouelley <fabricemehouelley43@gmail.com>
License: MIT
License-File: LICENSE
Keywords: code-health,code-quality,devops,git,hotspots,static-analysis,technical-debt
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# 🩺 CodePulse

[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-CodePulse-2088FF?logo=github&logoColor=white)](https://github.com/marketplace/actions/codepulse-risk-gate)
[![tests](https://github.com/Mehouelley/codepulse/actions/workflows/tests.yml/badge.svg)](https://github.com/Mehouelley/codepulse/actions/workflows/tests.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Zero dependencies](https://img.shields.io/badge/dependencies-none-brightgreen.svg)](pyproject.toml)

**Reveal a codebase's health from its git history.**

Linters read your code. CodePulse reads your code's *history* — and that reveals
things no linter can see: where bugs are born, what knowledge lives in one
person's head, and which files are secretly glued together.

Because it works purely from git history, **CodePulse works on any language**,
with **zero dependencies** beyond git and Python.

---

## Demo

![CodePulse demo](docs/demo.gif)

```console
$ codepulse . --badge
Grade: B (83/100)

$ codepulse . --changed origin/main
Release risk: HIGH (100/100)
   [100] crates/ui-egui/src/lib.rs   (major hotspot)
   Reviewers: Valentin Klein (29/37), Dmitrii Khlapov (22/37)

$ codepulse . --who crates/ui-egui/src/canvas.rs
canvas.rs — 64 commits, 22 authors — 45% Valentin Klein
```

> The GIF is generated from [`demo.tape`](demo.tape) ([VHS](https://github.com/charmbracelet/vhs)).

---

## What it shows

| Signal | Question it answers |
|---|---|
| 🔥 **Hotspots** | *Where do I refactor first?* Files that are both complex and changed constantly — the birthplace of most bugs. |
| 👥 **Bus factor** | *What breaks if someone leaves?* Files actively maintained by a single person. |
| 🔗 **Hidden coupling** | *What really depends on what?* Files that almost always change together, even when the code doesn't show a link. |
| 🏆 **Contributors** | Who is active across the analyzed window. |

The result is a single self-contained **HTML dashboard** you can open anywhere
or email to your team.

---

## Install

```bash
pip install codepulse-cli    # installs the `codepulse` command
```

## Quick start

```bash
# From a git repository:
codepulse /path/to/repo --open

# Common options:
codepulse . --since "6 months ago" --top 30 -o health.html
```

> Running from a source checkout instead? Use `python -m codepulse` with
> `PYTHONPATH=src`, or `pip install -e .`.

### Options

| Flag | Meaning |
|---|---|
| `repo` | Path to a git repository (default: current directory) |
| `-o, --output` | Output HTML path (default: `codepulse-report.html`) |
| `--since` | Only commits after a date, e.g. `"6 months ago"` |
| `--max-count N` | Limit to the N most recent commits |
| `--top N` | Rows per table (default: 20) |
| `--open` | Open the report in a browser when done |
| `--who PATH` | Show who knows a file best (from history) and exit |
| `--badge` | Print a shields.io health-badge snippet and exit |
| `--ignore GLOB` | Exclude paths matching a glob (repeatable) |

---

## Use in CI (the risk gate)

CodePulse can score *only the files a change touches* against the repo's risk
map, then set an exit code so your pipeline can warn or block.

```bash
# Score what this branch changed vs main; fail the job on HIGH risk.
python -m codepulse . --changed origin/main --fail-on HIGH

# Machine-readable output for dashboards / PR comments:
python -m codepulse . --changed origin/main --format json
```

Output (JSON):

```json
{
  "level": "HIGH",
  "score": 100,
  "high_risk_count": 1,
  "files": [
    { "path": "auth.py", "risk": 100, "commits": 6, "loc": 7,
      "reasons": ["hotspot majeur", "auteur unique (Alice)"] }
  ]
}
```

### GitHub Action (two lines)

Add CodePulse to any repository as a reusable Action — it scores each PR, posts
a **sticky comment** (updated in place, never spammed), and fails the check on
`HIGH` risk:

```yaml
name: CodePulse
on: pull_request
permissions:
  contents: read
  pull-requests: write
jobs:
  risk:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 } # full history is required
      - uses: Mehouelley/codepulse@v0.1.0
        with:
          fail-on: HIGH # or MEDIUM / LOW / '' to never fail
```

The PR comment looks like:

> 🩺 **CodePulse — Risque : 🔴 HIGH (100/100)**
> 38 fichiers modifiés · 1 à risque élevé
>
> 👥 **Relecteurs suggérés** : Valentin Klein (29/37 fichiers), Dmitrii Khlapov (22/37)

Prefer a plain workflow with no external action? One ships in
[`.github/workflows/codepulse.yml`](.github/workflows/codepulse.yml) — copy it in as-is.

**Why DevOps cares:** a release is roughly as risky as its riskiest file.
Touching a well-known hotspot — or a file only one person understands — is
exactly where change-failure-rate (a DORA metric) comes from. The gate makes
that risk visible *before* merge, not after an incident.

---

## How it works

1. Parses `git log --numstat` into commits and file changes (no merges).
2. Accumulates per-file history: commit count, authors, size on disk.
3. Derives the signals:
   - **Hotspot score** = `commits × complexity`, where complexity estimates
     decision points (branch keywords + boolean operators) — far better than
     raw line count at telling "big but simple" from "dense and risky".
   - **Bus factor risk** = files with ≥3 commits but exactly one author.
   - **Coupling degree** = `commits-together / min(individual commits)`,
     ignoring bulk commits that touch many files at once.

Inspired by the "code as a crime scene" approach to software analysis, made
simple enough to run in one command.

---

## Roadmap

- [x] Risk gate: score a change set, JSON output, CI exit code
- [x] Ignore globs / path filters for generated & data files
- [x] Post the gate result as a sticky PR comment (GitHub Action)
- [x] Trend over time (adaptive day/week/month buckets + hotspot-pressure verdict)
- [x] Complexity-based hotspots (decision-point estimate instead of line count)
- [x] Suggested PR reviewers from code ownership (in gate text/json/comment)
- [x] `--who <file>` — who knows this code best
- [x] `--badge` — shareable A–F health badge for your README
- [x] Orphaned-code section — complex files nobody touches anymore
- [x] **Recommendations** — prioritized, concrete actions, not just findings

## Development

```bash
pip install -e ".[dev]"
pytest
```

The suite covers the complexity estimator, git parsing, every analyzer, and an
end-to-end run against a throwaway git repo. CI runs it on Python 3.10 and 3.12.

## License

MIT
