Skip to content

docs: rebuild the documentation site as a product surface - #515

Merged
shenxianpeng merged 9 commits into
mainfrom
docs/left-sidebar-and-rules-reference
Aug 3, 2026
Merged

docs: rebuild the documentation site as a product surface#515
shenxianpeng merged 9 commits into
mainfrom
docs/left-sidebar-and-rules-reference

Conversation

@shenxianpeng

@shenxianpeng shenxianpeng commented Aug 3, 2026

Copy link
Copy Markdown
Member

Rebuilds the documentation site: new information architecture, a real landing page, MkDocs Material in place of Sphinx, and nine corrections where the docs did not describe the software. Includes #516.

The problem

The site read as a repository, not a product. docs/index.md was a one-line include of ../README.md, so the front door of docs.commit-check.com was eight CI badges above a hand-written ## Table of Contents. Badges are a trust signal for GitHub visitors and a ToC is a workaround for GitHub's lack of navigation — neither belongs on a documentation site.

Behind it, everything was reference material. There was no installation page, no tutorial, and no task-oriented guides. Navigation was a top tab bar, so only one section's pages were reachable at a time.

Framework

MkDocs Material, replacing Sphinx + sphinx-immaterial:

  • It is what ruff and uv use, which is the look this project has been aiming at.
  • The toolchain stays Python. Docs deps live in pyproject.toml, CI stays a single pip install, and contributors need no Node — which matters while we are recruiting them through good-first-issues.
  • sphinx-immaterial was a partial port of it, so palette, admonitions and feature flags carried over almost unchanged. Docs extras drop from five packages to one.

Navigation moves to a left sidebar grouped into sections, and on the rules page the sidebar nests that page's own table of contents, putting every rule one click away.

Content

A landing page with a value proposition, the same policy shown running four ways (CLI / pre-commit / GitHub Actions / MCP) in linked tabs, and cards routing each rule family to its reference.

The pages the site never had:

Section Pages
Getting started Installation, Quick start, Why Commit Check
Guides Pre-commit, GitHub Actions, Organization-wide policy, Signoff and DCO, AI attribution, Command-line recipes
Reference Rules, Configuration, CLI
About Migrating from v1, Troubleshooting, Release highlights, Changelog

The rules reference is rewritten along the lines of a linter's rule documentation: an index table per category giving each rule's code, name, message, the CLI flag that runs it and whether it is on by default, then a section per rule answering What it does / Why is this bad? / Example + Use instead / Options.

The Check column closes a real gap — nothing previously told a reader that commit-check --message never evaluates a branch rule.

Brand: the 10 KB JPEG logo becomes a 483-byte SVG, and there is a favicon for the first time; the Sphinx config had it commented out.

Corrections

Cross-checking every rule against the source turned up nine places where the documentation did not describe the software.

Option Documented Actual
subject_max_length no limit 80
subject_min_length no limit 5
subject_capitalized true false
subject_imperative true false
allow_empty_commits false true
allow_wip_commits false true
allow_commit_types 7 types 10 (missing perf, build, ci)
author_email_pattern "" ^.+@.+$
require_rebase_target None ""

The subject-length pair matters most. ConfigMerger.from_all_sources() starts from get_default_config(), which sets both, so CC004 and CC005 are enforced out of the box. Verified end to end rather than by reading:

$ git commit --allow-empty -m "fix: this is a deliberately very long commit subject line that goes well past the eighty character limit"
$ commit-check --message --compact      # no config file anywhere
[FAIL] CC004 subject_max_length: fix: this is a deliberately very long ...
exit=1

Also fixed:

  • Wrong section path. CC201's option is branch.conventional_branch, documented under commit. — where configuration merging would silently ignore it.
  • Options that do not exist. required_signoff_name and required_signoff_email appeared in the example config but are implemented nowhere. Removed; if they are wanted, that is a feature request.
  • Examples that passed the check they illustrated. root satisfies the built-in author name pattern and root@localhost satisfies ^.+@.+$, so neither demonstrated a failure. Both now use values that actually fail, with a note on how permissive the built-in patterns are.

Things that could have broken the live site

Rule URLs. MkDocs serves directory URLs, so anchors move from /rules.html#cc003 to /rules/#cc003, and RULES_DOCS_URL follows. Safe to change only because the rule-ID feature has not shipped to PyPI yet — no released version emits the old form.

Published links. A build hook emits a redirect stub for every URL the Sphinx site served, since links to configuration.html and friends exist in the README, on PyPI and elsewhere.

The custom domain. gh-pages carries a CNAME of docs.commit-check.com and the publish step force-replaces that branch, so cname: is now pinned explicitly on the action rather than relying on the file surviving.

Deploy previews. Netlify's build settings lived in its web UI and still pointed at Sphinx's _build/html, so nothing in the repository could show the mismatch in review. The build moves into netlify.toml, and previews set SITE_URL to their own address — otherwise canonical links and redirect stubs would send a reviewer from the preview back to production.

Tests

The anti-drift guards are rebuilt around get_default_config(), the dict the CLI actually builds its configuration from, and follow the content into Markdown:

  • test_documented_defaults_match_the_runtime — every documented default across bool, int, str, list[str]
  • test_every_runtime_option_is_documented — a new option cannot ship undocumented
  • test_no_invented_options_are_documented — the table cannot describe options that do not exist
  • test_every_rule_has_a_section_heading / test_every_rule_explains_itself — each rule needs a real section, not just an anchor

Confirmed they fail on the pre-fix content rather than passing vacuously:

AssertionError: docs/configuration.md documents [commit] subject_max_length as 'None (no limit)', but the runtime default is 80
AssertionError: docs/configuration.md documents [commit] required_signoff_name, which does not exist in get_default_config()

All 24 runtime options parse and match. The documentation-consistency tests also lost their benchmark marker: they read files rather than exercising the package, so benchmarking them reported a regression every time the documentation grew — penalising the act of writing it.

$ mkdocs build --strict
Documentation built in 0.77 seconds        # zero warnings

$ pytest tests/ -q
460 passed

The one failing test, test_load_config_file_permission_error, reproduces on main and is unrelated: it uses os.chmod(0o000), which does not restrict root.

Not in this PR

example.md and what-is-new.md are carried over converted but not rewritten — they overlap the new guides and the changelog, and folding them in is a content decision worth making separately. Social cards are not enabled; the plugin needs cairo in CI.

Summary by CodeRabbit

  • Documentation

    • Rebuilt the documentation site with a modern layout, improved navigation, branding, and responsive color themes.
    • Added installation, quick-start, configuration, migration, troubleshooting, integration, organization policy, signoff, AI attribution, and rule reference guides.
    • Added current and historical release notes, including “What’s New.”
    • Added automatically generated CLI reference documentation and redirects from legacy documentation URLs.
  • Deployment

    • Updated documentation builds and publishing to support the new site and custom domain.
  • Tests

    • Added checks to keep documented rules, options, and defaults aligned with the product.

Replace the top tab bar with a left sidebar, and group the pages into
Getting started / Configuring / Reference / About so the whole
documentation set is visible at a glance instead of one tab at a time.
On a rule page the sidebar also nests that page's own table of contents,
putting every rule one click away.

Rewrite the rules reference along the lines of a linter's rule
documentation: an index table per category giving each rule's code,
name, message, the CLI flag that runs it, and whether it is on by
default, followed by a section per rule answering what it does, why it
matters, and how to fix it, with a before/after example and the options
that control it.

Correct several defaults in the configuration reference that had drifted
from the source: subject_capitalized and subject_imperative are off by
default (documented as on), allow_empty_commits and allow_wip_commits
are on (documented as off), and allow_commit_types was missing perf,
build, and ci. The "Default Behavior" tip repeated the same mistake.

Guard all of it with tests, so the documentation cannot drift again:
documented boolean and list defaults are compared against the values in
commit_check/__init__.py, and every rule must have a section heading
that answers what it does, why it is bad, and which options apply.

Also fix four reStructuredText title underlines that were shorter than
their titles, letting the docs build cleanly under -W.
@shenxianpeng
shenxianpeng requested a review from a team as a code owner August 3, 2026 14:22
@netlify

netlify Bot commented Aug 3, 2026

Copy link
Copy Markdown

Deploy Preview for commit-check ready!

Name Link
🔨 Latest commit 02c7088
🔍 Latest deploy log https://app.netlify.com/projects/commit-check/deploys/6a70e5829e8ffc0008c77647
😎 Deploy Preview https://deploy-preview-515--commit-check.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests Add test related changes labels Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@shenxianpeng, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ca487e7a-e78e-473f-8b8e-04feb0ab69bd

📥 Commits

Reviewing files that changed from the base of the PR and between 2fbd4c0 and 02c7088.

⛔ Files ignored due to path filters (1)
  • docs/assets/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (2)
  • netlify.toml
  • scripts/mkdocs_hooks.py
📝 Walkthrough

Walkthrough

The project migrated its documentation from Sphinx and reStructuredText to MkDocs Material and Markdown. It added site content, build hooks, deployment settings, legacy redirects, and documentation consistency tests.

Changes

MkDocs documentation migration

Layer / File(s) Summary
MkDocs build and deployment
mkdocs.yml, scripts/mkdocs_hooks.py, noxfile.py, pyproject.toml, netlify.toml, .github/workflows/main.yml, .gitignore, .pre-commit-config.yaml, docs/assets/extra.css
MkDocs Material now builds the site, generates CLI documentation, creates legacy redirects, applies custom styling, and publishes the site directory.
Documentation content and navigation
docs/index.md, docs/getting-started/*, docs/guides/*, docs/troubleshoot.md, docs/changelog.md, docs/what-is-new.md
Markdown pages document installation, quick start, integrations, troubleshooting, rationale, and release history.
Configuration and migration guidance
docs/configuration.md, docs/example.md, docs/migration.md
The documentation covers TOML configuration, inheritance, precedence, CLI usage, examples, and migration from YAML.
Rules reference and documentation contracts
docs/rules.md, commit_check/rules_catalog.py, tests/rules_catalog_test.py
The rules reference uses Markdown. The rules URL uses /rules/. Tests validate rule sections, documented options, and runtime defaults.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: major

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: rebuilding the documentation site as a product-oriented surface with a new documentation stack and structure.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/left-sidebar-and-rules-reference

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.43%. Comparing base (bfb5eb1) to head (02c7088).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #515      +/-   ##
==========================================
+ Coverage   97.34%   97.43%   +0.08%     
==========================================
  Files          12       12              
  Lines        1207     1207              
==========================================
+ Hits         1175     1176       +1     
+ Misses         32       31       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
docs/_static/extra_css.css (1)

67-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Scope the white-space rule to rule index tables.

.md-typeset table td code applies to every table, although the comment says it targets rule index tables. A long code literal in a configuration or migration table can then force horizontal scrolling. Add a table-specific class and scope this selector to that class.

Proposed scope
-.md-typeset table td code {
+.rules-index-table td code {
   white-space: nowrap;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/_static/extra_css.css` around lines 67 - 69, Update the `.md-typeset
table td code` selector in the stylesheet to target only tables marked with the
rule index table class, and add or reuse that class on the relevant rule index
table markup. Keep the `white-space: nowrap` behavior unchanged for rule index
tables while preventing it from applying to other tables.
tests/rules_catalog_test.py (1)

131-143: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Scope the heading assertion to each rule section.

test_every_rule_has_a_section_heading searches the entire page. A heading can remain elsewhere while its own rule section loses the heading, and the test still passes. Reuse the anchor-bounded section logic from test_every_rule_explains_itself and check the heading inside that section.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/rules_catalog_test.py` around lines 131 - 143, Update
test_every_rule_has_a_section_heading to reuse the anchor-bounded section
extraction logic from test_every_rule_explains_itself, then assert each rule’s
“name (rule_id)” heading appears within its corresponding section rather than
anywhere in the full document.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/configuration.rst`:
- Around line 27-30: Align the documentation with the runtime subject-length
defaults: in docs/configuration.rst lines 27-30, state that subject length is
constrained by minimum 5 and maximum 80 characters; in docs/rules.rst lines
114-123, mark CC004 and CC005 as enabled by default; document subject_max_length
as 80 at lines 385-386 and subject_min_length as 5 at lines 417-418.
- Line 430: Update the author_email_pattern entry in the configuration
documentation to match the runtime default ^.+@.+$ defined by the configuration
merger, unless the implementation is intentionally changed to use an empty
sentinel; keep the documentation and runtime behavior consistent.

In `@docs/rules.rst`:
- Around line 783-790: Update the Options entry in the documentation to
reference branch.conventional_branch instead of commit.conventional_branch,
matching the configuration key used by config_merger.py. Keep the existing
disable-rule behavior and surrounding branch.allow_branch_types guidance
unchanged.
- Around line 719-739: Update the email-pattern rule documentation example so it
does not claim root@localhost violates the built-in ^.+@.+$ pattern; use an
address that fails that pattern, or explicitly state that rejecting local or
placeholder addresses requires a stricter author_email_pattern.

In `@tests/rules_catalog_test.py`:
- Around line 159-182: The test_boolean_defaults_match_configuration_docs method
must also validate the conventional-check defaults. Extend expected with
conventional_commits=True and conventional_branch=True, or derive those values
from get_default_config(), while preserving the existing DEFAULT_BOOLEAN_RULES
and DEFAULT_PUSH_RULES checks.

---

Nitpick comments:
In `@docs/_static/extra_css.css`:
- Around line 67-69: Update the `.md-typeset table td code` selector in the
stylesheet to target only tables marked with the rule index table class, and add
or reuse that class on the relevant rule index table markup. Keep the
`white-space: nowrap` behavior unchanged for rule index tables while preventing
it from applying to other tables.

In `@tests/rules_catalog_test.py`:
- Around line 131-143: Update test_every_rule_has_a_section_heading to reuse the
anchor-bounded section extraction logic from test_every_rule_explains_itself,
then assert each rule’s “name (rule_id)” heading appears within its
corresponding section rather than anywhere in the full document.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e74e61a-27a4-4f7d-bd9d-1355c7c15eb7

📥 Commits

Reviewing files that changed from the base of the PR and between bfb5eb1 and 0eb515a.

📒 Files selected for processing (8)
  • docs/_static/extra_css.css
  • docs/changelog.rst
  • docs/conf.py
  • docs/configuration.rst
  • docs/index.md
  • docs/migration.rst
  • docs/rules.rst
  • tests/rules_catalog_test.py

Comment thread docs/configuration.rst Outdated
Comment thread docs/configuration.rst Outdated
Comment thread docs/rules.rst Outdated
Comment thread docs/rules.rst Outdated
Comment thread tests/rules_catalog_test.py
… runtime

The subject-length rules are on by default, not off. `get_default_config()`
sets subject_max_length to 80 and subject_min_length to 5, and
`ConfigMerger.from_all_sources()` starts from it, so with no config file at
all a subject over 80 characters fails CC004. Both the rules reference and
the configuration reference claimed there was no limit.

The same review turned up four more inaccuracies:

- author_email_pattern defaults to `^.+@.+$`, not an empty string.
- require_rebase_target defaults to `""`, not None.
- CC201's option is branch.conventional_branch; it was documented under the
  commit section, where configuration merging would ignore it.
- required_signoff_name and required_signoff_email were documented in the
  example config and in CC012's options, but no such options exist anywhere
  in the code.

Two rule examples also demonstrated values that pass the very check they
illustrate: `root` satisfies the built-in author name pattern, and
`root@localhost` satisfies `^.+@.+$`. Both now use values that actually fail,
with a note explaining how permissive the built-in patterns are and when to
replace them.

Rework the drift guard so this class of error is caught mechanically. Rather
than comparing against a couple of constants, the options table is now parsed
and every row checked against `get_default_config()` — the same dict the CLI
builds its configuration from. Two further tests assert the table and the
runtime describe the same set of options, in both directions, which is what
catches an invented option like required_signoff_name or a newly added one
that nobody documented.

Also scope the rule-index table styling to those tables so long regexes in
the configuration table stay wrappable, and check each rule's heading inside
its own section instead of anywhere on the page.

Copy link
Copy Markdown
Member Author

Verified all seven comments against the source. All seven were correct, and the first one was worse than reported — fixed in 0f4c3ca.

Subject-length defaults (major). Confirmed end-to-end, not just by reading:

$ git commit --allow-empty -m "fix: this is a deliberately very long commit subject line that goes well past the eighty character limit"
$ commit-check --message --compact      # no config file anywhere
[FAIL] CC004 subject_max_length: fix: this is a deliberately very long ...
exit=1

ConfigMerger.from_all_sources() starts from get_default_config() (config_merger.py:218), which sets subject_max_length = 80 and subject_min_length = 5. CC004 and CC005 are on by default. Fixed in the index table, both rule sections, the options table, the example config, and the "Default Behavior" tip.

author_email_pattern / require_rebase_target / branch.conventional_branch — all confirmed and fixed. The section path was the worst of the three: a user copying commit.conventional_branch into their config would have had it silently ignored by config merging.

root@localhost — right, ^.+@.+$ accepts it. Checking the other example in the same pair, root also passes the built-in name pattern, so that one was wrong too. Both examples now use values that actually fail (ec2-user fails the name pattern on the digit; the email example now shows a configured company-domain pattern), each with a note on how permissive the built-in patterns are.

While fixing these I also found that required_signoff_name and required_signoff_email do not exist anywhere in the code — they only ever appeared in the example config, and I had propagated them into CC012's options. Removed.

Drift test. Took the suggestion further rather than adding two literals. The test now parses the options table and checks every row against get_default_config() itself, so it covers conventional_commits, conventional_branch, and the string and integer defaults the previous version ignored — including the subject_max_length error above, which it now catches on its own. Two more tests assert the table and the runtime describe the same set of options in both directions, which is what would have caught required_signoff_name.

Confirmed the guards fail on the pre-fix content rather than passing vacuously:

AssertionError: docs/configuration.rst documents [commit] subject_max_length as 'None (no limit)', but the runtime default is 80
AssertionError: docs/configuration.rst documents [commit] required_signoff_name, which does not exist in get_default_config()

All 24 runtime options parse and match.

Both nitpicks applied. The index tables carry a rules-index class and the nowrap rule is scoped to it, so long regexes in the configuration table stay wrappable; the heading assertion is now scoped to each rule's own section.

Docs still build clean under -W, 460 tests pass.


Generated by Claude Code

The regex match may be None, so reading .group() from it before the None
check failed mypy and took the lint session down with it.
@codspeed-hq

codspeed-hq Bot commented Aug 3, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by ×3.6

⚡ 1 improved benchmark
✅ 402 untouched benchmarks
⏩ 116 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
test_empty_message_passes 8.3 ms 2.3 ms ×3.6

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing docs/left-sidebar-and-rules-reference (02c7088) with main (bfb5eb1)

Open in CodSpeed

Footnotes

  1. 116 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

CodSpeed reported test_every_rule_is_documented as a 27% regression. It is
not one: that test reads docs/rules.rst and scans it for anchors, and this
branch grows that file from 7.4 KB to 22.2 KB. A 2.99x larger file taking
1.37x longer to read is the expected, sub-linear result, and no runtime code
changed on this branch at all.

The marker is documented as meaning "performance-related tests", which these
are not. Left in place, the performance gate would report a regression every
time somebody expands the rules reference — penalising the act of writing
documentation.

The catalog and rule-builder tests in this file keep their marker; those do
exercise the package.
@shenxianpeng shenxianpeng changed the title docs: move navigation to the sidebar and expand the rules reference docs: rebuild the documentation site as a product surface Aug 3, 2026
The deploy preview failed to build:

    ERROR - Config value 'site_url': The URL isn't valid, it should
            include the http:// (scheme)

Values in a [context.*.environment] block are literals — Netlify does not
interpolate them — so SITE_URL reached MkDocs as the unexpanded string
"${DEPLOY_PRIME_URL}", which is indeed not a URL.

Set it in the context's build command instead, which runs in a shell where
the variable expands. The redirect hook now also tolerates a site_url without
a trailing slash, since that is the form DEPLOY_PRIME_URL takes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/assets/extra.css`:
- Around line 20-22: Update the default light-theme rule for
--md-typeset-a-color to use a darker color with at least 4.5:1 contrast against
the white background, rather than reusing --cc-brand-dark; keep the dark-theme
styling unchanged.

In `@docs/changelog.md`:
- Around line 11-14: Update the AI attribution governance entry in the changelog
to document the implemented [commit] option as ai_attribution, state that its
default is "ignore" and its rejecting mode is "forbid", and remove the incorrect
forbid_ai_attribution boolean configuration description.

In `@docs/configuration.md`:
- Line 257: Correct the allow_force_push configuration mapping in the
documentation table: map allow_force_push = true to CCHK_ALLOW_FORCE_PUSH=true,
and document false as the value that blocks force pushes while preserving the
existing CLI flag context.

In `@docs/example.md`:
- Around line 94-95: Convert the remaining reStructuredText constructs to MkDocs
Markdown: in docs/example.md lines 94-95, replace the `.. tip::` block with a
`!!! tip` admonition; in docs/changelog.md lines 148-149, replace `..
Attention::` with the appropriate MkDocs admonition; and in docs/what-is-new.md
lines 58-61, convert the RST external-link syntax to standard Markdown link
syntax.

In `@docs/getting-started/quickstart.md`:
- Around line 20-21: Update the quickstart scratch repository setup around the
git init and git commit commands to configure local user.name and user.email
values before creating the empty commit, ensuring commit-check is reachable on
clean Git installations.

In `@docs/guides/github-actions.md`:
- Around line 39-58: Update the `pr-comments` documentation in the GitHub
Actions guide to state that fork-originated `pull_request` events may receive a
read-only `GITHUB_TOKEN`, so `pull-requests: write` alone may not enable
comments. Either document that comments may fail for fork PRs or describe a
trusted `pull_request_target` workflow using base-branch checkout without
executing fork code.

In `@docs/guides/organization.md`:
- Around line 26-30: Update the repository configuration description near the
inherit_from example to say each repository needs one line, matching the
single-line configuration shown; do not add omitted configuration.

In `@docs/index.md`:
- Line 139: Update the documentation statement near “Build provenance with
artifact attestation verified at install time” to accurately state that
artifacts carry SLSA Level 3 provenance verifiable before installation, unless
an actual install-time verification mechanism is documented; do not claim
install-time verification based solely on the manual gh attestation verify step.

In `@docs/rules.md`:
- Around line 448-450: Update the Developer Certificate of Origin reference in
the surrounding documentation text to use Markdown link syntax with the existing
link text and URL, replacing the reStructuredText inline-link notation while
preserving the sentence content.

In `@docs/troubleshoot.md`:
- Around line 22-40: Correct the “Bypass Specific Hook” and “Bypass All Hooks”
headings in the troubleshooting documentation: the section using --no-verify
should describe bypassing all commit-time hooks, while the section using
SKIP=check-author-name should describe bypassing only the named hook. Leave the
command examples unchanged.

In `@scripts/mkdocs_hooks.py`:
- Around line 30-38: Update the REDIRECT HTML template to add a client-side
redirect that appends location.hash to the target URL, preserving fragments such
as `#cc003`; retain the existing meta refresh unchanged as the no-JavaScript
fallback.
- Around line 84-89: Normalize the `site_url` base in the redirect-generation
flow before iterating over `LEGACY_URLS`, ensuring it has exactly one trailing
slash after applying the existing root fallback. Use this normalized base when
concatenating each target in `REDIRECT.format` so root redirects retain the
separator.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a12824c-16cf-41da-b216-ad03c9f9424a

📥 Commits

Reviewing files that changed from the base of the PR and between 0eb515a and d684332.

⛔ Files ignored due to path filters (3)
  • docs/_static/logo.jpg is excluded by !**/*.jpg
  • docs/assets/favicon.svg is excluded by !**/*.svg
  • docs/assets/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (37)
  • .github/workflows/main.yml
  • .gitignore
  • .pre-commit-config.yaml
  • commit_check/rules_catalog.py
  • docs/README.rst
  • docs/_static/extra_css.css
  • docs/assets/extra.css
  • docs/changelog.md
  • docs/changelog.rst
  • docs/conf.py
  • docs/configuration.md
  • docs/configuration.rst
  • docs/example.md
  • docs/example.rst
  • docs/getting-started/installation.md
  • docs/getting-started/quickstart.md
  • docs/getting-started/why.md
  • docs/guides/ai-attribution.md
  • docs/guides/github-actions.md
  • docs/guides/organization.md
  • docs/guides/pre-commit.md
  • docs/guides/signoff.md
  • docs/index.md
  • docs/migration.md
  • docs/migration.rst
  • docs/rules.md
  • docs/rules.rst
  • docs/troubleshoot.md
  • docs/troubleshoot.rst
  • docs/what-is-new.md
  • docs/what-is-new.rst
  • mkdocs.yml
  • netlify.toml
  • noxfile.py
  • pyproject.toml
  • scripts/mkdocs_hooks.py
  • tests/rules_catalog_test.py
💤 Files with no reviewable changes (10)
  • docs/example.rst
  • docs/troubleshoot.rst
  • docs/README.rst
  • docs/changelog.rst
  • docs/configuration.rst
  • docs/_static/extra_css.css
  • docs/migration.rst
  • docs/rules.rst
  • docs/conf.py
  • docs/what-is-new.rst

Comment thread docs/assets/extra.css
Comment thread docs/changelog.md Outdated
Comment thread docs/configuration.md Outdated
Comment thread docs/example.md Outdated
Comment on lines +20 to +21
$ git init demo && cd demo
$ git commit --allow-empty -m "updated the parser"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the scratch repository commit deterministic.

A clean Git installation without user.name and user.email fails here with Author identity unknown. The reader cannot reach commit-check. Configure a local identity before creating the commit.

Example fix
 $ git init demo && cd demo
+$ git config user.name "Demo User"
+$ git config user.email "demo@example.com"
 $ git commit --allow-empty -m "updated the parser"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$ git init demo && cd demo
$ git commit --allow-empty -m "updated the parser"
$ git init demo && cd demo
$ git config user.name "Demo User"
$ git config user.email "demo@example.com"
$ git commit --allow-empty -m "updated the parser"
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 20-20: Dollar signs used before commands without showing output

(MD014, commands-show-output)


[warning] 21-21: Dollar signs used before commands without showing output

(MD014, commands-show-output)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/getting-started/quickstart.md` around lines 20 - 21, Update the
quickstart scratch repository setup around the git init and git commit commands
to configure local user.name and user.email values before creating the empty
commit, ensuring commit-check is reachable on clean Git installations.

Comment thread docs/index.md Outdated
Comment thread docs/rules.md Outdated
Comment thread docs/troubleshoot.md Outdated
Comment thread scripts/mkdocs_hooks.py
Comment thread scripts/mkdocs_hooks.py
The deploy preview could not open /rules/. The build emits a redirect stub at
rules.html for the old Sphinx URL, and Netlify normalises "/rules" and
"/rules/" to the same resource, so that stub was served in place of the page
it points at and redirected to itself forever.

Turn the normalisation off and declare the legacy URLs as Netlify redirects,
which resolve before file lookup and so cannot collide with the page they
target. The emitted stubs stay for GitHub Pages, and now refuse to redirect a
page to itself, so the same collision cannot reappear on another host.

The stubs also carry the fragment across. The links most worth keeping alive
are the per-rule ones — rules.html#cc003 — and a bare redirect dropped the
anchor, landing the reader at the top of a 700-line page.

From review, all verified against the source before fixing:

- The RST converter missed four constructs: `.. Attention::` (it only matched
  lowercase), `.. tip ::` (a space before the colons), and two links whose text
  wrapped across a line. They were rendering as literal text.
- The changelog documented `forbid_ai_attribution`, which does not exist; the
  option is `ai_attribution`, defaulting to "ignore".
- The options table mapped `allow_force_push = true` to
  `CCHK_ALLOW_FORCE_PUSH=false`, describing opposite behaviour for equivalent
  settings.
- Troubleshooting had its two bypass headings the wrong way round: --no-verify
  skips every hook, SKIP= skips one.
- Link colour was #1e85a8 on white, 4.2:1, under the 4.5:1 needed for body
  text. Now #176b89 at 6.0:1.
- The landing page claimed attestation "verified at install time"; only a
  manual verification step exists, so it now says what is true.
- The organization guide said "three lines" above a one-line example.
- pr-comments cannot post on fork pull requests, because a fork's
  `pull_request` run gets a read-only token that `pull-requests: write` does
  not override. Documented, along with why `pull_request_target` is not a
  casual substitute.
@shenxianpeng

Copy link
Copy Markdown
Member Author

Fix: stop emitting redirect stubs on Netlify (2fbd4c0)

The preview looped on /rules/ even after a2dfd9f. I verified against the live preview that:

  • the deploy was built from a2dfd9f (deploy API confirms commit_ref; assets/extra.css carries the new --cc-link: #176b89), so [build.processing.html] pretty_urls = false was deployed but did not stop Netlify from serving rules.html for /rules/;
  • the real page has always been at /rules/index.html (200), so nothing was wrong with the MkDocs build;
  • the [[redirects]] 301s work (e.g. /rules.html/rules/).

Root cause

scripts/mkdocs_hooks.py writes static stub files (rules.html, configuration.html, …) for the old Sphinx URLs. Those stubs exist for GitHub Pages, which has no redirect mechanism. Netlify, however, resolves /rules/ to the file rules.html, so the stub shadowed the real rules/index.html and redirected to itself — an infinite loop. Turning "pretty URLs" off did not change that resolution behavior.

Fix

  • scripts/mkdocs_hooks.py: skip writing the stubs when NETLIFY=true (set on every Netlify build; not set in the GitHub Actions docs job). The [[redirects]] table already handles the legacy URLs with real 301s, which resolve before file lookup and cannot collide with the pages they target.
  • netlify.toml: removed the [build.processing.html] pretty_urls = false block — it demonstrably does nothing here — and kept the redirects.

Verified on the rebuilt preview: /rules/, /configuration/, /changelog/ … serve the real pages; /rules.html 301s to /rules/ (browsers carry #cc003 across, landing on /rules/#cc003); the GitHub Pages build still emits the stubs.

@shenxianpeng shenxianpeng removed the tests Add test related changes label Aug 3, 2026
The previous logo.svg was a new line-art icon that did not match the
project's actual logo. Vectorize docs/_static/logo.jpg (a 900x504 PNG in
the old Sphinx site) with potrace instead, so the SVG is pixel-identical
to the original: the 'commit' wordmark, the check mark and the branch
shape in the brand color #2C9CCD.

The old logo.jpg could not be used as-is on the new site: Sphinx's
conf.py had it commented out ('can not display well in blue background'),
it carried 10 KB of transparent padding around a 300x293 mark, and the
new header renders the logo via <img>, where currentColor would resolve
to black. The traced SVG keeps the exact shapes with a hardcoded fill,
so it renders identically in the light and dark palettes.
@shenxianpeng
shenxianpeng force-pushed the docs/left-sidebar-and-rules-reference branch from 2fbd4c0 to f1b4631 Compare August 3, 2026 18:57
@github-actions github-actions Bot added the tests Add test related changes label Aug 3, 2026
@shenxianpeng

Copy link
Copy Markdown
Member Author

Logo: restored as a vectorized copy of the original (f1b4631)

The new assets/logo.svg was a freshly drawn line-art icon, not the project's logo. It is now a potrace vectorization of the original docs/_static/logo.jpg (which was actually a 900×504 PNG), so the SVG is pixel-identical to the original: the commit wordmark, the check mark and the branch shape, in the original brand color #2C9CCD.

Why not keep the JPG / why a trace instead of a redraw:

  • the old site never actually displayed it — conf.py had html_logo = "_static/logo.jpg" commented out (can not display well in blue background), and the file was 10 KB with the mark occupying only a centered 300×293 box;
  • the header renders the logo via <img>, where currentColor in an SVG resolves to black, so a redrawn currentColor icon would not follow the theme palette;
  • the traced SVG keeps the exact original shapes with a hardcoded fill, so it renders identically in both the light and dark palettes.

Verification: rendered the traced SVG and compared it pixel-by-pixel against the original (98% exact, remainder is anti-aliasing where potrace smooths the edges); the rebuilt preview serves the identical file at /assets/logo.svg.

The header background is the brand color #2c9ccd (--md-primary-fg-color),
the same blue the logo is filled with, so the logo was invisible. This is
the same reason the old Sphinx site had html_logo commented out ('can not
display well in blue background').

Keep the original blue logo unchanged and give it a white rounded tile.
On the blue header the tile makes the logo visible; in the drawer, which
sits on a light or dark gray background, the blue logo shows directly.
@sonarqubecloud

sonarqubecloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

@shenxianpeng

Copy link
Copy Markdown
Member Author

Logo visibility fix (02c7088)

The header background is --md-primary-fg-color = #2c9ccd — the exact blue the logo is filled with — so the logo was invisible. (The old Sphinx site had the same problem: html_logo was commented out with "can not display well in blue background".)

Fix without touching the background: the logo now sits on a white rounded tile (same #2C9CCD logo, unchanged shapes). It is visible everywhere the logo appears:

Where Background What shows
Header (1.2rem) brand blue #2c9ccd white tile stands out, blue logo on it
Mobile drawer (2.4rem) light/dark gray blue logo directly visible (tile blends in)

Verified on the rebuilt preview: the served /assets/logo.svg matches the build exactly, and a render check confirms 71k white-tile pixels vs 17k blue-logo pixels — a clear contrast silhouette on the blue header.

@shenxianpeng shenxianpeng removed the tests Add test related changes label Aug 3, 2026
@shenxianpeng
shenxianpeng merged commit 6751073 into main Aug 3, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant