#!/bin/sh # Flags Co-Authored-By trailers with Claude/Anthropic attribution in PR commits. # The hive convention in /knowledge/hive-rules.md forbids these trailers. # # Pattern is loose (case-insensitive, matches `claude`, `anthropic`, or # `noreply@anthropic.com` anywhere after `co-authored-by`) to cover variants # like `Co-Authored-By: Claude Sonnet 4.5 `. # # Scope is the PR's commits (BASE..HEAD), not entire history — old commits # must not fail the build. set -eu if [ -n "${GITHUB_BASE_REF:-}" ]; then base="origin/${GITHUB_BASE_REF}" else base="origin/main" fi # actions/checkout@v3 fetches the PR head but may not fetch the base branch if ! git rev-parse --verify "$base" >/dev/null 2>&1; then branch="${base#origin/}" git fetch origin "$branch" 2>/dev/null || true if ! git rev-parse --verify "$base" >/dev/null 2>&1; then base="origin/main" git fetch origin main 2>/dev/null || base="HEAD~10" fi fi commits="$(git log --reverse --format='%H' "${base}..HEAD" 2>/dev/null || true)" if [ -z "$commits" ]; then exit 0 fi hits="" for sha in $commits; do msg="$(git log -1 --format='%B' "$sha")" if printf '%s\n' "$msg" | grep -qiE 'co-authored-by.*claude|co-authored-by.*anthropic|co-authored-by.*noreply@anthropic\.com'; then subject="$(git log -1 --format='%s' "$sha")" hits="${hits}${sha}|${subject} " fi done if [ -n "$hits" ]; then printf '%s' "$hits" | while IFS='|' read -r sha subject; do [ -z "$sha" ] && continue short_sha="$(printf '%s' "$sha" | cut -c1-8)" printf '::error title=Attribution trailer found in %s::%s — commit carries a Co-Authored-By trailer with Claude/Anthropic attribution, forbidden by /knowledge/hive-rules.md\n' \ "$short_sha" "$subject" done count="$(printf '%s' "$hits" | grep -c '|' || true)" printf 'check-attribution-trailers: %s commit(s) with prohibited trailers found\n' "$count" >&2 exit 1 fi exit 0