Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ platform/coverage/

# Supabase CLI per-machine cache (project refs, pooler URLs, version files)
supabase/.temp/
.vercel
57 changes: 57 additions & 0 deletions .husky/post-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/sh

# >>> iris-push-start >>>
#!/bin/sh
# Iris auto-push: runs analysis and pushes to platform once per day.
# Runs in background to not block the commit.

IRIS_DIR="$HOME/.iris"
STAMP_FILE="$IRIS_DIR/.last_push_$(basename "$(git rev-parse --show-toplevel)" 2>/dev/null | tr '/' '_')"
TODAY=$(date +%Y-%m-%d)

# Check if already pushed today
if [ -f "$STAMP_FILE" ]; then
LAST_PUSH=$(cat "$STAMP_FILE" 2>/dev/null)
if [ "$LAST_PUSH" = "$TODAY" ]; then
exit 0
fi
fi

# Check if iris is available and authenticated
IRIS_BIN=""
for candidate in "$IRIS_DIR/bin/iris" "$IRIS_DIR/venv/bin/iris" "$(command -v iris 2>/dev/null)"; do
if [ -x "$candidate" ]; then
IRIS_BIN="$candidate"
break
fi
done

if [ -z "$IRIS_BIN" ]; then
exit 0
fi

# Check auth config exists
if [ ! -f "$IRIS_DIR/config.json" ]; then
exit 0
fi

# Check token is configured
TOKEN=$(grep -o '"token"' "$IRIS_DIR/config.json" 2>/dev/null)
if [ -z "$TOKEN" ]; then
exit 0
fi

REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$REPO_ROOT" ]; then
exit 0
fi

# Run in background so we don't block the commit
(
mkdir -p "$IRIS_DIR"
"$IRIS_BIN" "$REPO_ROOT" --push --quiet 2>/dev/null && echo "$TODAY" > "$STAMP_FILE"
) &

exit 0

# <<< iris-push-end <<<
82 changes: 82 additions & 0 deletions .husky/prepare-commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/sh

# >>> iris-hook-start >>>
#!/bin/sh
# Iris AI Attribution Hook (prepare-commit-msg)
#
# Detects AI agent environment variables and appends a Co-Authored-By
# tag to the commit message BEFORE the commit is created.
#
# This is safer than post-commit + amend because:
# - No history rewriting (commit is born with the correct message)
# - No hash changes after creation
# - No GPG signature invalidation
# - No double CI triggers
# - If this hook fails, the commit proceeds without the tag (exit 0)
#
# Installed via: iris hook install

# Arguments from git:
# $1 = path to the commit message file
# $2 = source of the message (message, template, merge, squash, commit)
# $3 = commit hash (only for amend)
COMMIT_MSG_FILE="$1"
COMMIT_SOURCE="${2:-}"

# Skip on merge, squash, and amend — these already have their messages
case "$COMMIT_SOURCE" in
merge|squash|commit) exit 0 ;;
esac

# --- Detect AI agent ---
# All detection is via environment variables. No subprocess calls.

AGENT_NAME=""
AGENT_EMAIL=""

# Domain for synthetic Co-Author emails. Override with IRIS_AGENT_EMAIL_DOMAIN.
# Default is "iris.invalid" (RFC 6761 reserved TLD — guaranteed never routable).
AGENT_EMAIL_DOMAIN="${IRIS_AGENT_EMAIL_DOMAIN:-iris.invalid}"

# 1. Vercel standard ($AI_AGENT)
if [ -n "$AI_AGENT" ]; then
AGENT_NAME="$AI_AGENT"
AGENT_EMAIL="$(printf '%s' "$AI_AGENT" | tr '[:upper:] ' '[:lower:]-')@${AGENT_EMAIL_DOMAIN}"

# 2. Claude Code
elif [ -n "$CLAUDE_CODE" ]; then
AGENT_NAME="Claude Code"
AGENT_EMAIL="claude-code@${AGENT_EMAIL_DOMAIN}"

# 3. Cursor
elif [ -n "$CURSOR_SESSION" ] || [ -n "$CURSOR_TRACE_ID" ]; then
AGENT_NAME="Cursor"
AGENT_EMAIL="cursor@${AGENT_EMAIL_DOMAIN}"

# 4. Windsurf
elif [ -n "$WINDSURF_SESSION" ]; then
AGENT_NAME="Windsurf"
AGENT_EMAIL="windsurf@${AGENT_EMAIL_DOMAIN}"

# 5. No agent detected — exit cleanly
else
exit 0
fi

# --- Check if attribution already present in the message ---
# Read the current message file (may be a template or empty).
# Match by tool name (local part) so this works regardless of email domain
# — including legacy trailers from older domains.

if grep -qi "Co-Authored-By:.*\(claude-code\|cursor\|windsurf\|copilot\|anthropic\|codeium\|tabnine\|amazon-q\|gemini\)" "$COMMIT_MSG_FILE" 2>/dev/null; then
exit 0
fi

# --- Append Co-Authored-By to the message file ---
# This is a simple file append. No git commands, no side effects.

printf '\nCo-Authored-By: %s <%s>\n' "$AGENT_NAME" "$AGENT_EMAIL" >> "$COMMIT_MSG_FILE"

exit 0

# <<< iris-hook-end <<<
Loading
Loading