Skip to content

Commit c79badf

Browse files
committed
ci: block Co-Authored-By: <AI> trailers, recommend Assisted-By
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
1 parent 3dd87f3 commit c79badf

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: commit-trailers
2+
on:
3+
pull_request:
4+
merge_group:
5+
6+
permissions:
7+
contents: read
8+
pull-requests: read
9+
10+
jobs:
11+
no-ai-coauthor:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Reject AI Co-Authored-By trailers
15+
uses: actions/github-script@v7
16+
with:
17+
script: |
18+
const pr = context.payload.pull_request;
19+
if (!pr) return;
20+
const commits = await github.paginate(github.rest.pulls.listCommits, {
21+
owner: context.repo.owner,
22+
repo: context.repo.repo,
23+
pull_number: pr.number,
24+
});
25+
// Known AI coding agents that stamp a `Co-Authored-By:` trailer,
26+
// matched by their vendor email or distinctive bot login. We key on
27+
// bot identities (unambiguous), never on bare human names, so
28+
// legitimate human co-authors are never blocked.
29+
const AI_AGENTS = new RegExp([
30+
'anthropic\\.com', // Claude / Claude Code
31+
'copilot-swe-agent', // GitHub Copilot
32+
'\\+copilot@users\\.noreply', // GitHub Copilot
33+
'devin-ai-integration', // Devin (Cognition)
34+
'cursoragent|@cursor\\.com', // Cursor Agent
35+
'google-labs-jules', // Google Jules / Gemini
36+
'@aider\\.chat', // Aider
37+
'windsurf|codeium', // Windsurf / Codeium
38+
].join('|'), 'i');
39+
const coAuthorLine = /^\s*co-authored-by:.*$/gim;
40+
const offenders = commits
41+
.filter((c) =>
42+
(c.commit.message.match(coAuthorLine) || []).some((l) =>
43+
AI_AGENTS.test(l),
44+
),
45+
)
46+
.map((c) => c.sha.slice(0, 8));
47+
if (offenders.length === 0) {
48+
core.info('No AI Co-Authored-By trailers found.');
49+
return;
50+
}
51+
const msg = [
52+
`Commits ${offenders.join(', ')} carry a "Co-Authored-By: <AI agent>" trailer.`,
53+
'',
54+
'Under US copyright law (which governs CNCF projects) a Co-Authored-By',
55+
'trailer naming an AI agent can attribute rights over the code to its',
56+
'vendor. Use an informational "Assisted-By: <agent>" trailer instead — it',
57+
'discloses AI assistance without transferring authorship.',
58+
'',
59+
'Rationale: https://github.com/anthropics/claude-code/issues/66602',
60+
'',
61+
'Fix: rebase and amend the trailer, then force-push.',
62+
'Prevent it at source: set includeCoAuthoredBy: false in your Claude Code settings.',
63+
].join('\n');
64+
await core.summary.addRaw(msg).write();
65+
core.setFailed(msg);

0 commit comments

Comments
 (0)