Skip to content
Merged
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: 2 additions & 1 deletion .claude/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ delete or shrink the rule — do not duplicate.
├── bash/ # Shell script-specific
├── yaml/ # YAML authoring conventions
├── markdown/ # Markdown authoring conventions
└── copier/ # Copier template-repo conventions
└── copier/ # Copier update workflow and answers-file rules
└── template-conventions.md
```

Detailed how-to content that previously lived here has moved to skills:
Expand Down
26 changes: 15 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ destination folder.
│ ├── .github/workflows/ # Generated CI/CD workflows
│ └── … # pyproject.toml.jinja, justfile.jinja, CLAUDE.md.jinja, …
├── tests/ # pytest suite for this meta-repo (see tests/CLAUDE.md)
│ ├── constants.py # REPO_ROOT / TEMPLATE_ROOT / COPIER_YAML for nested test modules
│ ├── script_imports.py # REPO_ROOT + load_script_module() for unit tests importing scripts/
│ ├── conftest.py # top-level shared fixtures
│ ├── unit/ # fast isolated script tests
│ ├── integration/ # Copier copy/update integration suite
Expand Down Expand Up @@ -117,11 +117,14 @@ just ci
This runs: `fix` → `check`.

`check` bundles: `uv sync --frozen`, `fmt-check`, `ruff check`, `basedpyright`,
`sync-check`, `docs-check` (D-only; redundant with `ruff check` for enforcement), `test-ci-matrix`
(same pytest commands as `tests.yml` for 3.11/3.12/3.13), `pre-commit run --all-files`, `audit` (pip-audit).
`sync-check`, `docs-check` (D-only; redundant with `ruff check` for enforcement), `test-ci`
(pytest with coverage on the default Python 3.11 venv — same command as the 3.11 leg of `tests.yml`),
`pre-commit run --all-files`. Dependency audit (`pip-audit`) is **not** part of `check`; run
`just audit` locally or rely on `security.yml` on GitHub (CodeQL is GHA-only). Use `just test-ci-matrix`
to exercise the full 3.11 / 3.12 / 3.13 matrix locally.

Together, `lint.yml` + `tests.yml` + `security.yml` mirror these checks on GitHub (CodeQL is
GHA-only). All steps must pass before a PR is mergeable.
Together, `lint.yml` + `tests.yml` + `security.yml` cover the merge gate on GitHub. All steps must
pass before a PR is mergeable.

## Generating a test project from the template

Expand Down Expand Up @@ -240,17 +243,18 @@ and are readable by any AI assistant (Claude Code, Cursor, or any LLM):
```
.claude/rules/
├── README.md ← how to read and write rules; dual-hierarchy explained
├── common/ ← language-agnostic: coding-style, git-workflow, testing, security,
│ development-workflow, code-review
├── python/ ← Python: coding-style, testing, patterns, security, hooks
├── jinja/ ← Jinja2: coding-style, testing (meta-repo only)
├── common/ ← language-agnostic: coding-style, git-workflow, testing, security, hooks
├── python/ ← Python: coding-style, testing, hooks
├── bash/ ← Bash: coding-style, security
├── markdown/ ← placement rules, authoring conventions
├── yaml/ ← YAML formatting for copier.yml and workflows (meta-repo only)
├── yaml/ ← YAML formatting for copier.yml and workflows (meta-repo only)
└── copier/ ← Copier template conventions (meta-repo only)
└── template-conventions.md
```

Jinja2 and broader Copier how-tos live under `.claude/skills/` (for example `jinja-guide/`), not
as a separate `rules/jinja/` tree.

The `template/.claude/rules/` tree mirrors this structure for generated projects
(common, python, bash, markdown — no Jinja, yaml, or Copier-specific rules).

Expand Down Expand Up @@ -407,5 +411,5 @@ just clean # removes build/, dist/, .pytest_cache, .ruff_cache, __pycache__, *
- Added `CLAUDE.md` in `template/` — explains Jinja2 source layout, Copier variables, dual `.claude/` hierarchy
- Added `CLAUDE.md` in `tests/` — explains test patterns, helpers, categories, and how to add new tests
- Added `CLAUDE.md` in `scripts/` — documents each script, CLI flags, outputs, and CI integration
- Added `CLAUDE.md` in `.claude/` — orientation hub for hooks, commands, rules, and the dual-hierarchy
- Documented hooks and rules in `.claude/hooks/README.md` and `.claude/rules/README.md` (dual hierarchy with `template/.claude/`)
- Added `CLAUDE.md` in `.github/` — documents all meta-repo workflows and design principles
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,14 @@ Other useful commands:
- 🔍 **`just lint`**: lint check
- 🧠 **`just type`**: type check (basedpyright **standard** mode)
- 📜 **`just docs-check`**: Google-style docstrings (ruff `D` only)
- ✅ **`just review`**: `fix` → `lint` → `type` → `docs-check`
- ✅ **`just review`**: `fix` → `lint` → `type` → `docs-check` (no tests; pre-merge static checks)
- 🧪 **`just test`**: run template integration tests (renders the template and asserts output)
- 📊 **`just coverage`**: run tests with coverage report
- ⚡ **`just test-parallel`**: run tests in parallel (faster)
- 🔁 **`just precommit`**: run pre-commit on all files
- 🩺 **`just doctor`**: print toolchain and project versions
- 🔗 **`just sync-check`**: validate root/template sync policy (`scripts/check_root_template_sync.py`)
- ✋ **`just check`**: read-only full gate (matches GitHub Actions lint + tests + security steps)
- 🔄 **`just review`**: `fix` + `lint` + `type` + `docs-check` (no tests, pre-merge validation)
- ✋ **`just check`**: read-only gate (`fmt-check`, lint, types, sync-check, docstrings, `test-ci`, pre-commit). For the full Python 3.11–3.13 matrix locally, use **`just test-ci-matrix`**. Dependency audit: **`just audit`** (also runs in `security.yml` on GitHub).

### Testing this template

Expand Down
3 changes: 2 additions & 1 deletion template/.claude/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ delete or shrink the rule — do not duplicate.
├── bash/ # Shell script-specific
├── yaml/ # YAML authoring conventions
├── markdown/ # Markdown authoring conventions
└── copier/ # Copier template-repo conventions
└── copier/ # Copier update workflow and answers-file rules
└── template-conventions.md
```

Detailed how-to content that previously lived here has moved to skills:
Expand Down
7 changes: 5 additions & 2 deletions template/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ template/
│ ├── workflows/
│ │ ├── ci.yml.jinja # Main test matrix (Python 3.11–3.13)
│ │ ├── lint.yml.jinja # Ruff + basedpyright on PRs
│ │ ├── dependency-review.yml.jinja # Dependency diff review on PRs (optional)
│ │ ├── docs.yml.jinja # MkDocs deploy to gh-pages (conditional)
│ │ ├── pre-commit-update.yml.jinja # Weekly pre-commit autoupdate
│ │ ├── release.yml.jinja # Version bump + GitHub Release (conditional)
│ │ └── security.yml.jinja # CodeQL + pip-audit (conditional)
│ │ ├── security.yml.jinja # CodeQL + pip-audit (conditional)
│ │ ├── dependency-review.yml # PR dependency review (static)
│ │ ├── labeler.yml # Path-based PR labels (static)
│ │ ├── pr-policy.yml # PR title/body/commits (static)
│ │ └── stale.yml # Stale issue/PR bot (static)
│ ├── ISSUE_TEMPLATE/ # Bug report + feature request templates
│ ├── CODE_OF_CONDUCT.md.jinja
│ ├── CODEOWNERS.jinja
Expand Down
9 changes: 6 additions & 3 deletions template/CLAUDE.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,13 @@ and are readable by any AI assistant (Claude Code, Cursor, or any LLM):
```
.claude/rules/
├── README.md ← how to read and write rules
├── common/ ← language-agnostic: coding-style, git-workflow, testing, security,
├── python/ ← Python: coding-style, testing, patterns, security, hooks
├── common/ ← language-agnostic: coding-style, git-workflow, testing, security, hooks
├── python/ ← Python: coding-style, testing, hooks
├── bash/ ← Bash: coding-style, security
└── markdown/ ← placement rules, authoring conventions
├── yaml/ ← YAML authoring (workflows, config)
├── markdown/ ← placement rules, authoring conventions
└── copier/ ← Copier update workflow (see `paths` in `template-conventions.md`)
└── template-conventions.md
```

## Standards enforcement
Expand Down
25 changes: 9 additions & 16 deletions tests/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ optional features are gated properly.
|---|---|
| `conftest.py` | Top-level pytest fixtures shared across all test tiers |
| `unit/` | Fast isolated tests for automation scripts in `scripts/` |
| `script_imports.py` | `load_script_module()` helper for importing `scripts/*.py` in unit tests |
| `script_imports.py` | `REPO_ROOT` and `load_script_module()` for unit tests that import `scripts/*.py` |
| `unit/conftest.py` | Fixtures shared within the unit tier |
| `integration/` | Tests exercising Copier copy/update across the full template |
| `integration/conftest.py` | Fixtures shared within the integration tier |
Expand Down Expand Up @@ -80,8 +80,8 @@ optional features are gated properly.

### Package structure
- `src/<package_name>/__init__.py`, `core.py`, `common/` modules all exist.
- `tests/<package_name>/test_core.py`, `test_support.py` exist.
- `conftest.py` exists.
- `tests/unit/test_core.py`, `tests/unit/common/test_support.py` (and other `tests/unit/common/*`) exist.
- `tests/conftest.py` exists.

### Logging layout
- `logging_manager.py` is present under `common/`.
Expand All @@ -103,20 +103,13 @@ just coverage # run with coverage report
RUN_TEMPLATE_INTEGRATION=1 just test # include slow integration tests
```

## Path constants — no shared file
## Path constants

Do **not** create a shared constants file (e.g. `constants.py`) for path values.
Define path constants at the top of each test file that needs them:

```python
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent.parent # adjust depth as needed
TEMPLATE_ROOT = REPO_ROOT / "template"
COPIER_YAML = REPO_ROOT / "copier.yml"
```

Constants are trivial one-liners; a shared module adds indirection with no benefit.
- **Unit tests** that load `scripts/*.py` should import **`REPO_ROOT`** from **`tests.script_imports`**
(see `tests/unit/test_*.py`).
- **Integration tests** (for example `integration/test_template.py`) define **`REPO_ROOT`**,
**`TEMPLATE_ROOT`**, and **`COPIER_YAML`** at the top of the file — do not add a separate
`constants.py` module for these; keep paths next to the tests that use them.

## Adding a new test

Expand Down
Loading