Skip to content

cadence: commits-per-day timeline + gap detection #4

@simon-marcus

Description

@simon-marcus

Implement `commitlens cadence` — a per-day commit count timeline with gap detection.

Deliverable

Module: `src/commitlens/cadence.py`. Register in `_register_subcommands`.

Output schema

```json
{
"_render": "",
"days": [
{"date": "2026-04-01", "commits": 3},
{"date": "2026-04-02", "commits": 0},
...
],
"total_commits": 113,
"active_days": 41,
"longest_gap": {"start": "2026-04-10", "end": "2026-04-22", "days": 12}
}
```

`days` covers EVERY day from `first_commit` to `last_commit` inclusive — no skipped days. `active_days` is the count of `days` entries with `commits > 0`. `longest_gap` is the longest run of zero-commit days; if there's no gap, set it to `null`.

Human render

A sparkline-ish timeline like:

```
2026-04-01 ### 3
2026-04-02 . 0
2026-04-03 ## 2
...
```

Where bar width = `min(40, commits)` (so big-commit days don't blow out the column). Below the timeline, print:

```
Total: 113 commits over 60 days (41 active, 19 idle)
Longest gap: 12 days, 2026-04-10 → 2026-04-22
```

Tests

`tests/test_cadence.py` using `git_repo` with the `date=` parameter to scatter commits across known dates including a deliberate 5-day gap. Assert:

  • `total_commits` matches.
  • `days` length equals `(last - first).days + 1`.
  • `active_days` matches.
  • `longest_gap` correctly identifies the 5-day gap.
  • Edge case: a repo with only one commit produces `longest_gap: null`.

Metadata

Metadata

Assignees

No one assigned

    Labels

    symphonyCreated by Symphony

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions