Skip to content

git_blame_age

Fire on lines matching a regex whose git blame author-time is older than max_age_days. Same regex match shape as file_content_forbidden, but with a per-line age gate: a recent TODO passes silently; an old TODO fires. The comparison uses one deterministic UTC reference: --as-of YYYY-MM-DD, then ALINT_AS_OF, then the HEAD commit's committer timestamp. Every finding ends with (as of YYYY-MM-DD).

{{ctx.match}} substitutes the regex capture group 1 when present, otherwise the full match — useful for surfacing which marker was caught (TODO vs FIXME vs …). alint explain <id> shows the resolved date and whether it came from explicit input or HEAD.

Heuristic notes:

  • Formatting passes reset blame age. cargo fmt / prettier rewrites every touched line, attributing it to the format commit rather than the original author. List formatting-sweep commits in a tracked, regular .git-blame-ignore-revs; alint applies that repository input but ignores global and clone-local blame.ignoreRevsFile lists.
  • Vendored / imported code carries the import commit's timestamp — exclude vendor/, third_party/, generated trees.
  • Squash-merged PRs collapse to a single commit date, so the squash date wins over the actual edit date.
  • Performance. git blame is O(file_size × commits_touching_file) per file. On large monorepos pair with alint check --changed so blame only runs over modified files in CI.

If Git cannot be run or the lint root is not a Git repository, the rule reports a resource_read analysis failure even when --as-of supplies the reference date. In a usable repository with an unborn HEAD, provide --as-of or ALINT_AS_OF; otherwise the missing reference date is an evaluation failure. Untracked files and individual files whose blame fails remain silent no-ops. Check-only — auto-removing matched lines is destructive and pinning a line as "do nothing" doesn't help.

OptionTypeRequiredDefaultDescription
max_age_daysinteger (>= 1)yesMinimum line age (in days) for a matching line to fire as a violation. Lines younger than this pass silently. Common values: 90 (one quarter), 180 (half a year), 365 (a full year of debt).
patternstringyesRust-regex pattern applied to each blame line's content. Capture group 1 (when present) is exposed as {{ctx.match}} in the message template; without a capture group, {{ctx.match}} substitutes the full match.

Plus the common paths, level, id, when, scope_filter, and expect_matches fields. This table is generated from the JSON Schema; option types and defaults are authoritative.

A TODO comment that has gone stale

Section titled "A TODO comment that has gone stale"

The rule fires on this repository:

  • reference.txt✓
  • src/
  • src/main.rs

    ⚠ warning stale-todos

    2:1 This TODO is older than 30 days; address it or remove the marker. (as of 2026-10-16)

reference.txt
advance HEAD's deterministic analysis time
src/main.rs
fn main() {
// TODO: refactor this
}

With this .alint.yml:

version: 1
rules:
- id: stale-todos
kind: git_blame_age
paths: "**/*.rs"
pattern: '\bTODO\b'
max_age_days: 30
message: "This TODO is older than 30 days; address it or remove the marker."
level: warning

committed with this history (oldest first):

2000-01-01T00:00:00 add a todo (adds src/main.rs)
2026-10-16T00:00:00 advance head (adds reference.txt)

alint check reports:

Terminal window
--- src/main.rs ----------------------------------------------------------------
! warning stale-todos
2:1 This TODO is older than 30 days; address it or remove the marker.
(as of 2026-10-16)
Summary (1 violation):
! 1 warning
0 passing * 1 failing

This repository is compliant:

  • src/
  • src/main.rs✓
src/main.rs
fn main() {
// TODO: refactor this
}

With this .alint.yml:

version: 1
rules:
- id: stale-todos
kind: git_blame_age
paths: "**/*.rs"
pattern: '\bTODO\b'
max_age_days: 30
message: "This TODO is older than 30 days; address it or remove the marker."
level: warning

committed with this history (oldest first):

add a todo (adds src/main.rs)

alint check reports:

Terminal window
v All 1 rule(s) passed.