This guide covers how to configure Watchflow rules. Rules are description + event_types + parameters; the engine matches parameter keys to built-in conditions. No custom code—just YAML in .watchflow/rules.yaml on the default branch.
Pro tip: Test rule ideas at watchflow.dev. Use “Evaluate” for feasibility and suggested YAML, or run repo analysis to get a full suggested config. When you land from the app install flow (?installation_id=...&repo=owner/repo), no PAT is required.
Each rule has:
| Field | Required | Description |
|---|---|---|
description |
Yes | Short human-readable description (used in check runs and comments). |
enabled |
No | Default true. Set false to disable without deleting. |
severity |
No | low | medium | high | critical. Drives presentation, not logic. |
event_types |
Yes | Events this rule runs on: pull_request, push, deployment, etc. |
parameters |
Yes | Key-value map. Keys determine which condition runs (e.g. require_linked_issue, max_lines). |
The loader reads .watchflow/rules.yaml from the repo default branch and builds Rule objects with condition instances from the condition registry. Parameter names must match what the conditions expect; see below.
Linked issue
parameters:
require_linked_issue: truePR must reference an issue (e.g. “Fixes #123”) in title or body.
Title pattern
parameters:
title_pattern: "^feat|^fix|^docs|^style|^refactor|^test|^chore|^perf|^ci|^build|^revert"PR title must match the regex (e.g. conventional commits).
Description length
parameters:
min_description_length: 50PR body length must be ≥ N characters.
Required labels
parameters:
required_labels: ["Type/Bug", "Type/Feature", "Status/Review"]PR must have all of these labels.
Min approvals
parameters:
min_approvals: 2At least N approvals required.
Max PR size (lines)
parameters:
max_lines: 500Total additions + deletions must be ≤ N. The loader also accepts max_changed_lines as an alias.
CODEOWNERS: require owners as reviewers
parameters:
require_code_owner_reviewers: trueFor every file changed, the corresponding CODEOWNERS entries must be in the requested reviewers (users or teams). If CODEOWNERS is missing, the condition skips (no violation).
CODEOWNERS: path must have owner
parameters:
require_path_has_code_owner: trueEvery changed path must have at least one owner in CODEOWNERS. If CODEOWNERS is missing, the condition skips.
Critical paths / code owners
parameters:
critical_owners: [] # or list of path patterns if supportedChanges to critical paths require code-owner review. (See registry for exact semantics.)
Protected branches
parameters:
protected_branches: ["main", "master"]Blocks targeting these branches (e.g. merge without going through PR flow as configured).
No force push
parameters:
no_force_push: trueReject force pushes. Typically used with event_types: ["push"].
Max file size
parameters:
max_file_size_mb: 1No single file in the PR may exceed N MB.
File pattern
parameters:
pattern: "tests/.*\\.py$|test_.*\\.py$"
condition_type: "files_match_pattern"Changed files must (or must not) match the pattern; exact behavior depends on condition.
Allowed hours, days, weekend — See condition registry and examples in repo for allowed_hours, timezone, days, and deployment-related parameters.
Restricted diff patterns
parameters:
diff_restricted_patterns: ["console\\.log", "TODO:", "debugger"]Flag added lines in the PR diff that match any of the listed regex patterns.
Security pattern detection
parameters:
security_patterns: ["api_key", "secret", "password", "token"]Detect hardcoded secrets or sensitive data in PR diffs. Violations are raised with critical severity.
Test coverage enforcement
parameters:
require_tests: true
test_file_pattern: "^tests/.*" # optional, defaults to common test pathsSource file changes must include corresponding test file changes. Ignored file types: .md, .txt, .yaml, .json.
Unresolved review comments
parameters:
block_on_unresolved_comments: trueBlock merge when unresolved (non-outdated) review comment threads exist on the PR.
Comment response time SLA
parameters:
max_comment_response_time_hours: 24Flag unresolved review threads that have exceeded the specified hour-based SLA.
Self-approval prevention
parameters:
block_self_approval: truePR authors cannot approve their own pull requests. Violations are raised with critical severity.
Cross-team approval
parameters:
required_team_approvals: ["backend", "security"]Require approvals from members of specified GitHub teams before merge.
Signed commits
parameters:
require_signed_commits: trueAll commits in the PR must be cryptographically signed (GPG, SSH, or S/MIME). Required for SOC2/FedRAMP compliance.
Changelog required
parameters:
require_changelog_update: truePRs that modify source code must include a corresponding CHANGELOG.md or .changeset/ update. Docs, tests, and .github/ paths are excluded.
Description-diff alignment
parameters:
require_description_diff_alignment: trueUses the configured AI provider to check whether the PR description semantically reflects the actual code changes. Flags mismatches like "description says fix login but diff only touches billing code." Adds ~1-3s latency per evaluation. If the LLM is unavailable (provider not configured, rate limit), the condition gracefully skips without blocking the PR.
Linked issue + PR size + CODEOWNERS reviewers
rules:
- description: "PRs must reference a linked issue (e.g. Fixes #123)"
enabled: true
severity: high
event_types: ["pull_request"]
parameters:
require_linked_issue: true
- description: "PR total lines changed must not exceed 500"
enabled: true
severity: medium
event_types: ["pull_request"]
parameters:
max_lines: 500
- description: "When a PR modifies paths with CODEOWNERS, those owners must be added as reviewers"
enabled: true
severity: high
event_types: ["pull_request"]
parameters:
require_code_owner_reviewers: trueTitle pattern + description length
rules:
- description: "PR titles must follow conventional commit format; descriptions must be at least 50 chars"
enabled: true
severity: medium
event_types: ["pull_request"]
parameters:
title_pattern: "^feat|^fix|^docs|^style|^refactor|^test|^chore"
min_description_length: 50No force push to main
rules:
- description: "No direct pushes to main - all changes must go through PRs"
enabled: true
severity: critical
event_types: ["push"]
parameters:
no_force_push: true- low — Informational; no blocking.
- medium — Warning; often acknowledgable.
- high — Blocking unless acknowledged (when the rule allows).
- critical — Blocking; acknowledgment may not be allowed depending on rule.
Severity affects how violations are presented in check runs and comments; it does not change the condition logic.
- pull_request — PR opened, updated, synchronized, etc.
- push — Pushes to branches (use
no_force_pushfor branch protection). - deployment / deployment_status / deployment_review — Deployment protection and time-based deploy rules.
- issue_comment — Used for parsing
@watchflow acknowledgeand similar commands.
Rules are loaded from .watchflow/rules.yaml on the repo default branch (e.g. main) via the GitHub API using the installation token. So:
- Changes to
.watchflow/rules.yamltake effect after merge to the default branch. - No local clone or filesystem access is required for evaluation; PR data and CODEOWNERS content are fetched by the enricher.
- Start small — Enable one or two rules (e.g.
require_linked_issue,require_code_owner_reviewers), then add more. - Use watchflow.dev — Run repo analysis or feasibility to get suggested YAML that uses the correct parameter names.
- Version control — Keep
.watchflow/rules.yamlin the repo and review rule changes in PRs. - Acknowledgment — Use
@watchflow acknowledge "reason"for legitimate one-off exceptions; don’t use it to bypass policy routinely.
For the full list of conditions and parameter names, see Features and the source: src/rules/conditions/ and src/rules/registry.py.