Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/ai-contribution.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: AI Contribution Report

on:
push:
branches:
- main

jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Count AI-attributed commits
run: |
total=$(git log --oneline | wc -l | tr -d ' ')
cursor=$(git log --format="%B" | grep -i "co-author.*cursor" | wc -l | tr -d ' ')
claude=$(git log --format="%B" | grep -i "co-authored.*claude" | wc -l | tr -d ' ')
copilot=$(git log --format="%B" | grep -i "co-author.*copilot" | wc -l | tr -d ' ')
ai=$((cursor + claude + copilot))
human=$((total - ai))
Comment on lines +19 to +23

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 minor (bug): grep ... | wc -l counts matching lines, whereas total counts commits. Two problems follow:

  1. A single commit that carries more than one AI trailer (e.g. both Co-Authored-By: Claude and Co-authored-by: Cursor, which happens on hand-offs between tools) is counted once in total but once in each of cursor/claude/copilot. That inflates ai above the true count of AI-attributed commits and makes human=$((total - ai)) potentially negative, which then renders as a negative count and a negative percentage.
  2. grep -i "co-author.*cursor" matches on the whole commit body, so a prose mention (e.g. "discussed co-author roles with the Cursor team") is counted as a trailer.

To count commits rather than trailer lines, and to anchor on the trailer, consider matching per-commit. For example, count commits whose body contains the trailer:

cursor=$(git log --format="%H %(trailers:key=Co-authored-by,valueonly)" | grep -ic "cursor")

or iterate commits and grep each body once, so a commit is attributed at most once per tool.

🤖 Generated by Astra


echo "## AI Contribution Report" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Tool | Commits | Share |" >> "$GITHUB_STEP_SUMMARY"
echo "|------|---------|-------|" >> "$GITHUB_STEP_SUMMARY"
echo "| Cursor | $cursor | $(( cursor * 100 / total ))% |" >> "$GITHUB_STEP_SUMMARY"
echo "| Claude | $claude | $(( claude * 100 / total ))% |" >> "$GITHUB_STEP_SUMMARY"
echo "| Copilot | $copilot | $(( copilot * 100 / total ))% |" >> "$GITHUB_STEP_SUMMARY"
echo "| **AI total** | **$ai** | **$(( ai * 100 / total ))%** |" >> "$GITHUB_STEP_SUMMARY"
echo "| Human | $human | $(( human * 100 / total ))% |" >> "$GITHUB_STEP_SUMMARY"
Comment on lines +29 to +33

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 nit (other): Integer division truncates each share, so the per-row percentages will not sum to 100% (e.g. three rows at 33% each show 99%). If exactness matters for the summary, compute the human share as 100 - ai_share rather than independently, or round. Non-blocking.

🤖 Generated by Astra

echo "| **Total** | **$total** | 100% |" >> "$GITHUB_STEP_SUMMARY"
Comment on lines +29 to +34

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 minor (bug): Every Share cell divides by $total. On a repository with zero commits reachable from HEAD, total is 0 and $(( cursor * 100 / total )) aborts the step with a divide-by-zero. Unlikely on main today, but cheap to guard. Consider computing shares only when total > 0, e.g.:

if [ "$total" -eq 0 ]; then total=1; fi

(or skip the percentage column when there are no commits).

🤖 Generated by Astra

Loading