Skip to content

Attribution & blame

Source: packages/core/src/git/attribution.ts, packages/core/src/patterns/blame.ts, packages/cli/src/commands/blame.ts · Spec: §3.3, §8.1

Capture (best-effort, derivation recorded)

Section titled “Capture (best-effort, derivation recorded)”

attribution is about the code’s history; Actor is about who operates Beetl — never conflated.

  • introducedBygit blame --porcelain over diagnosis.filesImplicated line refs (path:line/path:line-end; no line → whole file), deduped, capped at 10, each entry via: "git-blame".
  • fixedByfix.commits resolved through git show, via: "git-show".
  • Any git failure (not a repo, unknown path/commit) yields nothing — capture is silent best-effort, never an error.

Capture is incremental (H-06): each side derives independently and merges into any existing attribution — introducedBy once filesImplicated exists, fixedBy once fix.commits lands later in the staged workflow. It re-runs whenever source fields change, dedupes by author+commit, and is a no-op when nothing new derives (no event spam). Agents may also supply attribution in a draft/record directly. It fires on:

  • update / move / resolve gate flags — persisted via a dedicated applyAttribution mutation, logged as an update event (fields: ["attribution"]).
  • new — captured right after create.
  • file-complete — derived from the input record and injected before filing, since the result is terminal (read-only on disk).

beetl blame [--author <who>] [--agents|--humans] [--category <name>]

Section titled “beetl blame [--author <who>] [--agents|--humans] [--category <name>]”

Explicit per-author/per-agent analysis (beetl patterns stays authorless):

  • Reporters — initiator actors, sessions + category distribution.
  • Introducers / fixers — git-derived authors; fixers carry a refixed count (how many of their fixes were later re-fixed — fix-quality signal).
  • Agent vs human — reported-session split, overall and per category.

Every stat carries its derivation methods (via). --agents/--humans restrict sessions by reporting actor kind; --author filters rows by substring; --category scopes sessions first.

Local-only by default (spec §8.1, ADR-0008, M-06): blame output is terminal/JSON-only. The global mirror omits attribution entirely unless attribution.inCommittedReports is true (so default blame --global aggregates reporters only); pattern reports stay always authorless. beetl blame --record is the explicit act that commits a rendered blame report to .beetl/reports/<date>-blame.md and returns recordedPath.