Skip to content

Latest commit

 

History

History
136 lines (105 loc) · 6.71 KB

ATTRIBUTION.md

File metadata and controls

136 lines (105 loc) · 6.71 KB

AI Attribution

Which commits an AI agent wrote, read from evidence a repository already carries, with optional edit-time capture for the agents you choose. Every commit gets one of three labels, and every share is shown with the coverage behind it.

Label Meaning
agent A marker or a captured edit ties the commit to an agent
human_attested An explicit human record: a git-ai note naming only human authors, or an Agent Trace record whose contributors are all human
unknown No marker either way. Unknown is never counted as human

What is read by default

With no configuration, indexing reads public markers from local git history. No network calls, no model, no prompts.

Marker Example
Bot author or committer copilot-swe-agent[bot], devin-ai-integration[bot], cursoragent@cursor.com
Message footer Generated with Claude Code, the aider (aider) author suffix
Trailers Co-authored-by: naming an agent service identity, Assisted-by:, Generated-by:
git-ai notes Authorship notes on refs/notes/ai (git-ai standard)
Agent Trace .agent-trace/traces.jsonl records committed to the repository

Every pattern is anchored to a service identity (a bot login, a service email, an exact footer phrase), never a bare name, so a contributor called Devin stays unlabelled.

To recognise your own bot or footer, add it under agent_provenance: in .repowise/config.yaml:

agent_provenance:
  service_emails:
    mybot@example.com: {agent: mybot, tier: 1}
  footer_patterns:
    - {pattern: "Generated by MyBot", agent: mybot}

Edit-time capture (opt-in)

Capture records which lines an agent wrote as it writes them, so commits carry a label even when nothing in the message says so. It is off until both the repository and your user config turn it on.

Agent Capture
Claude Code PostToolUse hook installed with the agent hooks
Codex CLI PostToolUse hook installed with the agent hooks
Cursor afterFileEdit hook: repowise agents add --target=cursor --scope=user

Other agents are read through public markers only. The Attribution column of INTEGRATIONS.md is the live list.

The hook stores line hashes, the repo-relative path, an opaque session id, the tool and the model in .repowise/attribution/events.jsonl, never prompts or code. repowise update (which the post-commit hook runs) matches those hashes to the lines new commits added and labels a matched commit with the agent. An unmatched commit stays unknown.

Backfill from transcripts

repowise attribution backfill --agent claude-code,codex binds past commits from the transcripts these agents keep on this machine, under the same consent. It keeps line hashes only, binds an edit to a commit made within 14 days after it, and needs a run of 6 substantive lines. When it binds new commits, the next repowise update re-reads git history once to label them.

local and notes: what leaves the machine

Level Writes Leaves the machine
off (default) Nothing Nothing
local The sidecar under .repowise/attribution/ (gitignored) and labels in the local index Nothing
notes Everything local writes, plus a git-ai v3 note per matched commit on refs/notes/ai, and notes.rewriteRef so the note follows an amend or rebase Only when you run git push origin refs/notes/ai. Repowise never pushes

A note holds file paths, line ranges, the tool name, the model and a hashed session id. It never holds prompts, code, conversation ids or a person's identity. A commit that already has a note keeps it; Repowise only writes notes on commits without one.

Turning it on and off

# .repowise/config.yaml and ~/.repowise/config.yaml
attribution:
  enabled: true      # read public markers
  capture: off       # off, local or notes
  agents: []         # agent target ids, e.g. claude-code, codex, cursor

The stricter value wins per key across the repo and user files:

  • enabled: false in either file means nothing about AI is stored or shown on any surface.
  • capture takes the lower of the two levels, and an unset key counts as off.
  • agents is the set both files list.
  • DO_NOT_TRACK=1 keeps capture off.
  • An invalid value counts as the strictest value and is reported by status.

Key reference: CONFIG.md.

Status, purge and doctor

Command What it does
repowise attribution status [--format json] Effective, repo and user values, why any differ, capture per agent, sidecar counts, and commits by label with coverage
repowise attribution backfill --agent claude-code,codex [--format json] Binds past commits from local transcripts; prints commits scanned, bound and coverage before and after
repowise attribution purge [--yes] Deletes the index labels and file rollups, the .repowise/attribution/ sidecar and the notes Repowise wrote locally. Git history, trailers and notes written by anything else stay
repowise doctor At capture: notes, checks the fetch refspec, the push refspec and notes.rewriteRef, and names the command for anything missing

Where it shows

Surface What you see
CLI repowise attribution status
REST GET /api/repos/{id}/commits?authorship=agent|human|unknown, GET /api/repos/{id}/commits/agent-trend (monthly counts per label, coverage, share)
Web Commits page: agent badges, an authorship filter and a 12-month trend strip
MCP get_context file cards: agent share and coverage, when the file has agent commits
Change Records A three-state provenance block per change. See CHANGES.md

Coverage and the share

Coverage is the fraction of commits with a known source (agent plus human_attested). The AI share is the agent fraction of those covered commits, always printed beside its coverage, for example "at least 40% of covered commits, coverage 62%". Below 30% coverage the share is withheld and only the count is shown.

Limits

  • Squash merges that drop trailers lose those markers. PR-level signals (bot PR author, branch names, PR body) need forge APIs and are outside the local reader.
  • Capture labels a commit only when a run of at least two consecutive substantive lines from one agent matches. One-line edits, lines repeated three or more times in a file, and lines two agents both claim stay unmatched.
  • Pending capture events expire after 14 days. Each update binds at most 50 new commits and resumes from where it stopped.
  • Capture sees edits made on this machine. Teammates' work reaches you through their own capture or through notes they push.