diff --git a/docs/changelog.md b/docs/changelog.md index f05bc24..01fe8fa 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,89 @@ All **notable changes** to this project will be documented in this file. Full changelog available at [GitHub releases](https://github.com/commit-check/commit-check/releases). +## v2.13.0 (2026-08-04) + +### New Features + +* **Stable rule IDs** — every diagnostic now carries an ID such as `CC003` that + never changes once released. The ID appears in terminal output and in + `--format json` as `rule_id`, alongside a `docs_url` pointing at the rule's + section of the [rules reference](rules.md), so a failure can be cited in + review, looked up, or matched by tooling. + See PR [#512](https://github.com/commit-check/commit-check/pull/512). +* **More branch types accepted by default** — `docs/`, `ci/`, `test/`, + `refactor/`, `build/`, `perf/` and `style/` join the default + `allow_branch_types`, which stays a superset of the Conventional Branch + specification. + See PR [#505](https://github.com/commit-check/commit-check/pull/505). + +### Bug Fixes + +* **Rule IDs link to their documentation** — where the terminal renders OSC 8 + hyperlinks, the ID itself is the link and the separate `Docs:` line is + dropped. Piped output and CI logs keep the printed URL. Failure output also + names rules the way the reference titles them (`subject-min-length` rather + than `subject_min_length`), and the advice for the length rules now names the + configured limit instead of referring to it. + See PR [#520](https://github.com/commit-check/commit-check/pull/520). + +### Documentation + +* The documentation, the landing page and the blog moved to + [commit-check.com](https://commit-check.com) and are published from one + domain. `docs.commit-check.com` URLs redirect. + See PRs [#515](https://github.com/commit-check/commit-check/pull/515), + [#518](https://github.com/commit-check/commit-check/pull/518) and + [#519](https://github.com/commit-check/commit-check/pull/519). + +## v2.12.2 (2026-08-01) + +### Bug Fixes + +* **Space-separated AI model names** — Co-author trailers naming a model with + spaces rather than hyphens are now recognised by the AI attribution check. + See PR [#506](https://github.com/commit-check/commit-check/pull/506). + +### Chores + +* Recognised more common imperative verbs, so ordinary subjects stop being + rejected by `subject_imperative`. + See PR [#496](https://github.com/commit-check/commit-check/pull/496). + +## v2.12.1 (2026-07-31) + +### Bug Fixes + +* **Running without the package installed** — `PackageNotFoundError` is handled + instead of crashing when the version cannot be resolved. + See PR [#483](https://github.com/commit-check/commit-check/pull/483). +* Hardened the `pip install` step flagged by SonarCloud code scanning. + See PR [#479](https://github.com/commit-check/commit-check/pull/479). + +## v2.12.0 (2026-07-24) + +### New Features + +* **Configurable author patterns** — `author_name` and `author_email` accept a + custom regex, so organisations can require their own naming or email domain + instead of the built-in patterns. + See PR [#459](https://github.com/commit-check/commit-check/pull/459). + +### Bug Fixes + +* **Crash on Chinese Windows** — commit messages are no longer decoded with the + system GBK codec, which raised `UnicodeDecodeError`. + See PR [#475](https://github.com/commit-check/commit-check/pull/475). +* **Author validation reads git config first** — `git config user.name` is the + identity the *next* commit will carry, so it is checked before falling back + to the last commit's author. A misconfigured identity used to pass whenever + the previous commit happened to be valid. + See PR [#461](https://github.com/commit-check/commit-check/pull/461). +* `require_signed_off_by` accepts any name, and is skipped for authors listed + in `ignore_authors`. + See PRs [#462](https://github.com/commit-check/commit-check/pull/462) and + [#464](https://github.com/commit-check/commit-check/pull/464). + ## v2.11.0 (2026-07-06) ### New Features diff --git a/docs/guides/ai-attribution.md b/docs/guides/ai-attribution.md index e93a907..7ffdac7 100644 --- a/docs/guides/ai-attribution.md +++ b/docs/guides/ai-attribution.md @@ -34,7 +34,7 @@ ai_attribution = "forbid" Commits carrying a recognised AI signature now fail: ```text -CC013 ai_attribution check failed ==> feat: add caching layer +CC013 ai-attribution check failed ==> feat: add caching layer AI attribution policy violation Suggest: This project forbids AI-assisted commits. Remove AI trailers and re-commit. Docs: https://commit-check.com/rules/#cc013 diff --git a/docs/index.md b/docs/index.md index 4a24c97..01c36e1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,7 +20,7 @@ whatever your AI agent is committing on your behalf. ```console $ commit-check --message --branch - CC003 subject_imperative check failed ==> docs: revamped the profile + CC003 subject-imperative check failed ==> docs: revamped the profile Commit message should use imperative mood (e.g., 'fix bug' not 'fixed bug') Suggest: Change the first verb to imperative form Docs: https://commit-check.com/rules/#cc003 diff --git a/docs/rules.md b/docs/rules.md index f8333c4..cf19ec4 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -7,7 +7,7 @@ review comments, issue templates, and tooling. Rule IDs appear in commit-check's output and in `--format json` results: ```text -CC003 subject_imperative check failed ==> docs: revamped the profile +CC003 subject-imperative check failed ==> docs: revamped the profile Commit message should use imperative mood (e.g., 'fix bug' not 'fixed bug') Suggest: Change the first verb to imperative form, e.g., 'fix' instead of 'fixed' Docs: https://commit-check.com/rules/#cc003 diff --git a/docs/what-is-new.md b/docs/what-is-new.md index 4858f8e..a64fc17 100644 --- a/docs/what-is-new.md +++ b/docs/what-is-new.md @@ -4,6 +4,42 @@ The changes worth knowing about, newest first, each pointing at the page that documents it properly. For the full record of every change, see the [changelog](changelog.md). +## 2.13.0 — Stable rule IDs + +Every diagnostic now carries an ID that never changes once released, so a +failure can be cited in review, looked up, or matched by tooling. + +```console +$ commit-check --message +CC003 subject-imperative check failed ==> docs: revamped the profile +Commit message should use imperative mood (e.g., 'fix bug' not 'fixed bug') +Suggest: Change the first verb to imperative form +Docs: https://commit-check.com/rules/#cc003 +``` + +The ID also appears in `--format json` as `rule_id`, next to a `docs_url`. In a +terminal that renders hyperlinks the ID *is* the link, and the `Docs:` line is +dropped — piped output and CI logs keep it. + +`docs/`, `ci/`, `test/`, `refactor/`, `build/`, `perf/` and `style/` also join +the default branch types. + +[:octicons-arrow-right-24: Rules reference](rules.md) + +## 2.12.0 — Custom author patterns + +`author_name` and `author_email` accept a regex of your own, so a team can +require its own naming convention or email domain rather than the built-in +patterns. + +```toml title="cchk.toml" +[commit] +author_email = "^.+@example\\.com$" +``` + +[:octicons-arrow-right-24: CC101](rules.md#cc101) · +[CC102](rules.md#cc102) + ## 2.11.0 — AI attribution policy Commits carrying the trailers AI coding tools add — Claude Code, Copilot, diff --git a/tests/docs_sync_test.py b/tests/docs_sync_test.py index 2236425..80d174d 100644 --- a/tests/docs_sync_test.py +++ b/tests/docs_sync_test.py @@ -28,6 +28,10 @@ def _read_doc(name: str) -> str: return (DOCS / name).read_text(encoding="utf-8") +#: A pasted failure line, e.g. ``CC003 subject-imperative check failed ==> ...`` +_SAMPLE_FAILURE = re.compile(r"(CC\d{3}) (\S+) check failed ==>") + + def _rule_section(content: str, rule_id: str) -> str: """Return just the part of the rules page belonging to one rule.""" _, _, after = content.partition(f"{{ #{rule_id.lower()} }}") @@ -57,6 +61,27 @@ def test_every_rule_has_a_section_heading(self): f"docs/rules.md has no section titled '{heading}'" ) + def test_sample_output_matches_what_the_tool_prints(self): + """Pasted terminal output has to name rules the way the tool does. + + These blocks are transcripts, so nothing regenerates them and nothing + else here reads them: the heading and options-table guards both look + at reference tables. When the printed name moved from the config key + to its kebab-case form, six samples across four pages kept showing the + old one and every test still passed. + """ + by_id = {entry.rule_id: entry for entry in ALL_RULES} + stale = [] + for page in DOCS.rglob("*.md"): + for rule_id, printed in _SAMPLE_FAILURE.findall(page.read_text("utf-8")): + entry = by_id.get(rule_id) + if entry and printed != entry.name: + stale.append( + f"{page.relative_to(DOCS)}: {rule_id} shown as " + f"'{printed}', the tool prints '{entry.name}'" + ) + assert not stale, "sample output is out of date:\n " + "\n ".join(stale) + def test_every_rule_explains_itself(self): """Each rule section must answer what it does and why it matters.""" content = _read_doc("rules.md")