Thank you for contributing. This document covers the development workflow, CI requirements, and the branch protection settings that enforce them.
All changes — including those from automated agents — go through a pull request. Direct pushes to main are blocked by branch protection rules.
# 1. Create a feature or fix branch
git checkout -b fix/describe-the-change
# 2. Make changes, then verify locally before pushing
ruff check .
ruff format --check .
mypy src/skillscan/
pytest tests/ -q
# 3. Push and open a PR
git push origin fix/describe-the-change
gh pr create --fill
# 4. CI runs automatically on the PR
# 5. All checks must be green before merging
Every PR must pass all of the following before it can be merged:
| Check | Command | What it enforces |
|---|---|---|
| Lint | ruff check . |
No unused imports, undefined names, or style violations |
| Format | ruff format --check . |
Consistent code style (equivalent to black) |
| Type check | mypy src/skillscan/ |
No type annotation errors |
| Tests | pytest tests/ -q |
All unit and integration tests pass |
Run all four locally before pushing:
ruff check . && ruff format --check . && mypy src/skillscan/ && pytest tests/ -qThe following settings are configured on main in GitHub → Settings → Branches → Branch protection rules:
| Setting | Value | Why |
|---|---|---|
| Require a pull request before merging | ✅ Enabled | Prevents direct pushes to main |
| Required status checks | test (3.11), test (3.12), Lint & format |
CI must be green before merge |
| Require branches to be up to date before merging | ✅ Enabled | Prevents stale-branch merges that pass CI but break main |
| Do not allow bypassing the above settings | ✅ Enabled | Applies to admins and bots too |
| Allow force pushes | ❌ Disabled | Preserves commit history |
| Allow deletions | ❌ Disabled | Prevents accidental main deletion |
To configure these settings yourself:
- Go to
https://github.com/kurtpayne/skillscan-security/settings/branches - Click Add branch protection rule (or edit the existing
mainrule) - Set Branch name pattern to
main - Enable the settings in the table above
- Under Require status checks to pass before merging, search for and select:
test (3.11),test (3.12),Lint & format - Click Save changes
Use Conventional Commits:
<type>: <short description>
<optional body>
Common types: feat, fix, docs, refactor, test, chore.
Examples:
feat: add temporal trigger detection rule (MAL-055)fix: resolve mypy no-any-return in skill_schemadocs: update CONTRIBUTING with branch protection steps
- Add the rule entry to
src/skillscan/data/rules/default.yamlinsidestatic_rules - Include a
test_input: |block with sample content that triggers the rule - Include
test_expect: firesafter the test_input - Run
python3 scripts/sync-website-rules.pyto update the website TSX files - Run
SKILLSCAN_NO_USER_RULES=1 pytest tests/test_rule_inputs.py -qto verify - Open a PR — CI will validate the YAML parses and the rule fires on its test_input
Open an issue or start a discussion on GitHub.