Skip to content

Commit 118ecdf

Browse files
authored
docs: add a blog post on AI commit attribution policies (#52)
1 parent 406e9b8 commit 118ecdf

1 file changed

Lines changed: 163 additions & 0 deletions

File tree

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
---
2+
date:
3+
created: 2026-10-11
4+
readtime: 4
5+
slug: ai-commit-attribution-policy
6+
description: >-
7+
AI coding agents stamp their own trailers on your commits. Open source has
8+
answered that three ways; here is how to enforce whichever one your project
9+
chose, on every commit.
10+
categories:
11+
- UPDATES
12+
tags:
13+
- commit-check
14+
- ai
15+
- governance
16+
authors:
17+
- shenxianpeng
18+
---
19+
20+
# Your AI agent signs your commits. Does your project have a policy for that?
21+
22+
Ask Claude Code or Cursor to commit for you and, by default, the commit comes
23+
out stamped:
24+
25+
```text
26+
fix: resolve race condition in the cache
27+
28+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29+
```
30+
31+
Whether that line belongs in your history is a policy question, and open
32+
source has already given three different answers.
33+
34+
<!-- more -->
35+
36+
| Position | Who takes it |
37+
|---|---|
38+
| No AI trailers in the history; disclose in the pull request instead | [Kubernetes](https://www.kubernetes.dev/docs/guide/pull-requests/) |
39+
| AI is welcome, but say so with a trailer, and never credit the tool as a person | [Linux kernel](https://docs.kernel.org/process/coding-assistants.html) and [Fedora](https://docs.fedoraproject.org/en-US/council/policy/ai-policy/) (`Assisted-by:`) |
40+
| The tool can be credited as a co-author | [pytest](https://docs.pytest.org/en/stable/contributing.html) (`Co-authored-by:`) and the [ASF](https://www.apache.org/legal/generative-tooling.html) (`Generated-by:` or `Co-authored-by:`) |
41+
42+
The kernel adds one hard rule on top: an AI agent must never add a
43+
`Signed-off-by:` line, because only a person can certify the
44+
[DCO](https://developercertificate.org/).
45+
46+
The trouble is that all of these are policies written in contributor guidelines
47+
and enforced by a reviewer's eyes. Nobody reads trailers carefully on the
48+
twentieth pull request of the day.
49+
50+
## Making the policy a check
51+
52+
[Commit Check](https://github.com/commit-check/commit-check) is open-source
53+
commit policy as code for teams and AI agents: the rules for commit messages,
54+
branch names, authors and sign-offs live in one config file and are enforced in
55+
hooks, CI and pull requests. Since [v2.18](../../changelog.md#v2180) it can
56+
enforce each of those positions from `cchk.toml`:
57+
58+
```toml
59+
[commit]
60+
ai_attribution = "forbid" # or "disclose", or "ignore" (the default)
61+
```
62+
63+
With `forbid`, the stamped commit above fails:
64+
65+
```text
66+
CC013 ai-attribution check failed ==> Claude Code
67+
AI attribution is forbidden in this project — detected: Claude Code
68+
Suggest: This project does not accept AI attribution in commit messages. Remove the AI trailer lines and re-commit.
69+
Docs: https://commit-check.com/rules/#cc013
70+
```
71+
72+
With `disclose`, the same commit fails for a different reason, and the failure
73+
tells you exactly what to write instead:
74+
75+
```text
76+
CC014 ai-disclosure check failed ==> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
77+
AI assistance is not disclosed with Assisted-by or Generated-by — detected: Claude Code
78+
Suggest: Disclose the tool with "Assisted-by: Claude Opus 5"
79+
Docs: https://commit-check.com/rules/#cc014
80+
81+
CC015 ai-co-author check failed ==> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82+
An AI tool is credited as a co-author: Claude Code
83+
Suggest: Use "Assisted-by: Claude Opus 5" in place of the co-author line
84+
Docs: https://commit-check.com/rules/#cc015
85+
```
86+
87+
A third rule, [CC016](../../rules.md#cc016), rejects a sign-off by the tool.
88+
Only a person can certify the DCO, so no list of accepted trailers makes that
89+
sign-off acceptable. Each of the three rules can be
90+
[demoted to a warning](../../configuration.md#report-a-rule-without-enforcing-it)
91+
on its own, so you can roll the policy out gently.
92+
93+
The third position takes one more line: list `Co-authored-by` in
94+
[`ai_disclosure_trailers`](../../guides/policies.md#choosing-the-format), and the
95+
co-author line counts as the disclosure. CC016 still refuses the tool's
96+
sign-off.
97+
98+
The detection covers co-author and sign-off lines that name Claude Code, GitHub
99+
Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby or a model, and
100+
vendor marks such as "Generated with Claude Code". It matches the tools'
101+
noreply addresses, so a human co-author who happens to be called Claude is left
102+
alone. [CC013](../../rules.md#cc013) keeps the current list.
103+
104+
## The fix comes with the failure
105+
106+
With `--format json`, the failing checks carry the corrected message, so a
107+
script or an agent can apply it without interpreting anything:
108+
109+
```json
110+
"fix": "fix: resolve race condition in the cache\n\nAssisted-by: Claude Opus 5"
111+
```
112+
113+
Since [v2.18.3](../../changelog.md#v2183), `--fix` applies it for you. Give it
114+
the message file, or give the pre-commit hook
115+
[`args: [--fix]`](../../guides/pre-commit.md#fixing-the-message-instead-of-rejecting-it),
116+
and the co-author line is rewritten as the disclosure before the commit is
117+
recorded:
118+
119+
```console
120+
$ commit-check -m --fix msg.txt
121+
✎ fixed the commit message: CC014 ai-disclosure
122+
$ cat msg.txt
123+
fix: resolve race condition in the cache
124+
125+
Assisted-by: Claude Opus 5
126+
```
127+
128+
That is also the point of the [MCP server](../../guides/mcp.md): the agent asks
129+
for your rules before it commits, and writes the disclosure your project wants
130+
in the first place.
131+
132+
## Run it where it cannot be skipped
133+
134+
The same `cchk.toml` drives a pre-commit hook, a GitHub Action, a GitHub App
135+
and a plain CLI for any other CI, so the policy a developer sees locally is the
136+
one the pull request is checked against. Make that check required in the
137+
branch's ruleset or branch protection, and a commit that fails it cannot be
138+
merged. [Where to run it](../../guides/integrations.md) walks through each
139+
setup.
140+
141+
To try the disclosure policy without writing a config file:
142+
143+
```bash
144+
pip install commit-check
145+
printf 'fix: resolve race condition\n\nAssisted-by: Claude Opus 5\n' | CCHK_AI_ATTRIBUTION=disclose commit-check -m
146+
```
147+
148+
## What it cannot do
149+
150+
This checks disclosure, not authorship. It catches a commit that says it was
151+
AI-assisted; it cannot catch one that was AI-assisted and says nothing. Against
152+
a policy of "no AI contributions at all", it is an honesty check for
153+
contributors who already follow the rules, not a detector. For the far more
154+
common policy, "tell us when you used it, and in this format", it turns a
155+
paragraph in CONTRIBUTING into a check that runs on every commit.
156+
157+
The rules, with examples, are in the [rules reference](../../rules.md#cc013),
158+
and the [policy guide](../../guides/policies.md#ai-attribution) walks through
159+
each setting.
160+
161+
Which of the three positions does your project take, and is it written down
162+
anywhere yet? Tell us in
163+
[Discussions](https://github.com/commit-check/commit-check/discussions).

0 commit comments

Comments
 (0)