Skip to content

Commit 581391d

Browse files
committed
docs: bring the site in step with v2.19.0
The pre-commit pins move from v2.18.3 to v2.19.0, and the changelog gains the v2.19.0 entry (2026-10-14) with a Highlights row. - CC201 and the configuration reference document require_description_grammar, and CC201 gives the config that agrees with every Conventional Branch conformance case git can create. The default type list is described against spec 1.1.0, which includes feat, fix and the AI agent prefixes. - CC013, the AI attribution guide and the blog post name Amp, OpenHands, Factory Droid and Jules. The guide says that a bot-authored Jules or OpenHands commit with no trailer passes, since only the message is read. - The JSON samples and the Python API schema carry the new reason field, with a transcript of a skip caused by ignore_authors. - The pre-commit guide says which tags check-tag checks on a push.
1 parent 118ecdf commit 581391d

8 files changed

Lines changed: 128 additions & 22 deletions

File tree

‎docs/blog/posts/ai-commit-attribution-policy.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ sign-off.
9797

9898
The detection covers co-author and sign-off lines that name Claude Code, GitHub
9999
Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby or a model, and
100-
vendor marks such as "Generated with Claude Code". It matches the tools'
100+
vendor marks such as "Generated with Claude Code";
101+
[v2.19.0](../../changelog.md#v2190) added Amp, OpenHands, Factory Droid and
102+
Jules. It matches the tools'
101103
noreply addresses, so a human co-author who happens to be called Claude is left
102104
alone. [CC013](../../rules.md#cc013) keeps the current list.
103105

‎docs/changelog.md‎

Lines changed: 48 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.19.0](#v2190) | Branch descriptions held to the Conventional Branch grammar; Amp, OpenHands, Factory Droid and Jules recognised | [CC201](rules.md#cc201) · [CC013](rules.md#cc013) |
1415
| [2.18.3](#v2183) | `--fix` corrects a message in place; `--branch` reads GitLab, Bitbucket, Azure and Jenkins variables | [Fixing a message in place](example.md#fixing-a-message-in-place) · [Other CI](guides/other-ci.md) |
1516
| [2.18.0](#v2180) | AI disclosure policy: three rules, and the correction written for you | [Policy guides](guides/policies.md#asking-for-disclosure-instead) · [CC014](rules.md#cc014) |
1617
| [2.17.0](#v2170) | Concrete corrections for mechanical slips; a `warn` level per rule | [Reading the JSON](example.md#reading-the-json) · [Report without enforcing](configuration.md#report-a-rule-without-enforcing-it) |
@@ -30,6 +31,53 @@ below and to the page that documents the feature properly.
3031
| [2.5.0](#v250) | Organization-wide config with `inherit_from` | [Across an organization](guides/organization.md) |
3132
| [2.0.0](#v200) | Configuration moved from YAML to TOML — breaking | [Migrating from v1](migration.md) |
3233

34+
## v2.19.0 (2026-10-14) { #v2190 }
35+
36+
### Added
37+
38+
* **`require_description_grammar` checks what follows the branch type** —
39+
`conventional_branch` checks the `<type>/` prefix and accepted anything
40+
after it, so `feature/Add_Login`, `fix/header_bug` and `release/v1.-2.0`
41+
all passed. With `[branch] require_description_grammar = true` the
42+
description must follow the specification's grammar: lowercase letters and
43+
digits, words joined by single hyphens, dots only inside a word. It is off
44+
by default, because bot branches such as
45+
`dependabot/npm_and_yarn/lodash-4.17.21` do not follow that grammar.
46+
See PR [#581](https://github.com/commit-check/commit-check/pull/581) and
47+
[CC201](rules.md#cc201).
48+
49+
* **Amp, OpenHands, Factory Droid and Jules are recognised** — co-author and
50+
sign-off lines naming them (`Amp <amp@ampcode.com>`, `openhands`,
51+
`factory-droid[bot]`, `google-labs-jules[bot]`) and Amp's
52+
`Amp-Thread-ID:` trailer now count as AI attribution, for
53+
[CC013](rules.md#cc013) and for the `disclose` rules alike. People named
54+
Jules or Amp are not flagged.
55+
See PR [#606](https://github.com/commit-check/commit-check/pull/606) and
56+
[Forbidding AI-attributed commits](guides/policies.md#forbidding-ai-attributed-commits).
57+
58+
* **`--format json` says why a check was skipped** — a check skipped because
59+
the author or a co-author is on an `ignore_authors` list carries a `reason`,
60+
such as `author dependabot[bot] is in [commit].ignore_authors`. Every check
61+
has the key; it is empty when there is no reason to give.
62+
See PR [#605](https://github.com/commit-check/commit-check/pull/605) and
63+
[When a check is skipped](example.md#when-a-check-is-skipped).
64+
65+
### Fixed
66+
67+
* **`check-tag` checks the tags a push sends** — under pre-commit the hook
68+
judged the tags on `HEAD`, so a bad tag sent by `git push --follow-tags`
69+
from another branch got through, and a tag push could be rejected over a
70+
local tag on `HEAD` that it did not carry. It now checks the tag a tag push
71+
names, and on a branch push the tags on every commit the push carries.
72+
See PR [#603](https://github.com/commit-check/commit-check/pull/603).
73+
74+
* **A GitHub Actions tag build has no branch to judge** — on a tag push,
75+
`GITHUB_REF_NAME` holds the tag, so `--branch` failed
76+
[CC201](rules.md#cc201) on `v1.2.0`. A tag build now falls back to `HEAD`,
77+
which is always accepted, as tag builds on GitLab, Bitbucket, Azure and
78+
Jenkins already did.
79+
See PR [#603](https://github.com/commit-check/commit-check/pull/603).
80+
3381
## v2.18.3 (2026-10-07) { #v2183 }
3482

3583
### Added

‎docs/configuration.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,13 @@ allow_force_push = true # set false to block force pushes
222222
[branch]
223223
# https://conventionalbranch.org
224224
conventional_branch = true
225-
# changed: spec types only. The default is a superset — these plus the
226-
# Conventional Commit types, AI agent prefixes and bot prefixes — so setting
227-
# this at all narrows it. Omit the line to accept all of them.
225+
# changed: the spec's five purpose types only. The default is a superset —
226+
# these plus their aliases feat and fix, AI agent prefixes, the other
227+
# Conventional Commit types and bot prefixes — so setting this at all narrows
228+
# it. Omit the line to accept all of them.
228229
allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore"]
230+
# true also holds the part after "/" to the spec's grammar
231+
require_description_grammar = false
229232
# allow_branch_names = [] # optional: extra standalone names, e.g. ["develop"]
230233
# require_rebase_target = "main" # optional: no rebase requirement by default
231234
# ignore_authors = [] # optional: as above, for branch checks
@@ -261,7 +264,7 @@ Used from a hook definition, with no config file anywhere in the repository:
261264
```yaml title=".pre-commit-config.yaml"
262265
repos:
263266
- repo: https://github.com/commit-check/commit-check
264-
rev: v2.18.3
267+
rev: v2.19.0
265268
hooks:
266269
- id: check-message
267270
args:
@@ -306,6 +309,7 @@ The full mapping between the three forms:
306309
| `conventional_branch = true` | `CCHK_CONVENTIONAL_BRANCH=true` | `--conventional-branch=true` |
307310
| `allow_branch_types = ["feature"]` | `CCHK_ALLOW_BRANCH_TYPES=feature,bugfix` | `--allow-branch-types=feature,bugfix` |
308311
| `allow_branch_names = ["develop"]` | `CCHK_ALLOW_BRANCH_NAMES=develop,staging` | `--allow-branch-names=develop,staging` |
312+
| `require_description_grammar = true` | `CCHK_REQUIRE_DESCRIPTION_GRAMMAR=true` | `--require-description-grammar=true` |
309313
| `require_rebase_target = "main"` | `CCHK_REQUIRE_REBASE_TARGET=main` | `--require-rebase-target=main` |
310314
| `allow_force_push = true` | `CCHK_ALLOW_FORCE_PUSH=true` | `--no-force-push` (sets `allow_force_push` to `false`) |
311315
| `ai_attribution = "forbid"` | `CCHK_AI_ATTRIBUTION=forbid` | `--ai-attribution=forbid` |
@@ -371,7 +375,8 @@ the same thing twice, so read the description rather than the cell:
371375
| commit | ai_disclosure_trailers | list[str] | ["Assisted-by", "Generated-by"] | The trailers that disclose AI assistance under `"disclose"`. The first one is what a correction is written with. Listing `Co-authored-by` says the project accepts the tool as a co-author, and CC015 then passes. `Signed-off-by` is refused: only a person can certify the DCO. |
372376
| commit | ai_disclosure_pattern | str | "" (any value) | A regex the disclosure trailer's value must match under `"disclose"`, e.g. `'^\S+/\S+$'` for an `agent/model` format. Empty accepts any value, but a trailer with no value at all is reported whatever the pattern is. |
373377
| branch | conventional_branch | bool | true | Enforce Conventional Branch specification. |
374-
| branch | allow_branch_types | list[str] | ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix", "build", "ci", "docs", "perf", "refactor", "style", "test", "ai", "claude", "codex", "copilot", "cursor", "dependabot", "renovate"] | Allowed branch types when `conventional_branch` is true. The default is a superset of the [Conventional Branch spec](https://conventionalbranch.org/): the spec types (`feature`, `bugfix`, `hotfix`, `release`, `chore`) plus the Conventional Commit types (`build`, `ci`, `docs`, `perf`, `refactor`, `style`, `test`), AI agent prefixes (`ai`, `claude`, `codex`, `copilot`, `cursor`) and bot prefixes (`dependabot`, `renovate`). For strict spec-only validation, set this option explicitly (e.g. `["feature", "bugfix", "hotfix", "release", "chore"]`). |
378+
| branch | allow_branch_types | list[str] | ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix", "build", "ci", "docs", "perf", "refactor", "style", "test", "ai", "claude", "codex", "copilot", "cursor", "dependabot", "renovate"] | Allowed branch types when `conventional_branch` is true. The default is a superset of the [Conventional Branch spec](https://conventionalbranch.org/): the spec's types (`feature`, `bugfix`, `hotfix`, `release`, `chore`, their aliases `feat` and `fix`, and the AI agent prefixes `ai`, `claude`, `codex`, `copilot`, `cursor`) plus the other Conventional Commit types (`build`, `ci`, `docs`, `perf`, `refactor`, `style`, `test`) and bot prefixes (`dependabot`, `renovate`). For strict spec-only validation, set this option explicitly to the spec's types; [CC201](rules.md#cc201) has the full config. |
379+
| branch | require_description_grammar | bool | false | Also hold the description after `<type>/` to the Conventional Branch grammar: lowercase letters and digits, words joined by single hyphens, dots only inside a word. Off by default, because bot branches such as `dependabot/npm_and_yarn/lodash-4.17.21` do not follow it. See [CC201](rules.md#cc201). |
375380
| branch | allow_branch_names | list[str] | [] (empty list) | Additional standalone branch names allowed when conventional_branch is true (e.g., ["develop", "staging"]). By default, master, main, HEAD, and PR-* are always allowed. |
376381
| branch | require_rebase_target | str | "" (no requirement) | Target branch for rebase requirement. If not set, no rebase validation is performed. |
377382
| push | allow_force_push | bool | true | Allow force pushes. Set to `false` to block force pushes when used as a pre-push hook or with `--no-force-push`. |

‎docs/example.md‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pushed:
159159
```yaml title=".pre-commit-config.yaml"
160160
repos:
161161
- repo: https://github.com/commit-check/commit-check
162-
rev: v2.18.3
162+
rev: v2.19.0
163163
hooks:
164164
- id: check-no-force-push
165165
stages: [pre-push]
@@ -286,6 +286,18 @@ $ echo "Merge branch 'main' into topic" | commit-check -m --no-banner
286286
```
287287

288288
In JSON each skipped check carries `"status": "skip"`, distinct from `"pass"`.
289+
When a check is skipped because the author or a co-author is on an
290+
`ignore_authors` list, `reason` says so. Here `HEAD` is a Dependabot commit
291+
and `cchk.toml` lists `dependabot[bot]` under `[commit] ignore_authors`:
292+
293+
```console
294+
$ commit-check -m --rev HEAD --format json | jq -c '.checks[] | {rule_id, status, reason}'
295+
{"rule_id":"CC001","status":"skip","reason":"author dependabot[bot] is in [commit].ignore_authors"}
296+
{"rule_id":"CC004","status":"skip","reason":"author dependabot[bot] is in [commit].ignore_authors"}
297+
{"rule_id":"CC005","status":"skip","reason":"author dependabot[bot] is in [commit].ignore_authors"}
298+
```
299+
300+
For any other skip, such as a merge subject, `reason` is empty.
289301

290302
!!! warning "A green run can still have validated nothing"
291303

@@ -323,7 +335,8 @@ $ echo "Fix: add streaming support" | commit-check -m --format json | jq '.check
323335
"error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org",
324336
"suggest": "Use \"fix: add streaming support\"",
325337
"fix": "fix: add streaming support",
326-
"docs_url": "https://commit-check.com/rules/#cc001"
338+
"docs_url": "https://commit-check.com/rules/#cc001",
339+
"reason": ""
327340
}
328341
```
329342

‎docs/guides/policies.md‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,18 @@ Docs: https://commit-check.com/rules/#cc013
132132
```
133133

134134
Recognised signatures are co-author and sign-off lines naming Claude Code,
135-
GitHub Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf and Tabby, the
136-
disclosure trailers `Assisted-by:` and `Generated-by:`, vendor marks such as
137-
`🤖 Generated with Claude Code`, and generic AI model names. This is the
135+
GitHub Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby, Amp,
136+
OpenHands, Factory Droid and Jules, the disclosure trailers `Assisted-by:` and
137+
`Generated-by:`, vendor marks such as `🤖 Generated with Claude Code` and
138+
Amp's `Amp-Thread-ID:`, and generic AI model names. This is the
138139
position [Kubernetes](https://www.kubernetes.dev/docs/guide/pull-requests/)
139140
takes — no AI trailers in the history, disclosure in the pull request
140141
instead.
141142

143+
These rules read only the message. Jules and OpenHands can commit under their
144+
own bot identity instead of adding a co-author line, and such a commit passes
145+
when its message carries no trailer.
146+
142147
!!! warning "This checks disclosure, not authorship"
143148

144149
These rules read commit metadata. They detect a commit that *says* it

‎docs/guides/pre-commit.md‎

Lines changed: 7 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.18.3
11+
rev: v2.19.0
1212
hooks:
1313
- id: check-message
1414
- id: check-branch
@@ -50,6 +50,10 @@ The three `pre-push` hooks need their own install too:
5050
$ pre-commit install --hook-type pre-push
5151
```
5252

53+
`check-tag` checks the tags the push sends: the tag a tag push names, and on
54+
a branch push, such as `git push --follow-tags`, the tags on every commit the
55+
push carries.
56+
5357
pre-commit runs no hook for a push that creates a ref without carrying new
5458
commits. So a new tag pushed on its own, when the commit it points at is
5559
already on the remote, is never seen by `check-tag`.
@@ -61,7 +65,7 @@ Options can be passed as hook arguments, which keeps everything in one file:
6165
```yaml title=".pre-commit-config.yaml"
6266
repos:
6367
- repo: https://github.com/commit-check/commit-check
64-
rev: v2.18.3
68+
rev: v2.19.0
6569
hooks:
6670
- id: check-message
6771
args:
@@ -83,7 +87,7 @@ colon, and lets the commit through:
8387
```yaml title=".pre-commit-config.yaml"
8488
repos:
8589
- repo: https://github.com/commit-check/commit-check
86-
rev: v2.18.3
90+
rev: v2.19.0
8791
hooks:
8892
- id: check-message
8993
args: [--fix]

‎docs/guides/python-api.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Every function returns the same shape:
7070
"suggest": "...", # advice for a person
7171
"fix": "...", # the corrected value, or "" when it takes judgment
7272
"docs_url": "https://commit-check.com/rules/#cc001",
73+
"reason": "...", # why a skipped check did not run, when known; else ""
7374
},
7475
],
7576
}
@@ -80,7 +81,8 @@ Every function returns the same shape:
8081
- **`skip` is not `pass`.** A check skips when it never ran — the author is in
8182
`ignore_authors`, or there was nothing to check — and the top-level `status`
8283
is `skip` only when every check skipped. A skipped run validated nothing, so
83-
do not read it as approval.
84+
do not read it as approval. When the author or a co-author is in
85+
`ignore_authors`, the check's `reason` names them.
8486
- **`warn`** is a rule listed under the config's `warn`: reported in full,
8587
never a failure. The top-level `status` stays `pass`, and `warnings` counts
8688
them.

‎docs/rules.md‎

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,10 @@ git commit --amend --signoff
537537

538538
Rejects a commit whose message carries any AI attribution: a co-author or
539539
sign-off line naming Claude Code, Copilot, Codex, Gemini, Cursor, Devin,
540-
Aider, Windsurf or Tabby, a disclosure trailer such as `Assisted-by:` or
541-
`Generated-by:`, a vendor's own mark such as `🤖 Generated with Claude Code`,
542-
and generic AI model names.
540+
Aider, Windsurf, Tabby, Amp, OpenHands, Factory Droid or Jules, a disclosure
541+
trailer such as `Assisted-by:` or `Generated-by:`, a vendor's own mark such
542+
as `🤖 Generated with Claude Code` or Amp's `Amp-Thread-ID:` trailer, and
543+
generic AI model names.
543544

544545
**Why is this bad?**
545546

@@ -762,6 +763,11 @@ Checks that the current branch name follows the
762763

763764
`master`, `main`, `HEAD`, and `PR-*` are always accepted.
764765

766+
By default only the type is checked, and any description after the `/` is
767+
accepted. With `require_description_grammar` the description has to follow
768+
the specification's grammar too: lowercase letters and digits, words joined
769+
by single hyphens, dots only inside a word, as in `release/v1.2.0`.
770+
765771
**Why is this bad?**
766772

767773
A predictable prefix is something automation can act on: CI can skip expensive
@@ -787,14 +793,35 @@ feature/role-caching
787793

788794
* `branch.conventional_branch` — set to `false` to disable this rule.
789795
* `branch.allow_branch_types` — the accepted `<type>` values. The default is
790-
a superset of the specification: the spec types plus the Conventional Commit
791-
types, AI agent prefixes (`ai`, `claude`, `codex`, `copilot`,
792-
`cursor`), and bot prefixes (`dependabot`, `renovate`). Set it
793-
explicitly for strict spec-only validation.
796+
a superset of the specification: the spec's types (`feature`, `bugfix`,
797+
`hotfix`, `release`, `chore`, their aliases `feat` and `fix`, and the AI
798+
agent prefixes `ai`, `claude`, `codex`, `copilot` and `cursor`), plus the
799+
other Conventional Commit types and the bot prefixes `dependabot` and
800+
`renovate`. Set it explicitly for strict spec-only validation.
801+
* `branch.require_description_grammar` — set to `true` to hold the
802+
description to the specification's grammar, so `feature/Add_Login`,
803+
`feature/new--login` and `feature/a/b` are rejected. Off by default,
804+
because bot branches such as `dependabot/npm_and_yarn/lodash-4.17.21` do
805+
not follow it.
794806
* `branch.allow_branch_names` — additional standalone names to accept, such as
795807
`["develop", "staging"]`.
796808
* `branch.ignore_authors` — bypass the check for specific authors.
797809

810+
To check branches exactly as the specification does, set the spec's types,
811+
the description grammar, and its third trunk branch, `develop`:
812+
813+
```toml title="cchk.toml"
814+
[branch]
815+
conventional_branch = true
816+
allow_branch_types = ["feature", "feat", "bugfix", "fix", "hotfix", "release", "chore", "ai", "claude", "codex", "copilot", "cursor"]
817+
require_description_grammar = true
818+
allow_branch_names = ["develop"]
819+
```
820+
821+
With that, `commit-check --branch` agrees with every case of the
822+
specification's [conformance suite](https://github.com/conventional-branch/conventional-branch/blob/main/tests/fixtures.json)
823+
that git can create as a branch.
824+
798825
### merge-base (CC202) { #cc202 }
799826

800827
**What it does**

0 commit comments

Comments
 (0)