From a8664ebc399cfadc47b55f11bfe73edc1b3af658 Mon Sep 17 00:00:00 2001 From: Branimir Georgiev <66906831+braboj@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:17:50 +0200 Subject: [PATCH 1/2] docs(readme): explain how to use the shipped checks without the templates (#2412) The hook table is generated from .pre-commit-hooks.yaml, leaving out deprecated hooks, so it cannot drift from the hooks upstream ships. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DpT5xSVK2FLNdArtRtNjLH --- README.md | 33 +++++++++++++++++++++++++++++++++ tools/sync_docs.py | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index daf7e7f7..5ed08f3d 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,39 @@ keep your team on design and testing. 2. Review the result before you commit it. +## Use the checks only + +A project can run the shipped checks without the templates. Add them to +`.pre-commit-config.yaml`, pinned to a released tag, and list the hooks it +wants: + +```yaml +repos: + - repo: https://github.com/solid-ai-dev/solid-ai-templates + rev: v3.0.0 + hooks: + - id: find-unfenced-checks + - id: find-bare-suppressions +``` + + +| Hook | What it does | +|------|--------------| +| `find-unfenced-checks` | Find checks stated outside a fenced block | +| `compile-embedded-checks` | Compile the Python checks embedded in Markdown | +| `find-line-continuations` | List line continuations in embedded checks | +| `find-bare-suppressions` | Find lint suppressions that name no rule | +| `report-test-edits` | Report changes that edit an existing test | +| `check-ascii-identifiers` | Check Python identifiers are ASCII | +| `find-import-bans` | Find imports that cross a declared boundary | +| `report-off-limits-paths` | Report committed changes touching off-limits paths | + + +Run them on each commit with `pre-commit install`, and in CI with +`pre-commit run --all-files`. A hook that finds nothing to check prints +`not applicable: ` and passes; read it as nothing checked, not as +a pass. `templates/core/quality-gates.md` describes each hook's arguments. + ## Documentation | Read | For | diff --git a/tools/sync_docs.py b/tools/sync_docs.py index d0f091ca..4000e151 100644 --- a/tools/sync_docs.py +++ b/tools/sync_docs.py @@ -490,6 +490,31 @@ def _readme_agents(): return "\n".join(out) +def _readme_hooks(): + """Render the README table of shipped hooks a project can run. + + The hook list is written once, in `.pre-commit-hooks.yaml`. A + deprecated hook still runs until the next major, but a project + starting now has no reason to adopt it, so the table leaves it out. + """ + text = io.open(ROOT / ".pre-commit-hooks.yaml", encoding="utf-8").read() + hooks = re.findall(r"^- id: (\S+)\n\s+name: \"?([^\"\n]+)\"?$", text, + re.MULTILINE) + + # A changed layout in the hook file would parse to nothing here, and an + # empty table would read as upstream shipping no checks. + if not hooks: + raise SystemExit( + "sync: .pre-commit-hooks.yaml parsed to zero hooks; refusing to " + "write an empty README table" + ) + + out = ["| Hook | What it does |", "|------|--------------|"] + out += ["| `%s` | %s |" % (hid, name) for hid, name in hooks + if not name.startswith("Deprecated:")] + return "\n".join(out) + + def main(): check_mode = "--check" in sys.argv @@ -525,6 +550,7 @@ def main(): has_model_table = "" in readme_text model_limits = _readme_model_limits() if has_model_table else None agent_outputs = _readme_agents() + readme_hooks = _readme_hooks() interview_content = _interview_stacks(manifest) spec_doc = ROOT / "docs" / "architecture" / "05-building-block-view.md" @@ -532,9 +558,10 @@ def main(): examples_doc = ROOT / CHAIN_EXAMPLES_DOC example_blocks = {"spec-chain-examples": chain_examples} - # The README is fork-owned. Upstream's is a short front page with no - # generated section; a fork keeps the markers for the tables it shows, - # and each pair present is filled, so --check still sees its drift. A + # The README is fork-owned. Upstream's is a short front page whose only + # generated section is the hook table; a fork keeps the markers for the + # tables it shows, and each pair present is filled, so --check still + # sees its drift. A # section is absent only when both markers are: one marker deleted from # a pair would otherwise leave a stale table outside every check. readme_blocks = {} @@ -543,6 +570,7 @@ def main(): ("readme-extras", readme_extras), ("readme-root-counts", readme_root_counts), ("readme-agents", agent_outputs), + ("readme-hooks", readme_hooks), ("readme-model-limits", model_limits)): opens = "" % marker in readme_text closes = "" % marker in readme_text From 070fe46ca8b9dbee2ea724c82770d59b21844e46 Mon Sep 17 00:00:00 2001 From: Branimir Georgiev <66906831+braboj@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:19:07 +0200 Subject: [PATCH 2/2] docs(changelog): add the README checks-only section (#2412) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DpT5xSVK2FLNdArtRtNjLH --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da05d33..af6fcfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,8 @@ Releases up to 2.63.0 are listed in - Rules that compress an incident into one line gain a short example ([#2171]) - A check that fails when a new section ID splits a section frozen in 3.x ([#2278]) +- The README shows how to run the shipped checks without the templates + ([#2423]) ### Changed @@ -489,6 +491,7 @@ Releases up to 2.63.0 are listed in [#2387]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2387 [#2389]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2389 [#2415]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2415 +[#2423]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2423 ## [2.90.0] - 2026-09-12