Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

<!-- generated:readme-hooks -->
| 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 |
<!-- /generated:readme-hooks -->

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: <reason>` and passes; read it as nothing checked, not as
a pass. `templates/core/quality-gates.md` describes each hook's arguments.

## Documentation

| Read | For |
Expand Down
34 changes: 31 additions & 3 deletions tools/sync_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -525,16 +550,18 @@ def main():
has_model_table = "<!-- generated:readme-model-limits -->" 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"
spec_blocks = {"spec-core-tier": spec_core_tier}
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 = {}
Expand All @@ -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 = "<!-- generated:%s -->" % marker in readme_text
closes = "<!-- /generated:%s -->" % marker in readme_text
Expand Down
Loading