Browse documentation
Docs
AI attribution
How FeatureFactory tells AI from human - and what it can't tell you.
The key framing: detected AI share is a floor, not a ceiling
FeatureFactory's attribution system is honest about its limits. When it detects that a commit is AI-generated, it attributes 100% of that commit's non-excluded lines to AI. But the reverse is not symmetric: the absence of a detected signal does not mean the commit is human-written. Agents that do not leave any registered signal will be counted as human.
This means the AI share percentage on your dashboard is a lower bound. The actual AI contribution may be higher. Instrumenting your agents (see below) is the only way to close that gap.
Bottom line
If the AI share reads 30%, at least 30% of your tracked lines came from AI. It could be more. It will not be less, as long as your agents are instrumented.
Tier 1 - Deterministic detection
Tier 1 runs on every commit and PR. It matches against agent identities registered for your team. Signal kinds are checked in precedence order - first match wins.
bot_account
Commit or PR author login equals a registered pattern (case-insensitive)
Result: 100% AI, full confidence
github-actions[bot]renovate[bot]devin-ai-integration[bot]committer_email_pattern
Author email matches an fnmatch glob registered for the team
Result: 100% AI, full confidence
*@customers.devin.ai*@codegen.shcoauthor_trailer
A Co-Authored-By trailer line in the commit message contains the pattern
Result: AI-assisted (mixed if human author also present)
Co-Authored-By: Claude <noreply@anthropic.com>Co-Authored-By: github-copilot <copilot@github.com>message_marker
Commit message body contains the pattern (case-insensitive substring)
Result: AI-assisted (mixed if human author also present)
Generated by Claude CodeCursor AIagent_pr_flag
PR payload dot-path equals a registered value (squash-merge fallback only)
Result: 100% AI, full confidence
performed_via_github_app.slug=copilot-swe-agentpayload user.type=Bot
GitHub marks the PR author as a Bot in the payload (no identity row needed)
Result: 100% AI, confidence 0.90 (tool unlabeled)
Any GitHub Bot account not explicitly registeredMixed-commit semantics
A "mixed" commit is one where a trailer or message marker indicates an agent was involved, but the commit also has a human author login (not itself a bot, not ending in [bot]).
In this case:
- -All non-excluded lines in the commit are still attributed to AI. The agent co-authored; line-level splits are not reliable enough to do better.
- -The method is recorded as
mixedinstead oftrailerormessage_marker. - -Confidence is reduced: identity confidence minus 0.15, floored at 0.50. The human may have materially edited the output, so certainty drops.
- -The evidence blob records the author login and a note: "detected AI share is a floor."
Squash-merge fallback
Squash merges collapse the branch history into a single new commit, which means per-commit trailers are lost and the commit-to-PR linkage can be empty. When a PR has no linked commits, detection falls back to PR-level signals checked in this order:
- 1.bot_account - the PR author login matches a registered bot identity.
- 2.agent_pr_flag - a payload dot-path check on the PR payload (e.g.
performed_via_github_app.slug=copilot-swe-agent). - 3.GitHub Bot type -
user.type === 'Bot'in the payload. Confidence 0.90, tool unlabeled. - 4.Merge commit message - trailer and marker matchers run against the
merge_commit_messagefield in the PR payload, with the same mixed semantics as commits.
Lines for the squash fallback come from the PR's own file list, filtered by the same exclusion rules as commits (tests, vendor, lockfiles excluded).
Confidence meanings
Confidence is a number stored per attribution row. It reflects how certain the system is that the detected signal means what it says - not how certain it is that the code is AI-generated in general.
Tier 1 deterministic
Bot account or email pattern match. The signal is unambiguous - the author IS a registered bot or an email pattern specifically set up for agents.
Tier 1 mixed
Trailer or marker detected but a human author is also present. The agent co-authored but a human may have edited the output. Confidence is identity confidence minus 0.15, floored at 0.50.
Tier 2 LLM heuristic
No Tier 1 signal found. An LLM analyzed the diff and flagged it as likely AI-generated. Model confidence is clamped to [0.30, 0.70] regardless of what the model returns - never reported as high-confidence.
No attribution
Tier 1 found nothing and Tier 2 either did not run or returned is_ai_generated: false. The commit is counted as human.
Tier 2 - LLM heuristic (optional)
When Tier 1 finds no signal and the team has the ai_attribution_heuristic_enabled setting turned on, FeatureFactory runs a Tier 2 LLM pass on commits that have countable, non-excluded lines.
The LLM receives a diff excerpt (up to ~20K characters of counted files) and returns a structured response: is_ai_generated, ai_percent, tool_guess, reasoning, and confidence.
Guardrails on Tier 2 results:
- -Model confidence is clamped to [0.30, 0.70]. Tier 2 results are never presented as high-confidence.
- -Tool name is only surfaced when clamped confidence is at or above 0.50. Below that threshold the tool field stays null.
- -The evidence blob always records that a heuristic was run, whether the result was positive or negative, so you can audit the decision.
- -Merge commits and commits with zero countable lines skip Tier 2 entirely.
PR-level rollup
Pull request attribution is a line-weighted rollup over the PR's non-merge commits:
- -
ai_lines= sum of (commit percent_ai_lines x commit counted lines) across all non-merge commits. - -
percent_ai_lines= ai_lines / (ai_lines + human_lines). Null when the PR has zero counted lines. - -Method is the commit method contributing the most AI lines. When two distinct methods tie, the PR method becomes
mixed. - -Tool name is the tool contributing the most AI lines, or null when there is no clear single leader (a tie would be dishonest to resolve arbitrarily).
- -Confidence is the AI-lines-weighted average of contributing commit confidences.
How to instrument your agents
The most reliable way to get accurate attribution is to configure your agents to leave a Co-Authored-By trailer on every commit they produce. FeatureFactory matches these against registered coauthor_trailer identities.
Commit trailer format
Git trailers go at the end of the commit message, separated from the body by a blank line:
feat: add checkout flow
Implement the cart-to-order pipeline including payment validation,
stock reservation, and confirmation email dispatch.
Co-Authored-By: Claude Code <noreply@anthropic.com>Common agent examples
| Agent / tool | Suggested trailer | Register pattern as |
|---|---|---|
| Claude Code | Co-Authored-By: Claude Code <noreply@anthropic.com> | noreply@anthropic.com |
| GitHub Copilot | Co-Authored-By: GitHub Copilot <copilot@github.com> | copilot@github.com |
| Cursor | Co-Authored-By: Cursor <cursor-ai@cursor.sh> | cursor-ai@cursor.sh |
| Custom/internal agent | Co-Authored-By: My Agent <agent@internal> | agent@internal |
Bot accounts
If your agent commits under its own GitHub account (common with Devin, Copilot Workspace, and similar autonomous agents), register the login as a bot_account identity instead. This gives higher confidence than trailer matching because the author identity is unambiguous.
# Devin-style bot account
Login: devin-ai-integration[bot]
Kind: bot_account
# GitHub App bot
Login: copilot-swe-agent[bot]
Kind: bot_accountEmail pattern matching
For agents that always commit from a predictable email domain but with varying usernames, use a committer_email_pattern identity with a fnmatch glob:
# Matches any address ending in @customers.devin.ai
Pattern: *@customers.devin.ai
Kind: committer_email_patternWas this article helpful?
Your response enters the same customer insight queue used by product feedback.