From 1e2065f4437a34df7d280c4590206e74ecfbe05a Mon Sep 17 00:00:00 2001 From: Ofer Affias Date: Mon, 10 Nov 2025 20:40:59 +0200 Subject: [PATCH 1/2] Add AI adoption tracking automation documentation and example Add comprehensive documentation for the AI adoption tracking automation that detects and labels PRs involving 40+ AI tools through rules files, commit co-authors, and PR authors. Includes the full automation manifest with patterns for detection and labeling. --- .../ai-adoption-tracking/README.md | 123 ++++ .../ai-copilot-labels.png | Bin 0 -> 34560 bytes .../ai_adoption_tracking.cm | 643 ++++++++++++++++++ 3 files changed, 766 insertions(+) create mode 100644 docs/automations/ai-adoption-tracking/README.md create mode 100644 docs/automations/ai-adoption-tracking/ai-copilot-labels.png create mode 100644 docs/downloads/automation-library/ai_adoption_tracking.cm diff --git a/docs/automations/ai-adoption-tracking/README.md b/docs/automations/ai-adoption-tracking/README.md new file mode 100644 index 00000000..e3d977e7 --- /dev/null +++ b/docs/automations/ai-adoption-tracking/README.md @@ -0,0 +1,123 @@ +--- +title: Automation - AI Adoption Tracking +description: Automatically track and label AI tool adoption in your repository +category: [analytics, ai] +--- +# AI Adoption Tracking + +Automatically detect and label PRs that involve AI tool usage to track AI adoption across your development workflow. + +**Supported AI Tools** (40+): Claude, Cursor, GitHub Copilot, Windsurf, Google Gemini, Aider, Qodo (PR-Agent), CodeRabbit, Devin AI, Amazon Q, and many more. + +![AI Adoption Tracking Labels](ai-copilot-labels.png) + +!!! info "Configuration Description" + Tracks three types of AI adoption based on [LinearB's AI Insights](https://linearb.helpdocs.io/article/n8q4ydqmkd-ai-insights): + + * **Rules File** - Detects AI configuration files (`.cursorrules`, `CLAUDE.md`, etc.) + * **Co-author** - Detects AI tools in commit co-author lines + * **PR Author** - Detects PRs created by AI bots + + Automation Actions: + + * Apply labels: `ai-used`, `ai-adoption-*`, and `ai-tool-*` + * Post explanatory comments + +!!! example "AI Adoption Tracking" + ```yaml+jinja + --8<-- "docs/downloads/automation-library/ai_adoption_tracking.cm" + ``` +
+ + [:octicons-download-24: Download this example as a CM file.](/downloads/automation-library/ai_adoption_tracking.cm){ .md-button } + +
+ +## How It Works + +### Rules File Detection + +The automation scans changed files for AI tool configuration patterns: + +| Tool | Configuration Files | +|------|-------------------| +| Claude | `CLAUDE.md` | +| Cursor | `.cursorrules`, `.cursor/rules/*.md` | +| GitHub Copilot | `.github/copilot-instructions.md`, `.github/*-instructions.md` | +| Windsurf | `.windsurfrules` | +| Gemini | `GEMINI.md` | +| Aider | `.aider.conf.yml` | + +When these files are added or modified, the PR is labeled with `ai-adoption-rules` and the specific tool label. + +### Co-author Detection + +The automation checks commit messages for AI co-authors using case-insensitive patterns: + +``` +Co-authored-by: Claude +Co-authored-by: GitHub Copilot +``` + +Pattern format: `[Cc]o-[Aa]uthored-[Bb]y:.*[Tt]oolName` + +This matches various capitalizations: +- `Co-authored-by: Claude` +- `co-authored-by: claude` +- `CO-AUTHORED-BY: CLAUDE` + +### PR Author Detection + +The automation identifies PRs created by AI bots: +- `claude[bot]` +- `github-copilot[bot]` +- `coderabbit[bot]` +- etc. + +## Customization + +### Track Additional Tools + +Add new tools by extending the `config` section: + +```yaml +config: + # Add custom tool detection + has_my_tool_rules: {{ files | match(regex=r/^\.mytool\/config\.yaml$/) | some }} + has_my_tool_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Mm]y[Tt]ool/) | some }} + + # Update any_ai_detected to include new tool + any_ai_detected: {{ ... or has_my_tool_rules or has_my_tool_coauthor }} +``` + +Then add corresponding automation rules: + +```yaml +automations: + ai_rules_my_tool: + if: + - {{ config.has_my_tool_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-tool-mytool' +``` + +### Disable Comments + +Remove `add-comment` actions to apply labels only without posting comments. + +### Track Specific Tools Only + +Remove automation rules for tools you don't want to track. + +## Additional Resources + +--8<-- "docs/snippets/general.md" + +**Related Automations**: + +* [Label PRs by Context](/automations/label-prs-by-context/) - Apply contextual labels to PRs +* [Track Code Experts](/automations/standard/explain-code-experts/) - Identify code ownership + +--8<-- "docs/snippets/automation-footer.md" diff --git a/docs/automations/ai-adoption-tracking/ai-copilot-labels.png b/docs/automations/ai-adoption-tracking/ai-copilot-labels.png new file mode 100644 index 0000000000000000000000000000000000000000..983af06ce096695878c9ac17df556022b79f80a9 GIT binary patch literal 34560 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 B=h6TG literal 0 HcmV?d00001 diff --git a/docs/downloads/automation-library/ai_adoption_tracking.cm b/docs/downloads/automation-library/ai_adoption_tracking.cm new file mode 100644 index 00000000..d903986f --- /dev/null +++ b/docs/downloads/automation-library/ai_adoption_tracking.cm @@ -0,0 +1,643 @@ +# -*- mode: yaml -*- +# This CM automation tracks AI tool adoption in your repository +# Based on: https://linearb.helpdocs.io/article/n8q4ydqmkd-ai-insights +# +# Adoption Types: +# - Rules File: AI tool configuration file added/modified +# - Co-author: AI tool contributed as co-author in commits +# - PR Author: AI tool or bot created the PR + +manifest: + version: 1.0 + +# Custom expressions for AI tool detection +config: + # Rule file patterns for each AI tool + has_aider_rules: {{ files | match(regex=r/(^|.*\/).aider.conf.yml$/) | some }} + has_amazonq_rules: {{ files | match(regex=r/^\.amazonq\/rules\/[^\/]+\.md$/) | some }} + has_augmentcode_rules: {{ files | match(regex=r/^\.augment\/rules\/[^\/]+\.md$/) | some }} + has_claude_rules: {{ files | match(regex=r/(^|.*\/)CLAUDE\.md$/) | some }} + has_cursor_rules: {{ files | match(regex=r/(^|.*\/)\.cursorrules$|^\.cursor\/rules\/[^\/]+\.md$/) | some }} + has_customtool_rules: {{ files | match(regex=r/(^|.*\/)\.customtool$|^\.custom\/rules\/[^\/]+\.rules$/) | some }} + has_firebase_rules: {{ files | match(regex=r/(^|.*\/).idx\/airules.md$/) | some }} + has_gemini_rules: {{ files | match(regex=r/(^|.*\/)GEMINI\.md$/) | some }} + has_github_copilot_rules: {{ files | match(regex=r/^\.github\/copilot-instructions\.md$|^\.github\/[^\/]+-instructions\.md$/) | some }} + has_goose_rules: {{ files | match(regex=r/(^|.*\/)\.goosehints$/) | some }} + has_jetbrains_junie_rules: {{ files | match(regex=r/^\.junie\/[^\/]+\.md$/) | some }} + has_kilocode_rules: {{ files | match(regex=r/^\.kilocode\/rules\/[^\/]+\.md$/) | some }} + has_kiro_rules: {{ files | match(regex=r/^\.kiro\/steering\/[^\/]+\.md$/) | some }} + has_openai_rules: {{ files | match(regex=r/(^|.*\/)AGENT\.md$|(^|.*\/)AGENTS\.md$/) | some }} + has_openhands_rules: {{ files | match(regex=r/^\.openhands\/microagents\/[^\/]+\.md$/) | some }} + has_warp_rules: {{ files | match(regex=r/(^|.*\/)WARP\.md$/) | some }} + has_windsurf_rules: {{ files | match(regex=r/(^|.*\/)\.windsurfrules$/) | some }} + has_zed_rules: {{ files | match(regex=r/(^|.*\/)\.rules$/) | some }} + + # Co-author detection patterns (check commit messages) + has_aider_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Aa]ider/) | some }} + has_aikido_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Aa]ikido/) | some }} + has_amazonq_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Aa]mazon.*[Qq]/) | some }} + has_atlassian_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]ode.*[Rr]eviewer/) | some }} + has_bito_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Bb]ito/) | some }} + has_claude_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]laude/) | some }} + has_codeant_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]odeant/) | some }} + has_codegen_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]odegen/) | some }} + has_coderabbit_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]ode[Rr]abbit/) | some }} + has_codota_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]odota/) | some }} + has_cubic_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]ubic/) | some }} + has_cursor_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]ursor/) | some }} + has_devin_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Dd]evin/) | some }} + has_ellipsis_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ee]llipsis/) | some }} + has_factory_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ff]actory/) | some }} + has_fine_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ff]ine/) | some }} + has_gemini_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]emini/) | some }} + has_github_copilot_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Cc]opilot/) | some }} + has_gitlab_duo_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]it[Ll]ab.*[Dd]uo/) | some }} + has_gitstream_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]itstream/) | some }} + has_google_jules_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]oogle.*[Jj]ules/) | some }} + has_graphite_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]raphite/) | some }} + has_greptile_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Gg]reptile/) | some }} + has_jazzberry_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*([Pp]rophet|[Jj]azzberry)/) | some }} + has_jetbrains_junie_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Jj]et[Bb]rains.*[Jj]unie/) | some }} + has_korbit_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Kk]orbit/) | some }} + has_meticulous_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Mm]eticulous/) | some }} + has_openai_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*([Cc]odex|[Cc]hat[Gg][Pp][Tt])/) | some }} + has_opencode_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Oo]pencode/) | some }} + has_qodo_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*(pr.agent|[Qq]odo|[Cc]odium)/) | some }} + has_replit_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Rr]eplit/) | some }} + has_rovo_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Rr]ovo/) | some }} + has_sourcegraph_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ss]ourcegraph/) | some }} + has_sourcery_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ss]ourcery/) | some }} + has_sweep_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ss]weep/) | some }} + has_tabnine_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Tt]abnine/) | some }} + has_tusk_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Tt]usk/) | some }} + has_whatthediff_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ww]hat.*[Dd]iff/) | some }} + has_windsurf_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ww]indsurf/) | some }} + + # PR Author detection patterns + is_claude_author: {{ pr.author | match(regex=r/(^claude$|claude ai|claude ai assistant|claude code|claude github action|claude\[bot\])/i) }} + is_coderabbit_author: {{ pr.author | match(regex=r/coderabbit/i) }} + is_cursor_author: {{ pr.author | match(regex=r/(-cursor|^cursor)/i) }} + is_devin_author: {{ pr.author | match(regex=r/(devin ai|devin-ai)/i) }} + is_fine_author: {{ pr.author | match(regex=r/(^fine-agent|^fine-ai)/i) }} + is_gemini_author: {{ pr.author | match(regex=r/(^gemini$|^gemini-|gemini-code-assist)/i) }} + is_github_copilot_author: {{ pr.author | match(regex=r/copilot/i) }} + is_gitstream_author: {{ pr.author | match(regex=r/gitstream/i) }} + is_greptile_author: {{ pr.author | match(regex=r/greptile/i) }} + is_qodo_author: {{ pr.author | match(regex=r/(^pr agent|^pr-agent|^pr_agent|codium pr-agent|pr-ia-20240430|qodo\b|s-qce-pr-reviewer)/i) }} + + # General AI detection - true if ANY AI tool/method is detected + any_ai_detected: {{ has_aider_rules or has_amazonq_rules or has_augmentcode_rules or has_claude_rules or has_cursor_rules or has_customtool_rules or has_firebase_rules or has_gemini_rules or has_github_copilot_rules or has_goose_rules or has_jetbrains_junie_rules or has_kilocode_rules or has_kiro_rules or has_openai_rules or has_openhands_rules or has_warp_rules or has_windsurf_rules or has_zed_rules or has_aider_coauthor or has_aikido_coauthor or has_amazonq_coauthor or has_atlassian_coauthor or has_bito_coauthor or has_claude_coauthor or has_codeant_coauthor or has_codegen_coauthor or has_coderabbit_coauthor or has_codota_coauthor or has_cubic_coauthor or has_cursor_coauthor or has_devin_coauthor or has_ellipsis_coauthor or has_factory_coauthor or has_fine_coauthor or has_gemini_coauthor or has_github_copilot_coauthor or has_gitlab_duo_coauthor or has_gitstream_coauthor or has_google_jules_coauthor or has_graphite_coauthor or has_greptile_coauthor or has_jazzberry_coauthor or has_jetbrains_junie_coauthor or has_korbit_coauthor or has_meticulous_coauthor or has_openai_coauthor or has_opencode_coauthor or has_qodo_coauthor or has_replit_coauthor or has_rovo_coauthor or has_sourcegraph_coauthor or has_sourcery_coauthor or has_sweep_coauthor or has_tabnine_coauthor or has_tusk_coauthor or has_whatthediff_coauthor or has_windsurf_coauthor or is_claude_author or is_coderabbit_author or is_cursor_author or is_devin_author or is_fine_author or is_gemini_author or is_github_copilot_author or is_gitstream_author or is_greptile_author or is_qodo_author }} + +automations: + # ============================================================================= + # RULES FILE ADOPTION - Label PRs that add/modify AI tool configuration files + # ============================================================================= + + label_aider_rules: + if: + - {{ config.has_aider_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-aider' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Aider Rules File** + + This PR adds or modifies Aider configuration files, indicating rules-based AI adoption. + + label_amazonq_rules: + if: + - {{ config.has_amazonq_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-amazon-q' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Amazon Q Rules File** + + This PR adds or modifies Amazon Q configuration files, indicating rules-based AI adoption. + + label_augmentcode_rules: + if: + - {{ config.has_augmentcode_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-augmentcode' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: AugmentCode Rules File** + + This PR adds or modifies AugmentCode configuration files, indicating rules-based AI adoption. + + label_claude_rules: + if: + - {{ config.has_claude_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-claude' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Claude Rules File** + + This PR adds or modifies Claude/Claude Code configuration files, indicating rules-based AI adoption. + + label_cursor_rules: + if: + - {{ config.has_cursor_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-cursor' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Cursor Rules File** + + This PR adds or modifies Cursor configuration files, indicating rules-based AI adoption. + + label_firebase_rules: + if: + - {{ config.has_firebase_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-firebase-studio' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Firebase Studio Rules File** + + This PR adds or modifies Firebase Studio AI configuration files, indicating rules-based AI adoption. + + label_gemini_rules: + if: + - {{ config.has_gemini_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-gemini' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Google Gemini Rules File** + + This PR adds or modifies Google Gemini configuration files, indicating rules-based AI adoption. + + label_github_copilot_rules: + if: + - {{ config.has_github_copilot_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-github-copilot' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: GitHub Copilot Rules File** + + This PR adds or modifies GitHub Copilot instruction files, indicating rules-based AI adoption. + + label_goose_rules: + if: + - {{ config.has_goose_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-goose' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Goose Rules File** + + This PR adds or modifies Goose configuration files, indicating rules-based AI adoption. + + label_jetbrains_junie_rules: + if: + - {{ config.has_jetbrains_junie_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-jetbrains-junie' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: JetBrains Junie Rules File** + + This PR adds or modifies JetBrains Junie configuration files, indicating rules-based AI adoption. + + label_kilocode_rules: + if: + - {{ config.has_kilocode_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-kilocode' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Kilo Code Rules File** + + This PR adds or modifies Kilo Code configuration files, indicating rules-based AI adoption. + + label_kiro_rules: + if: + - {{ config.has_kiro_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-kiro' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Kiro Rules File** + + This PR adds or modifies Kiro steering files, indicating rules-based AI adoption. + + label_openai_rules: + if: + - {{ config.has_openai_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-openai-codex' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: OpenAI Codex Rules File** + + This PR adds or modifies OpenAI Codex configuration files, indicating rules-based AI adoption. + + label_openhands_rules: + if: + - {{ config.has_openhands_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-openhands' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Open Hands Rules File** + + This PR adds or modifies Open Hands microagent files, indicating rules-based AI adoption. + + label_warp_rules: + if: + - {{ config.has_warp_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-warp' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Warp Rules File** + + This PR adds or modifies Warp configuration files, indicating rules-based AI adoption. + + label_windsurf_rules: + if: + - {{ config.has_windsurf_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-windsurf' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Windsurf Rules File** + + This PR adds or modifies Windsurf configuration files, indicating rules-based AI adoption. + + label_zed_rules: + if: + - {{ config.has_zed_rules }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-rules' + - action: add-label@v1 + args: + label: 'ai-tool-zed' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Zed Rules File** + + This PR adds or modifies Zed configuration files, indicating rules-based AI adoption. + + # ============================================================================= + # CO-AUTHOR ADOPTION - Label PRs where AI tools contributed as co-authors + # ============================================================================= + + label_aider_coauthor: + if: + - {{ config.has_aider_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-aider' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Aider Co-author** + + This PR includes commits with Aider as a co-author, indicating collaborative AI adoption. + + label_claude_coauthor: + if: + - {{ config.has_claude_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-claude' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Claude Co-author** + + This PR includes commits with Claude as a co-author, indicating collaborative AI adoption. + + label_cursor_coauthor: + if: + - {{ config.has_cursor_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-cursor' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Cursor Co-author** + + This PR includes commits with Cursor as a co-author, indicating collaborative AI adoption. + + label_github_copilot_coauthor: + if: + - {{ config.has_github_copilot_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-github-copilot' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: GitHub Copilot Co-author** + + This PR includes commits with GitHub Copilot as a co-author, indicating collaborative AI adoption. + + label_gemini_coauthor: + if: + - {{ config.has_gemini_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-gemini' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Google Gemini Co-author** + + This PR includes commits with Google Gemini as a co-author, indicating collaborative AI adoption. + + label_qodo_coauthor: + if: + - {{ config.has_qodo_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-qodo' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Qodo Co-author** + + This PR includes commits with Qodo (formerly Codium/PR-Agent) as a co-author, indicating collaborative AI adoption. + + label_devin_coauthor: + if: + - {{ config.has_devin_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-devin' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Devin AI Co-author** + + This PR includes commits with Devin AI as a co-author, indicating collaborative AI adoption. + + label_windsurf_coauthor: + if: + - {{ config.has_windsurf_coauthor }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-coauthor' + - action: add-label@v1 + args: + label: 'ai-tool-windsurf' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Windsurf Co-author** + + This PR includes commits with Windsurf as a co-author, indicating collaborative AI adoption. + + # Add more co-author automations for other tools as needed... + + # ============================================================================= + # PR AUTHOR ADOPTION - Label PRs created by AI tools/bots + # ============================================================================= + + label_claude_author: + if: + - {{ config.is_claude_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-claude' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Claude PR Author** + + This PR was created by Claude, indicating AI-driven PR creation. + + label_cursor_author: + if: + - {{ config.is_cursor_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-cursor' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Cursor PR Author** + + This PR was created by Cursor, indicating AI-driven PR creation. + + label_github_copilot_author: + if: + - {{ config.is_github_copilot_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-github-copilot' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: GitHub Copilot PR Author** + + This PR was created by GitHub Copilot, indicating AI-driven PR creation. + + label_devin_author: + if: + - {{ config.is_devin_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-devin' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Devin AI PR Author** + + This PR was created by Devin AI, indicating AI-driven PR creation. + + label_qodo_author: + if: + - {{ config.is_qodo_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-qodo' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: Qodo PR Author** + + This PR was created by Qodo (formerly Codium/PR-Agent), indicating AI-driven PR creation. + + label_coderabbit_author: + if: + - {{ config.is_coderabbit_author }} + run: + - action: add-label@v1 + args: + label: 'ai-adoption-pr-author' + - action: add-label@v1 + args: + label: 'ai-tool-coderabbit' + - action: add-comment@v1 + args: + comment: | + 🤖 **AI Adoption Detected: CodeRabbit PR Author** + + This PR was created by CodeRabbit, indicating AI-driven PR creation. + + # ============================================================================= + # GENERAL AI USAGE - Label any PR where AI was detected + # ============================================================================= + + label_ai_used: + if: + - {{ config.any_ai_detected }} + run: + - action: add-label@v1 + args: + label: 'ai-used' From a0df2bea41b31525964dd5e86bd26744de5d6181 Mon Sep 17 00:00:00 2001 From: Ofer Affias Date: Tue, 11 Nov 2025 11:09:02 +0200 Subject: [PATCH 2/2] Remove case-insensitive flags from AI author regex patterns --- .../ai_adoption_tracking.cm | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/downloads/automation-library/ai_adoption_tracking.cm b/docs/downloads/automation-library/ai_adoption_tracking.cm index d903986f..877a0820 100644 --- a/docs/downloads/automation-library/ai_adoption_tracking.cm +++ b/docs/downloads/automation-library/ai_adoption_tracking.cm @@ -74,16 +74,16 @@ config: has_windsurf_coauthor: {{ branch.commits.messages | match(regex=r/[Cc]o-[Aa]uthored-[Bb]y:.*[Ww]indsurf/) | some }} # PR Author detection patterns - is_claude_author: {{ pr.author | match(regex=r/(^claude$|claude ai|claude ai assistant|claude code|claude github action|claude\[bot\])/i) }} - is_coderabbit_author: {{ pr.author | match(regex=r/coderabbit/i) }} - is_cursor_author: {{ pr.author | match(regex=r/(-cursor|^cursor)/i) }} - is_devin_author: {{ pr.author | match(regex=r/(devin ai|devin-ai)/i) }} - is_fine_author: {{ pr.author | match(regex=r/(^fine-agent|^fine-ai)/i) }} - is_gemini_author: {{ pr.author | match(regex=r/(^gemini$|^gemini-|gemini-code-assist)/i) }} - is_github_copilot_author: {{ pr.author | match(regex=r/copilot/i) }} - is_gitstream_author: {{ pr.author | match(regex=r/gitstream/i) }} - is_greptile_author: {{ pr.author | match(regex=r/greptile/i) }} - is_qodo_author: {{ pr.author | match(regex=r/(^pr agent|^pr-agent|^pr_agent|codium pr-agent|pr-ia-20240430|qodo\b|s-qce-pr-reviewer)/i) }} + is_claude_author: {{ pr.author | match(regex=r/(^claude$|claude ai|claude ai assistant|claude code|claude github action|claude\[bot\])/) }} + is_coderabbit_author: {{ pr.author | match(regex=r/coderabbit/) }} + is_cursor_author: {{ pr.author | match(regex=r/(-cursor|^cursor)/) }} + is_devin_author: {{ pr.author | match(regex=r/(devin ai|devin-ai)/) }} + is_fine_author: {{ pr.author | match(regex=r/(^fine-agent|^fine-ai)/) }} + is_gemini_author: {{ pr.author | match(regex=r/(^gemini$|^gemini-|gemini-code-assist)/) }} + is_github_copilot_author: {{ pr.author | match(regex=r/copilot/) }} + is_gitstream_author: {{ pr.author | match(regex=r/gitstream/) }} + is_greptile_author: {{ pr.author | match(regex=r/greptile/) }} + is_qodo_author: {{ pr.author | match(regex=r/(^pr agent|^pr-agent|^pr_agent|codium pr-agent|pr-ia-20240430|qodo\b|s-qce-pr-reviewer)/) }} # General AI detection - true if ANY AI tool/method is detected any_ai_detected: {{ has_aider_rules or has_amazonq_rules or has_augmentcode_rules or has_claude_rules or has_cursor_rules or has_customtool_rules or has_firebase_rules or has_gemini_rules or has_github_copilot_rules or has_goose_rules or has_jetbrains_junie_rules or has_kilocode_rules or has_kiro_rules or has_openai_rules or has_openhands_rules or has_warp_rules or has_windsurf_rules or has_zed_rules or has_aider_coauthor or has_aikido_coauthor or has_amazonq_coauthor or has_atlassian_coauthor or has_bito_coauthor or has_claude_coauthor or has_codeant_coauthor or has_codegen_coauthor or has_coderabbit_coauthor or has_codota_coauthor or has_cubic_coauthor or has_cursor_coauthor or has_devin_coauthor or has_ellipsis_coauthor or has_factory_coauthor or has_fine_coauthor or has_gemini_coauthor or has_github_copilot_coauthor or has_gitlab_duo_coauthor or has_gitstream_coauthor or has_google_jules_coauthor or has_graphite_coauthor or has_greptile_coauthor or has_jazzberry_coauthor or has_jetbrains_junie_coauthor or has_korbit_coauthor or has_meticulous_coauthor or has_openai_coauthor or has_opencode_coauthor or has_qodo_coauthor or has_replit_coauthor or has_rovo_coauthor or has_sourcegraph_coauthor or has_sourcery_coauthor or has_sweep_coauthor or has_tabnine_coauthor or has_tusk_coauthor or has_whatthediff_coauthor or has_windsurf_coauthor or is_claude_author or is_coderabbit_author or is_cursor_author or is_devin_author or is_fine_author or is_gemini_author or is_github_copilot_author or is_gitstream_author or is_greptile_author or is_qodo_author }}