Claude Code Plugins

Community-maintained marketplace

Feedback

git-workflow-enforcer

@marcusgoll/Spec-Flow
13
0

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.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name git-workflow-enforcer
description 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.
Prevent lost work and enable granular rollback by enforcing git commits after every meaningful change (phase completion, task completion) with automatic commit generation following Conventional Commits standards. **Automatic commit generation when changes detected:**
  1. Detect uncommitted changes: Run git status --porcelain
  2. Classify change type: Phase completion, task completion, or file modification
  3. Generate commit message: Use Conventional Commits format based on context
  4. Validate safety: Check branch, merge conflicts, commit message format
  5. Execute commit: Stage files and commit with generated message
  6. 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-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:

  • git status --porcelain returns non-empty
  • Files created/modified/deleted
  • Working tree dirty before phase transition
**Conventional Commits format:** ``` ():

[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](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.

```bash
# Check for uncommitted changes
git status --porcelain

# If non-empty output → uncommitted changes exist
**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
**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.

**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.

**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
**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.

**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"
**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
For detailed templates, validation logic, and commit examples: