chore: standardize CLAUDE.md and lefthook hooks

Co-Authored-By: Svrnty Inc. <jp@svrnty.io>
This commit is contained in:
Jean-Philippe Brule 2026-03-08 11:22:05 -04:00
parent 3fa59306c2
commit 313b8c83ea
2 changed files with 89 additions and 6 deletions

View File

@ -43,13 +43,33 @@ Universal development practices for all Svrnty/a-gent repositories.
## Commit Rules ## Commit Rules
All AI-authored commits MUST use: ### Allowed Authors
Only these emails are permitted for commits:
- `jp@svrnty.io` (Jean-Philippe Brule)
- `mathias@svrnty.io` (Mathias Beaulieu-Duncan)
Configure with: `git config user.email jp@svrnty.io`
### AI-Assisted Commits
All AI-authored commits MUST include:
``` ```
Co-Authored-By: Svrnty Inc. <eng@svrnty.com> Co-Authored-By: Svrnty Inc. <jp@svrnty.io>
``` ```
NEVER use third-party AI tool/company names in commits. NEVER use third-party AI tool/company names in commits.
### Git Hooks Setup
Install lefthook to enforce commit standards:
```bash
brew install lefthook
lefthook install
```
The hooks automatically:
- Validate author email is in allowed list
- Append Co-Authored-By footer
- Warn on conventional commit format violations
## PR Discipline ## PR Discipline
- Clear, scoped commit messages - Clear, scoped commit messages
@ -73,7 +93,7 @@ Run before every commit:
## Cross-Repo Changes ## Cross-Repo Changes
When changes span multiple repos: - Each repo is standalone with its own build configuration
1. Commit to each repo separately - Reference related repos in commit messages for cross-repo changes
2. Reference related repo in commit message - Coordinate multi-repo changes via matching branch names
3. Run tests in each affected repo before commit - Test each repo independently before pushing

63
lefthook.yml Normal file
View File

@ -0,0 +1,63 @@
pre-commit:
parallel: true
commands:
check-author:
run: |
EMAIL=$(git config user.email)
ALLOWED="jp@svrnty.io mathias@svrnty.io"
for a in $ALLOWED; do
[ "$EMAIL" = "$a" ] && exit 0
done
echo "BLOCKED: author email '$EMAIL' not in allowed list: $ALLOWED"
exit 1
no-secrets:
run: |
BLOCKED=$(git diff --cached --name-only | grep -E '\.(env|pem|key)$|credentials\.json|id_rsa|id_ed25519' || true)
if [ -n "$BLOCKED" ]; then
echo "BLOCKED: refusing to commit sensitive files:"
echo "$BLOCKED"
exit 1
fi
no-large-files:
run: |
LARGE=$(git diff --cached --name-only -z | xargs -0 -I{} sh -c 'if [ -f "{}" ]; then size=$(wc -c < "{}"); if [ "$size" -gt 5242880 ]; then echo "{} ($(( size / 1048576 ))MB)"; fi; fi' || true)
if [ -n "$LARGE" ]; then
echo "WARNING: large files staged (>5MB):"
echo "$LARGE"
fi
commit-msg:
commands:
validate-message:
run: |
MSG=$(cat "{1}")
if echo "$MSG" | head -1 | grep -qE '^Merge '; then
exit 0
fi
if ! echo "$MSG" | head -1 | grep -qE '^[a-z]+(\([a-zA-Z0-9_-]+\))?: .+'; then
echo "WARNING: commit message does not follow conventional format: type(scope): message"
fi
append-coauthor:
run: |
MSG=$(cat "{1}")
if ! echo "$MSG" | grep -qF 'Co-Authored-By: Svrnty Inc. <jp@svrnty.io>'; then
printf '\n\nCo-Authored-By: Svrnty Inc. <jp@svrnty.io>\n' >> "{1}"
fi
pre-push:
commands:
protect-main:
run: |
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
echo "BLOCKED: direct push to $BRANCH is not allowed"
exit 1
fi
check-behind-remote:
run: |
git fetch origin 2>/dev/null || true
BRANCH=$(git rev-parse --abbrev-ref HEAD)
BEHIND=$(git rev-list --count HEAD..origin/"$BRANCH" 2>/dev/null || echo 0)
if [ "$BEHIND" -gt 0 ]; then
echo "WARNING: local branch is $BEHIND commit(s) behind origin/$BRANCH"
fi