# Contributing to Cleave

## Branching Strategy

### Trunk-Based Development

We use a trunk-based development workflow with `main` as the single source of truth.

```
main (trunk)
  ├─ feature/add-user-auth
  ├─ fix/windows-path-separator
  ├─ patch/typo-in-docs
  └─ chore/update-dependencies
```

### Branch Types

| Prefix | Purpose | Example | Semver Impact |
|--------|---------|---------|---------------|
| `feature/` | New functionality | `feature/junction-point-support` | Minor (0.x.0) |
| `fix/` | Bug fixes | `fix/race-condition-cleanup` | Patch (0.0.x) |
| `patch/` | Non-code fixes | `patch/update-readme` | Patch (0.0.x) |
| `chore/` | Maintenance | `chore/update-deps` | Patch (0.0.x) |
| `refactor/` | Code restructuring | `refactor/extract-path-utils` | Patch (0.0.x) |
| `perf/` | Performance improvements | `perf/cache-pattern-matching` | Minor (0.x.0) |
| `breaking/` | Breaking changes | `breaking/remove-deprecated-api` | Major (x.0.0) |

### Branch Naming

- Use lowercase with hyphens: `feature/windows-long-paths`
- Be descriptive: `fix/stale-copy-detection` not `fix/issue-42`
- Reference issues when applicable: `fix/symlink-race-condition-#15`

### Branch Lifecycle

1. **Create** branch from latest `main`
   ```bash
   git checkout main
   git pull
   git checkout -b feature/my-feature
   ```

2. **Develop** with frequent commits
   ```bash
   git add .
   git commit -m "feat: add initial structure"
   ```

3. **Sync** with main regularly
   ```bash
   git checkout main
   git pull
   git checkout feature/my-feature
   git rebase main  # or git merge main
   ```

4. **Push** to remote
   ```bash
   git push -u origin feature/my-feature
   ```

5. **Merge** to main via pull request
   - Squash commits for small features
   - Merge commit for larger features with valuable history
   - **Never** fast-forward merge

6. **Delete** branch after merge
   ```bash
   git branch -d feature/my-feature
   git push origin --delete feature/my-feature
   ```

## Release Process

### Semantic Versioning

We follow [Semantic Versioning 2.0.0](https://semver.org/):

```
MAJOR.MINOR.PATCH

1.2.3
│ │ └─ Patch: Bug fixes, non-code changes
│ └─── Minor: New features, backwards-compatible
└───── Major: Breaking changes
```

### Version Decision Matrix

| Change Type | Examples | Version Bump |
|-------------|----------|--------------|
| Breaking API changes | Remove function, change signature | Major (x.0.0) |
| Deprecation of public API | Mark function as deprecated | Minor (0.x.0) |
| New features | Add command, new flag | Minor (0.x.0) |
| Bug fixes | Fix crash, correct logic | Patch (0.0.x) |
| Documentation | README updates, typo fixes | Patch (0.0.x) |
| Internal refactoring | Extract function, rename private | Patch (0.0.x) |
| Performance improvements | Optimize algorithm, cache | Minor (0.x.0) |
| Dependency updates | Update PyYAML, add new dep | Patch (0.0.x) |

### Pre-1.0.0 Exemptions

Before reaching 1.0.0 stable:
- Minor breaking changes allowed in `0.x.0` releases
- Major breaking changes bump minor: `0.3.0` → `0.4.0`
- Signal stability with `1.0.0` release

### Release Steps

**Only from `main` branch. Never tag feature branches.**

#### 1. Prepare Release

```bash
# Ensure on main with latest changes
git checkout main
git pull

# Run full test suite
make test

# Review changes since last release
git log v0.3.0..HEAD --oneline

# Determine version bump (MAJOR.MINOR.PATCH)
NEXT_VERSION="0.4.0"  # Example
```

#### 2. Update Version

```bash
# Update pyproject.toml
sed -i '' 's/version = "0.3.0"/version = "0.4.0"/' pyproject.toml

# Update CHANGELOG.md
cat << EOF >> CHANGELOG.md

## [$NEXT_VERSION] - $(date +%Y-%m-%d)

### Added
- New feature A
- New feature B

### Fixed
- Bug fix C

### Changed
- Improvement D

EOF
```

#### 3. Commit Version Bump

```bash
git add pyproject.toml CHANGELOG.md
git commit -m "chore: bump version to $NEXT_VERSION"
```

#### 4. Create Tag

```bash
# Annotated tag with release notes
git tag -a v$NEXT_VERSION -m "Version $NEXT_VERSION: Brief summary

Highlights:
- Feature A
- Bug fix B
- Performance improvement C

See CHANGELOG.md for full details.
"
```

#### 5. Build and Test

```bash
# Clean previous builds
make clean

# Build distribution
make build

# Test installation locally
pip install dist/styrene_cleave-$NEXT_VERSION-py3-none-any.whl
cleave --version  # Should show new version
cleave install-skill
```

#### 6. Push and Publish

```bash
# Push commits and tags
git push origin main
git push origin v$NEXT_VERSION

# Upload to PyPI
make upload
```

#### 7. Create GitHub Release

1. Go to https://github.com/styrene-lab/cleave/releases
2. Click "Draft a new release"
3. Select tag: `v$NEXT_VERSION`
4. Title: `Version $NEXT_VERSION`
5. Description: Copy from CHANGELOG.md
6. Attach build artifacts (optional)
7. Publish release

### Hotfix Process

For critical fixes that can't wait for the next release cycle:

```bash
# Create hotfix branch from latest tag
git checkout v0.3.0
git checkout -b hotfix/critical-security-fix

# Make fix
git commit -m "fix: patch critical security vulnerability"

# Bump patch version
# Update pyproject.toml: 0.3.0 -> 0.3.1
# Update CHANGELOG.md

git commit -m "chore: bump version to 0.3.1"

# Merge to main
git checkout main
git merge --no-ff hotfix/critical-security-fix

# Tag
git tag -a v0.3.1 -m "Hotfix 0.3.1: Security patch"

# Push
git push origin main
git push origin v0.3.1

# Release
make upload

# Clean up
git branch -d hotfix/critical-security-fix
```

## Commit Message Convention

We follow [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <subject>

<body>

<footer>
```

### Types

| Type | Description | Example |
|------|-------------|---------|
| `feat` | New feature | `feat(cli): add --force-symlink flag` |
| `fix` | Bug fix | `fix(install): handle race condition on Windows` |
| `docs` | Documentation | `docs: update installation instructions` |
| `style` | Code style | `style: format with ruff` |
| `refactor` | Code refactoring | `refactor(install): extract path validation` |
| `perf` | Performance | `perf(assess): cache pattern matching` |
| `test` | Tests | `test(install): add Windows long path tests` |
| `chore` | Maintenance | `chore: bump dependencies` |
| `ci` | CI/CD | `ci: add Windows runner to GitHub Actions` |
| `revert` | Revert commit | `revert: "feat: add experimental feature"` |

### Breaking Changes

Mark breaking changes with `!` or `BREAKING CHANGE:` footer:

```
feat!: remove deprecated --validate flag

BREAKING CHANGE: The --validate flag has been removed. Use --no-validate instead.
```

### Examples

**Good:**
```
feat(cli): add version tracking for directory copies

- Store package version in .version file
- Auto-detect stale installations
- Update on package upgrade

Closes #42
```

**Bad:**
```
fixed stuff
```

## Pull Request Process

### Before Creating PR

- [ ] Branch name follows convention (`feature/`, `fix/`, etc.)
- [ ] All tests pass (`make test`)
- [ ] Code follows style guide (run `ruff check`)
- [ ] Commits follow conventional commit format
- [ ] CHANGELOG.md updated (if user-facing change)
- [ ] Documentation updated (if API change)

### PR Title

Use conventional commit format:
```
feat(install): add automatic stale copy detection
fix(cli): resolve Windows path separator issue
docs: update pipx installation instructions
```

### PR Description Template

```markdown
## Summary
Brief description of changes.

## Type of Change
- [ ] Bug fix (patch)
- [ ] New feature (minor)
- [ ] Breaking change (major)
- [ ] Documentation update

## Changes
- Change A
- Change B
- Change C

## Testing
How was this tested?

## Checklist
- [ ] Tests pass
- [ ] Documentation updated
- [ ] CHANGELOG.md updated (if user-facing)
- [ ] Follows commit conventions
```

### Review Process

1. **Automated Checks**: All CI/CD checks must pass
2. **Code Review**: At least one approval required
3. **Testing**: Reviewer should test locally for significant changes
4. **Merge**: Squash for small PRs, merge commit for larger features

## Development Workflow

### Local Development

```bash
# Initial setup
git clone git@github.com:styrene-lab/cleave.git
cd cleave
make dev  # Creates venv, installs with dev dependencies

# Make changes
git checkout -b feature/my-feature

# Test
make test

# Lint
.venv/bin/ruff check src/ tests/

# Format
.venv/bin/ruff format src/ tests/

# Type check
.venv/bin/mypy src/

# Commit
git add .
git commit -m "feat: add my feature"
```

### Running Tests

```bash
# All tests
make test

# Specific test file
.venv/bin/pytest tests/test_install_skill.py -v

# Specific test
.venv/bin/pytest tests/test_install_skill.py::TestInstallSkill::test_creates_symlink -v

# With coverage
.venv/bin/pytest --cov=cleave --cov-report=html
```

## Code Standards

### Python Style

- **Formatter**: Ruff (automated)
- **Linter**: Ruff with strict rules
- **Type Checker**: mypy in strict mode
- **Line Length**: 100 characters
- **Python Version**: 3.11+ (use modern syntax)

### Best Practices

- **Type Hints**: All public functions must have type hints
- **Docstrings**: All public modules, classes, and functions
- **Error Handling**: Explicit exception handling, no bare `except:`
- **Path Handling**: Use `pathlib.Path`, never string concatenation
- **Cross-Platform**: Test on Windows, macOS, Linux (via CI)
- **Tests**: Aim for >80% coverage, 100% for critical paths

### Code Review Checklist

- [ ] No hardcoded paths or platform assumptions
- [ ] Error messages are helpful and actionable
- [ ] Edge cases handled (empty input, missing files, etc.)
- [ ] No security vulnerabilities (path traversal, injection, etc.)
- [ ] Documentation reflects code changes
- [ ] Tests cover new functionality
- [ ] Backwards compatibility maintained (unless breaking change)

## Questions?

- **Issues**: https://github.com/styrene-lab/cleave/issues
- **Discussions**: https://github.com/styrene-lab/cleave/discussions
- **Email**: (if applicable)

---

**Thank you for contributing to Cleave!**
