Skip to content

Commit d51bdc0

Browse files
authored
docs: AI-only and real-project recipes, CC017, v2.20.0 (#76)
1 parent 96583e7 commit d51bdc0

11 files changed

Lines changed: 191 additions & 16 deletions

File tree

‎docs/changelog.md‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ below and to the page that documents the feature properly.
1111

1212
| Version | What changed | Documented in |
1313
|---|---|---|
14+
| [2.20.0](#v2200) | A commit authored by an AI tool rejected (CC017); Continue, Mistral Vibe and Qwen Code recognised; subject length `0` turns the rule off; Python 3.10 dropped | [CC017](rules.md#cc017) · [CC013](rules.md#cc013) · [CC004](rules.md#cc004) |
1415
| [2.19.5](#v2195) | GitHub merge queue branches accepted by default; aider's default co-author trailer recognised; exit 2 when git cannot read the repository | [CC201](rules.md#cc201) · [CC013](rules.md#cc013) · [Exit codes](troubleshoot.md#exit-codes) |
1516
| [2.19.4](#v2194) | `agents/` branches accepted by default; Cursor's `Made-with: Cursor` trailer recognised | [CC201](rules.md#cc201) · [CC013](rules.md#cc013) |
1617
| [2.19.3](#v2193) | A quoted `"false"` for a true/false setting refused instead of read as true | [Every option](configuration.md#every-option) |
@@ -36,6 +37,48 @@ below and to the page that documents the feature properly.
3637
| [2.5.0](#v250) | Organization-wide config with `inherit_from` | [Across an organization](guides/organization.md) |
3738
| [2.0.0](#v200) | Configuration moved from YAML to TOML — breaking | [Migrating from v1](migration.md) |
3839

40+
## v2.20.0 (2026-11-08) { #v2200 }
41+
42+
### Added
43+
44+
* **[CC017](rules.md#cc017) rejects a commit whose author is an AI tool** —
45+
the message rules read only the message, so an agent that commits under
46+
its own identity (`claude[bot]`, `google-labs-jules[bot]`,
47+
`devin-ai-integration[bot]`, OpenHands, an `(aider)` name) passed with a
48+
clean message, even one that credits a person as co-author. Under
49+
`ai_attribution = "forbid"` or `"disclose"` such a commit now fails.
50+
`ignore_authors` skips it and `warn` can report it without failing.
51+
See PR [#661](https://github.com/commit-check/commit-check/pull/661).
52+
53+
* **[CC013](rules.md#cc013)–[CC016](rules.md#cc016) recognise Continue,
54+
Mistral Vibe and Qwen Code** — their default commit signatures
55+
(`Generated with [Continue](https://continue.dev)`,
56+
`Generated by Mistral Vibe.` with `vibe@mistral.ai`, and
57+
`Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>`) passed every
58+
policy.
59+
See PRs [#657](https://github.com/commit-check/commit-check/pull/657) and
60+
[#659](https://github.com/commit-check/commit-check/pull/659).
61+
62+
### Changed
63+
64+
* **`subject_max_length = 0` and `subject_min_length = 0` turn the rule
65+
off** — `0` used to mean a limit of zero characters, so a project that
66+
wanted only the AI check had to pick a large number instead. See
67+
[Checking AI attribution and nothing else](guides/policies.md#checking-ai-attribution-and-nothing-else).
68+
See PR [#660](https://github.com/commit-check/commit-check/pull/660).
69+
70+
* **Python 3.11 or newer is required** — Python 3.10 reached end of life, and
71+
the `tomli` dependency is gone with it. The GitHub Action needs it too from
72+
v2.19.0: on `ubuntu-22.04`, add `actions/setup-python` first (see
73+
[GitHub Action](guides/github-actions.md)).
74+
See PR [#662](https://github.com/commit-check/commit-check/pull/662).
75+
76+
### Fixed
77+
78+
* **`[commit] require_verified` no longer warns as an unknown setting** — the
79+
GitHub App reads it, and the CLI now leaves it alone.
80+
See PR [#656](https://github.com/commit-check/commit-check/pull/656).
81+
3982
## v2.19.5 (2026-11-04) { #v2195 }
4083

4184
### Fixed

‎docs/compare/tools.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Replace the hook:
6565
```yaml title=".pre-commit-config.yaml"
6666
repos:
6767
- repo: https://github.com/commit-check/commit-check
68-
rev: v2.19.5
68+
rev: v2.20.0
6969
hooks:
7070
- id: check-message
7171
```

‎docs/configuration.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ Used from a hook definition, with no config file anywhere in the repository:
274274
```yaml title=".pre-commit-config.yaml"
275275
repos:
276276
- repo: https://github.com/commit-check/commit-check
277-
rev: v2.19.5
277+
rev: v2.20.0
278278
hooks:
279279
- id: check-message
280280
args:
@@ -387,8 +387,8 @@ the same thing twice, so read the description rather than the cell:
387387
| commit | message_pattern | str | "" (no custom pattern) | Custom regex pattern for commit message validation. When set, this pattern replaces the auto-generated Conventional Commits regex entirely, making it possible to enforce custom formats such as JIRA smart commits (e.g., `"^PROJ-\\d+: .+"`). When `message_pattern` is set (non-empty) it takes precedence over `conventional_commits`. |
388388
| commit | subject_capitalized | bool | false | Subject must start with a capital letter. |
389389
| commit | subject_imperative | bool | false | Subject must be in imperative mood. Judged on the first word's form, so a verb no list contains is still accepted — see [CC003](rules.md#cc003). |
390-
| commit | subject_max_length | int | 80 | Maximum length of the subject line. |
391-
| commit | subject_min_length | int | 5 | Minimum length of the subject line. |
390+
| commit | subject_max_length | int | 80 | Maximum length of the subject line. `0` turns the check off. |
391+
| commit | subject_min_length | int | 5 | Minimum length of the subject line. `0` turns the check off. |
392392
| commit | allow_commit_types | list[str] | ["feat", "fix", "docs", "style", "refactor", "test", "chore", "perf", "build", "ci"] | Allowed commit types when conventional_commits is true. |
393393
| commit | allow_merge_commits | bool | true | Allow merge commits. |
394394
| commit | allow_revert_commits | bool | true | Allow revert commits. |

‎docs/example.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pushed:
162162
```yaml title=".pre-commit-config.yaml"
163163
repos:
164164
- repo: https://github.com/commit-check/commit-check
165-
rev: v2.19.5
165+
rev: v2.20.0
166166
hooks:
167167
- id: check-no-force-push
168168
stages: [pre-push]

‎docs/getting-started.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ name.
4444

4545
!!! tip "Supported Python versions"
4646

47-
Commit Check supports Python 3.10 through 3.15, on Linux, macOS and Windows.
47+
Commit Check supports Python 3.11 through 3.15, on Linux, macOS and Windows.
4848

4949
Running it as a [pre-commit hook](guides/pre-commit.md)
5050
or a [GitHub Action](guides/github-actions.md) needs no

‎docs/guides/github-actions.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ jobs:
3939
The Action reads the same `cchk.toml` as the CLI, so a repository that already
4040
has one needs no Action-specific configuration.
4141

42+
!!! note "Python 3.11 or newer"
43+
44+
The Action runs on the runner's own Python, and since v2.19.0 it needs
45+
3.11 or newer. The `*-latest` GitHub-hosted runners have it.
46+
`ubuntu-22.04` ships 3.10, so add a setup step before the Action there:
47+
48+
```yaml
49+
- uses: actions/setup-python@v7
50+
with:
51+
python-version: "3.11"
52+
```
53+
4254
## Inputs
4355

4456
| Input | Default | What it does |

‎docs/guides/policies.md‎

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ Docs: https://commit-check.com/rules/#cc013
141141

142142
Recognised signatures are co-author and sign-off lines naming Claude Code,
143143
GitHub Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby, Amp,
144-
OpenHands, Factory Droid and Jules, the disclosure trailers `Assisted-by:` and
144+
OpenHands, Factory Droid, Jules, Continue, Mistral Vibe and Qwen Code, the
145+
disclosure trailers `Assisted-by:` and
145146
`Generated-by:`, vendor marks such as `🤖 Generated with Claude Code`, Amp's
146147
`Amp-Thread-ID:`, the Copilot coding agent's `Agent-Logs-Url:` and Cursor's
147148
`Made-with: Cursor`, and generic AI model names. This is the
@@ -166,6 +167,40 @@ also commits as its own account, but every commit it makes carries an
166167
mechanism against those who aren't. Be clear with yourself about which of
167168
those you are buying.
168169

170+
### Checking AI attribution and nothing else
171+
172+
`ai_attribution` sits alongside the message rules that are on by default, so
173+
`--message` still applies Conventional Commits and the subject length limits
174+
(80 characters at most, 5 at least). A project that has its own commit style
175+
and only wants the AI check turns those off:
176+
177+
```toml title="cchk.toml"
178+
[commit]
179+
ai_attribution = "forbid"
180+
conventional_commits = false
181+
subject_max_length = 0 # 0 turns the length rule off
182+
subject_min_length = 0
183+
```
184+
185+
Or, in the GitHub Action, without a config file:
186+
187+
```yaml
188+
- uses: commit-check/commit-check-action@v2
189+
env:
190+
CCHK_AI_ATTRIBUTION: forbid
191+
CCHK_CONVENTIONAL_COMMITS: false
192+
CCHK_SUBJECT_MAX_LENGTH: 0
193+
CCHK_SUBJECT_MIN_LENGTH: 0
194+
with:
195+
message: true
196+
branch: false
197+
```
198+
199+
Leave the length limits on and a long subject fails the job too. Dependency
200+
bots write long ones: Renovate's `Update dependency
201+
com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer to
202+
v20261103` is 95 characters.
203+
169204
### Asking for disclosure instead
170205

171206
Most projects that allow AI assistance ask to be told about it.
@@ -288,6 +323,47 @@ triagers judge each contribution by whether its author can explain it in their
288323
own words. A policy like that leaves nothing for commit-check to enforce, so
289324
keep `ai_attribution` at its default, `"ignore"`.
290325

326+
### Recipes from real projects
327+
328+
Many projects enforce their AI policy with a hand-written grep step in CI.
329+
Each policy below fits in a few lines of `cchk.toml`. Add
330+
`conventional_commits = false` if your project does not use Conventional
331+
Commits (see [Checking AI attribution and nothing else](#checking-ai-attribution-and-nothing-else)).
332+
333+
| Project | Its rule for commits | `cchk.toml` |
334+
|---|---|---|
335+
| [Kubernetes](https://www.kubernetes.dev/docs/guide/pull-requests/) | No AI co-author, no AI sign-off, no `Assisted-by` | `ai_attribution = "forbid"` |
336+
| [Linux kernel](https://docs.kernel.org/process/coding-assistants.html) | Every commit signed off by a person; an AI never signs off | `ai_attribution = "disclose"`, `require_signed_off_by = true`, top-level `warn = ["ai_disclosure"]` |
337+
| Nextcloud | `Assisted-by: AGENT_NAME:MODEL_VERSION` on AI-assisted commits; an AI never signs off | `ai_attribution = "disclose"`, `ai_disclosure_pattern = '^[^:\s]+:\S+'` |
338+
| [pip](https://github.com/pypa/pip/blob/main/AI_POLICY.md), [attrs](https://github.com/python-attrs/attrs/blob/main/.github/AI_POLICY.md) | No AI co-author; disclosure not required | `ai_attribution = "disclose"`, top-level `warn = ["ai_disclosure"]` |
339+
| Fedora, FluxCD | Disclose with `Assisted-by:` | `ai_attribution = "disclose"`, `ai_disclosure_trailers = ["Assisted-by"]` |
340+
341+
The Nextcloud recipe, in full:
342+
343+
```toml title="cchk.toml"
344+
[commit]
345+
ai_attribution = "disclose"
346+
ai_disclosure_pattern = '^[^:\s]+:\S+' # AGENT_NAME:MODEL_VERSION
347+
```
348+
349+
`Assisted-by: ClaudeCode:claude-sonnet-4-6` passes. `Assisted-by: Claude Code`
350+
fails CC014 because it names no model, and `Signed-off-by: Claude
351+
<noreply@anthropic.com>` fails CC016.
352+
353+
Some projects ask every commit to say whether AI was used, with
354+
`Assisted-by: none` when it was not. `disclose` only asks when a commit shows
355+
signs of AI, so pair it with a `message_pattern` that requires the trailer:
356+
357+
```toml title="cchk.toml"
358+
[commit]
359+
ai_attribution = "disclose"
360+
message_pattern = '(?ms).*^Assisted-by:[ \t]*\S'
361+
```
362+
363+
`message_pattern` replaces the Conventional Commits check, so this recipe
364+
cannot be combined with `conventional_commits = true`. A commit with no
365+
`Assisted-by:` line fails CC001; `Assisted-by: none` passes.
366+
291367
### Exempting automation
292368

293369
Bots that legitimately carry AI trailers can be excluded:

‎docs/guides/pre-commit.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Add Commit Check to `.pre-commit-config.yaml`:
88
```yaml title=".pre-commit-config.yaml"
99
repos:
1010
- repo: https://github.com/commit-check/commit-check
11-
rev: v2.19.5
11+
rev: v2.20.0
1212
hooks:
1313
- id: check-message
1414
- id: check-branch
@@ -68,7 +68,7 @@ Options can be passed as hook arguments, which keeps everything in one file:
6868
```yaml title=".pre-commit-config.yaml"
6969
repos:
7070
- repo: https://github.com/commit-check/commit-check
71-
rev: v2.19.5
71+
rev: v2.20.0
7272
hooks:
7373
- id: check-message
7474
args:
@@ -90,7 +90,7 @@ colon, and lets the commit through:
9090
```yaml title=".pre-commit-config.yaml"
9191
repos:
9292
- repo: https://github.com/commit-check/commit-check
93-
rev: v2.19.5
93+
rev: v2.20.0
9494
hooks:
9595
- id: check-message
9696
args: [--fix]

‎docs/guides/python-api.md‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ pass 1
127127
To apply a repository's own policy, load its file and pass it along:
128128

129129
```python
130-
import tomllib # on Python 3.10: import tomli as tomllib
130+
import tomllib
131131

132132
from commit_check.api import validate_message
133133

@@ -137,8 +137,7 @@ with open("cchk.toml", "rb") as f:
137137
result = validate_message("feat: add streaming support", config=config)
138138
```
139139

140-
On Python 3.10, `tomli` is already installed: commit-check depends on it
141-
there. `inherit_from` is not followed this way; only the file's own keys
140+
`inherit_from` is not followed this way; only the file's own keys
142141
apply. Every key is in the [configuration reference](../configuration.md).
143142

144143
## Fixing until it passes

‎docs/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ description: Commit policy as code for teams and AI agents. Messages, branches,
6363
</div>
6464
<ul class="cc-wrap cc-facts">
6565
<li>MIT licensed, no account needed</li>
66-
<li>Python 3.10 – 3.15 on Linux, macOS and Windows</li>
66+
<li>Python 3.11 – 3.15 on Linux, macOS and Windows</li>
6767
<li>Signed build provenance on every release</li>
6868
<li>CLI and hook work with any Git host</li>
6969
</ul>

0 commit comments

Comments
 (0)