Claude-skill-registry git-workflow-enforcer
Enforce git commits after every phase and task to enable rollback and prevent lost work. Auto-trigger when completing phases, tasks, or when detecting uncommitted changes. Auto-commit with Conventional Commits format. Verify branch safety, check for merge conflicts, enforce clean working tree. Block completion if changes not committed.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/git-workflow-enforcer" ~/.claude/skills/majiayu000-claude-skill-registry-git-workflow-enforcer && rm -rf "$T"
skills/data/git-workflow-enforcer/SKILL.md<quick_start> <auto_commit_workflow> Automatic commit generation when changes detected:
- Detect uncommitted changes: Run
git status --porcelain - Classify change type: Phase completion, task completion, or file modification
- Generate commit message: Use Conventional Commits format based on context
- Validate safety: Check branch, merge conflicts, commit message format
- Execute commit: Stage files and commit with generated message
- Provide feedback: Show commit hash and rollback command
Example:
Context: Task T001 completed ❌ UNCOMMITTED CHANGES DETECTED Modified: api/models/message.py Created: api/tests/test_message.py ✅ AUTO-COMMITTING with generated message: feat(green): T001 implement Message model to pass test Implementation: SQLAlchemy model with validation Tests: 26/26 passing Coverage: 93% (+1%) ✅ COMMITTED: abc123f Rollback: git revert abc123f
</auto_commit_workflow>
<trigger_patterns> Auto-invoke when detecting:
Phase completion markers:
- "Phase N complete"
- "/specify complete", "/plan complete", "/tasks complete"
- "analysis complete", "optimization complete"
- Phase command finishing
Task completion markers:
- "T### complete", "task ### done"
- "task-tracker mark-done" command
- "mark task complete"
Change detection:
returns non-emptygit status --porcelain- Files created/modified/deleted
- Working tree dirty before phase transition </trigger_patterns>
<commit_message_generation> Conventional Commits format:
<type>(<scope>): <subject> [optional body] [optional footer]
Auto-detection logic:
| Context | Type | Scope | Subject Template |
|---|---|---|---|
| Phase 0 | docs | spec | create specification for {feature} |
| Phase 0.5 | docs | clarify | resolve {n} clarifications for {feature} |
| Phase 1 | docs | plan | create implementation plan for {feature} |
| Phase 2 | docs | tasks | create task breakdown for {feature} ({n} tasks) |
| Phase 3 | docs | analyze | create cross-artifact analysis for {feature} |
| Phase 4 (RED) | test | red | {taskId} write failing test for {description} |
| Phase 4 (GREEN) | feat | green | {taskId} implement {description} to pass test |
| Phase 4 (REFACTOR) | refactor | - | {taskId} improve {description} |
| Phase 5 | docs | optimize | complete optimization review for {feature} |
| Phase 6 | docs | preview | create release notes for {feature} v{version} |
Body generation:
- Phase commits: Include metrics (task count, criteria count, etc.)
- Task commits: Include evidence (tests, coverage, commit hash)
- Fix commits: Include root cause and solution
See references/commit-templates.md for complete templates. </commit_message_generation> </quick_start>
<workflow> <detection_phase> **1. Monitor for Commit Triggers**Check for uncommitted changes when:
- Phase command completes
- task-tracker mark-done-with-notes called
- User mentions "commit", "save progress", etc.
# Check for uncommitted changes git status --porcelain # If non-empty output → uncommitted changes exist
</detection_phase>
<classification_phase> 2. Classify Change Type and Extract Context
Phase completion:
- Extract phase name from workflow state or command
- Extract feature slug from current directory
- Get artifact file paths (spec.md, plan.md, etc.)
Task completion:
- Extract TaskId from task-tracker parameters or conversation
- Extract task description from tasks.md
- Get phase marker ([RED], [GREEN], [REFACTOR])
- Extract evidence (tests, coverage) from completion context
File modification:
- Analyze changed files to infer purpose
- Check git log for recent commit patterns
- Default to "chore" type if unclear </classification_phase>
<validation_phase> 3. Validate Safety Before Committing
Check 1: Branch safety
CURRENT_BRANCH=$(git branch --show-current) if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then ❌ BLOCKED: Direct commits to main/master not allowed Recommendation: git checkout -b feat/{feature-slug} Exit code: 1 fi if [[ ! "$CURRENT_BRANCH" =~ ^(feat|feature|bugfix|fix|hotfix|chore)/ ]]; then ⚠️ WARNING: Branch name doesn't follow convention Expected: feat/*, bugfix/*, hotfix/*, chore/* Current: $CURRENT_BRANCH Proceed? (auto-yes in non-interactive mode) fi
Check 2: Merge conflicts
# Check for conflict markers if grep -r "<<<<<<<" . --exclude-dir=.git; then ❌ BLOCKED: Unresolved merge conflicts detected Resolve conflicts before committing Exit code: 1 fi # Check git status for conflicts if git status | grep -q "both modified"; then ❌ BLOCKED: Merge conflicts in git status Run: git status Exit code: 1 fi
Check 3: Remote tracking
# Check if branch has upstream if ! git rev-parse --abbrev-ref @{upstream} &>/dev/null; then ⚠️ WARNING: Branch has no upstream tracking Recommendation: git push -u origin $(git branch --show-current) Continue without upstream? (auto-yes) fi
Check 4: Commit message format
# Validate Conventional Commits format COMMIT_MSG="$1" # Check format: type(scope): subject if ! [[ "$COMMIT_MSG" =~ ^(feat|fix|docs|test|refactor|perf|chore|ci|build|revert)(\([a-z0-9-]+\))?: ]]; then ❌ INVALID: Commit message doesn't follow Conventional Commits Expected: type(scope): subject Got: $COMMIT_MSG Auto-fix? (yes) → Prepend "chore: " to message fi # Check subject length (<50 chars recommended) SUBJECT=$(echo "$COMMIT_MSG" | head -1) if [[ ${#SUBJECT} -gt 72 ]]; then ⚠️ WARNING: Subject line too long (${#SUBJECT} > 72 chars) Recommendation: Keep under 50 chars for readability fi
See references/validation-rules.md for complete validation logic. </validation_phase>
<commit_generation_phase> 4. Generate and Execute Commit
Stage files:
# Get list of changed files CHANGED_FILES=$(git status --porcelain | awk '{print $2}') # Stage all changed files (auto-add for convenience) git add $CHANGED_FILES # Or stage all (if in feature directory) git add specs/$FEATURE_SLUG/
Generate commit message:
# Use template based on context if [[ "$CONTEXT" == "phase_complete" ]]; then TYPE="docs" SCOPE="$PHASE_NAME" SUBJECT="create $ARTIFACTS for $FEATURE_SLUG" BODY="- Artifacts: $(echo $ARTIFACTS | tr '\n' ', ') - Phase: $PHASE_NAME - Feature: $FEATURE_SLUG" elif [[ "$CONTEXT" == "task_complete" ]]; then # Extract from tasks.md PHASE_MARKER=$(grep "$TASK_ID" tasks.md | grep -oP '\[([A-Z]+)\]' | tr -d '[]') if [[ "$PHASE_MARKER" == "RED" ]]; then TYPE="test" SCOPE="red" elif [[ "$PHASE_MARKER" == "GREEN" ]]; then TYPE="feat" SCOPE="green" elif [[ "$PHASE_MARKER" == "REFACTOR" ]]; then TYPE="refactor" SCOPE="" fi SUBJECT="$TASK_ID $(extract_task_description)" BODY="Implementation: $NOTES Tests: $EVIDENCE Coverage: $COVERAGE" fi # Construct full message COMMIT_MESSAGE="${TYPE}(${SCOPE}): ${SUBJECT} ${BODY}"
Execute commit:
git commit -m "$(cat <<EOF $COMMIT_MESSAGE EOF )" COMMIT_HASH=$(git rev-parse --short HEAD) echo "✅ COMMITTED: $COMMIT_HASH" echo " Rollback: git revert $COMMIT_HASH"
See references/auto-commit-logic.md for detailed generation rules. </commit_generation_phase>
<verification_phase> 5. Verify and Provide Feedback
Verify commit succeeded:
# Check that working tree is now clean if [ -n "$(git status --porcelain)" ]; then ⚠️ WARNING: Working tree still dirty after commit Uncommitted files: $(git status --short) Manual review needed fi # Get commit details COMMIT_HASH=$(git rev-parse --short HEAD) COMMIT_MSG=$(git log -1 --pretty=%B) COMMIT_TIME=$(git log -1 --format=%ar) CHANGED_FILES=$(git diff-tree --no-commit-id --name-only -r HEAD | wc -l)
Provide feedback:
✅ **AUTO-COMMIT SUCCESSFUL** **Commit:** $COMMIT_HASH ($COMMIT_TIME) **Message:** $COMMIT_MSG **Files:** $CHANGED_FILES changed **Branch:** $(git branch --show-current) **Working tree:** Clean **Rollback:** git revert $COMMIT_HASH **Push:** git push
Check for unpushed commits:
UNPUSHED=$(git log @{u}.. --oneline 2>/dev/null | wc -l) if [[ $UNPUSHED -gt 0 ]]; then ⚠️ **REMINDER: Unpushed Commits** You have $UNPUSHED unpushed commit(s) on this branch. Push to backup: git push fi
</verification_phase> </workflow>
<safety_checks> Blocking checks (prevent commit):
- ❌ On main/master branch (unless deployment phase)
- ❌ Unresolved merge conflicts
- ❌ Invalid commit message format (auto-fixable with prompt)
Warning checks (allow but warn):
- ⚠️ Branch name doesn't follow conventions
- ⚠️ No upstream tracking configured
- ⚠️ Commit subject line >50 chars
- ⚠️ Unpushed commits exist
Auto-fix attempts:
- Branch: Suggest
git checkout -b feat/{slug} - Message format: Prepend "chore: " if type missing
- Upstream: Suggest
git push -u origin {branch}
See references/safety-checks.md for complete check logic. </safety_checks>
<anti_patterns> Avoid these mistakes:
1. Bundling multiple phases in one commit
❌ BAD: git commit -m "complete spec, plan, and tasks" ✅ GOOD: git commit -m "docs(spec): create specification for user-messaging" git commit -m "docs(plan): create implementation plan for user-messaging" git commit -m "docs(tasks): create task breakdown for user-messaging"
2. Committing to main/master directly
❌ BAD: (on main) git commit -m "feat: add feature" ✅ GOOD: git checkout -b feat/user-messaging git commit -m "feat: add message model"
3. Vague commit messages
❌ BAD: git commit -m "fixes" git commit -m "updates" git commit -m "WIP" ✅ GOOD: git commit -m "fix(api): correct message validation logic" git commit -m "refactor: extract MessageService from controller"
4. Skipping commits between tasks
❌ BAD: # Implement T001, T002, T003 git commit -m "implement all tasks" ✅ GOOD: # Implement T001 git commit -m "feat(green): T001 implement Message model" # Implement T002 git commit -m "feat(green): T002 implement MessageService" # Implement T003 git commit -m "feat(green): T003 add /messages endpoint"
5. Not checking for conflicts before commit
❌ BAD: git commit -m "fix: update model" # Later: ❌ Push rejected, conflicts with remote ✅ GOOD: git fetch git merge origin/main # Resolve any conflicts git commit -m "fix: update model after merge"
</anti_patterns>
<success_criteria> Git workflow enforcement working when:
- ✓ Uncommitted changes automatically committed after phase/task completion
- ✓ Commit messages follow Conventional Commits format
- ✓ Commits blocked on main/master (redirected to feature branch)
- ✓ Merge conflicts detected and block commit
- ✓ Branch naming conventions validated
- ✓ Unpushed commits detected and warned
- ✓ Working tree always clean between phases
- ✓ Every task has dedicated commit with hash in NOTES.md
- ✓ Rollback points available for every phase and task
- ✓ Commit subject lines concise (<50 chars recommended)
Safety checks passing when:
- Protected branches (main/master) have no direct commits
- All commits follow type(scope): subject format
- No unresolved merge conflict markers in codebase
- Branches have upstream tracking configured
- Clear rollback procedures available </success_criteria>
<reference_guides> For detailed templates, validation logic, and commit examples:
- references/commit-templates.md - Complete Conventional Commits templates by phase/task type
- references/auto-commit-logic.md - Auto-commit generation rules and context extraction
- references/validation-rules.md - Safety checks, branch validation, conflict detection
- references/safety-checks.md - Blocking vs warning checks, auto-fix strategies
- references/rollback-procedures.md - Rollback commands for phases, tasks, and batches </reference_guides>