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
23 changes: 16 additions & 7 deletions .claude/commands/check-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@
description: Find deprecated access patterns in code and documentation
---

## Reference Document
## Run the CI scanner first

**Read the authoritative patterns guide first:**
`docs/developer/UW3_Style_and_Patterns_Guide.qmd`
The `src/` pattern list is machine-enforced; the scanner is the single source of
truth for what is banned and what is allowlisted legacy:

Key sections:
- Section 4 "Array and Data Management" - array indexing patterns
- Section 5 "Context Managers" - deprecated vs current access patterns
- Section 6 "MPI and Parallel Patterns" - parallel safety
```bash
pixi run -e amr-dev python scripts/check_deprecated_patterns.py
python scripts/check_deprecated_patterns.py --include-docs # report-only docs inventory
```

Policy and pattern definitions: `docs/developer/guides/style-gates.md`
(allowlist shrinks only — never add entries to make a PR pass).

## Reference Documents

- `docs/developer/UW3_STYLE_CHARTER.md` — normative rules (§3 naming, §4 comments, §7 data access)
- `docs/developer/subsystems/data-access.md` — governing data-access reference
- `docs/developer/UW3_Style_and_Patterns_Guide.md` — broader style reference

---

Expand Down
16 changes: 16 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!-- Describe WHAT changed and WHY. Keep the diff reviewable: one topic per PR. -->

## Checklist (UW3 Style Charter — docs/developer/UW3_STYLE_CHARTER.md)

- [ ] I have read the Style Charter and followed it over the surrounding code (S2)
- [ ] No drive-by refactors, renames, or "while I was here" cleanups (S9)
- [ ] Bug fixes ship the regression test, written first, with `level_*` and `tier_*` markers (S8)
- [ ] No hedging names (`maybe_` / `try_` / `do_`) and no commented-out code (S3, S4)
- [ ] Every exception swallow states its sanctioned failure mode in a comment (S4)
- [ ] New data access uses `.array` / `mesh.X.coords` — no `with ....access(...)`, no `mesh.data` (S7)
- [ ] Parallel safety considered — np2/np4 checked where swarm/mesh/solver dispatch is touched (S11)
- [ ] No `pixi.toml` / `pixi.lock` or other dependency changes riding in an unrelated PR
- [ ] AI-assisted work carries the attribution line below

<!-- If AI-assisted, end the PR body with:
Underworld development team with AI support from [Claude Code](https://claude.com/claude-code) -->
53 changes: 53 additions & 0 deletions .github/workflows/style-gates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Style Gates

# Machine-enforced subset of docs/developer/UW3_STYLE_CHARTER.md (S3, S4, S7).
# Fast (<1 min): no PETSc build, no package install — the scanner is stdlib-only.
#
# The gate fails on deprecated patterns NOT recorded in
# scripts/deprecated_pattern_allowlist.txt. That allowlist records pre-existing
# legacy hits and may only SHRINK: fix the code your PR adds; only a maintainer
# adds allowlist entries.

on:
pull_request:
branches:
- development
- main
types: [opened, synchronize, reopened]

jobs:
deprecated-patterns:
name: Deprecated-pattern scan (Charter S3/S4/S7)
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Scan src/ for Charter-banned patterns
run: |
echo "Running the deprecated-pattern scanner (stdlib only)..."
if ! python scripts/check_deprecated_patterns.py; then
echo ""
echo "FAILED: your change introduces a pattern banned by the UW3 Style Charter."
echo ""
echo " Charter: docs/developer/UW3_STYLE_CHARTER.md (S3 naming, S4 comments, S7 data access)"
echo " Guide: docs/developer/guides/style-gates.md"
echo " Run local: pixi run -e amr-dev python scripts/check_deprecated_patterns.py"
echo ""
echo "Fix the flagged code. The allowlist"
echo "(scripts/deprecated_pattern_allowlist.txt) records pre-existing legacy"
echo "hits only and may only SHRINK — only a maintainer adds entries."
exit 1
fi

- name: Report deprecated patterns in docs/ (informational)
run: |
# Never fails: docs cleanup is tracked separately. This keeps the
# inventory visible in the job log without blocking PRs.
python scripts/check_deprecated_patterns.py --include-docs || true
5 changes: 5 additions & 0 deletions docs/developer/UW3_STYLE_CHARTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ This Charter wins on any conflict. One governing document per topic:
`UW3_Style_and_Patterns_Guide.md` remains as the detailed reference, but where it and
this Charter disagree (notably docstring format and coordinate access), the Charter wins.

**Machine enforcement**: the cheapest-to-check rules here (§3 hedging names, §4 silent
swallows, §7 deprecated data access) are enforced in CI by
`scripts/check_deprecated_patterns.py` via `.github/workflows/style-gates.yml`; its
allowlist records pre-existing legacy hits and may only shrink. See `guides/style-gates.md`.

## 11. Things to Remember

Underworld is a parallel code — no feature is complete if it only works in serial.
Expand Down
5 changes: 5 additions & 0 deletions docs/developer/guides/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ Step 8 is deliberately left to a human so the review gate on `main` is never
bypassed. CI (`.github/workflows/release.yml`) publishes the GitHub Release from
the committed `docs/release-notes/vX.Y.0.md`.

The CI style gates must also be green on the release branch — the
`development → main` PR (step 7) runs `.github/workflows/style-gates.yml`
automatically; see [style-gates.md](style-gates.md) for the checks and the
shrink-only allowlist policy.

### Documentation freshness sweeps (before step 6)

Two "pull" documents go stale silently between releases; refresh both as part
Expand Down
70 changes: 70 additions & 0 deletions docs/developer/guides/style-gates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Style gates (CI)

The cheapest-to-check rules of the [UW3 Style Charter](../UW3_STYLE_CHARTER.md)
are machine-enforced on every pull request to `development` and `main` by
`.github/workflows/style-gates.yml`. The job is fast (no PETSc build) and runs
a single stdlib-only scanner: `scripts/check_deprecated_patterns.py`.

## What the gate checks

| Pattern id | Charter | Flags | Use instead |
|---|---|---|---|
| `access-context` | §7 | `with mesh.access(...)` / `with swarm.access(...)` | the variable's `.array` property directly |
| `mesh-data` | §7 | `mesh.data` (coordinate read) | `mesh.X.coords` |
| `hedging-name` | §3 | `def maybe_*` / `def try_*` / `def do_*` (and `_`-private forms) | a name stating what the function DOES |
| `except-pass` | §4 | `except ...:` + bare `pass` with no comment nearby | a comment stating the sanctioned failure mode |

Detection is line-based and deliberately simple; the exact heuristics (and the
documented exclusions, e.g. commented-out lines and `self.data` inside Mesh
methods) are in the scanner's module docstring. A related regression net —
`tests/test_0641_wave_c_api_shims.py` in the `level_1 + tier_a` CI gate —
covers the deprecation *warnings* the shimmed APIs must keep emitting.

## The allowlist only shrinks

`scripts/deprecated_pattern_allowlist.txt` records the legacy hits that
existed when the gate was introduced (baseline: `development` @ `9f5ed9e9`,
2026-07), one `path:pattern-id` per line. The gate fails on any hit **not**
listed there.

```{warning}
The allowlist may only **shrink**. If your PR trips the gate, fix the code —
do not add allowlist lines. Only a maintainer adds entries, and only for code
that predates the gate. When you clean up a listed file, delete its entries;
the scanner reminds you by reporting stale ones.
```

## Running locally

```bash
pixi run -e amr-dev python scripts/check_deprecated_patterns.py # the CI gate
pixi run -e amr-dev python scripts/check_deprecated_patterns.py --include-docs # + docs/ report
pixi run -e amr-dev python scripts/check_deprecated_patterns.py --no-allowlist # full legacy inventory
```

The scanner needs nothing beyond the Python standard library, so plain
`python scripts/check_deprecated_patterns.py` works in any environment.

## When your PR trips the gate

1. Read the flagged line(s) in the job log — each hit names its pattern id and
the Charter rule it violates.
2. Fix the code (the table above gives the replacement for each pattern).
3. If you believe a hit is a false positive of the line-based heuristic,
say so in the PR and ask a maintainer to rule — do not edit the allowlist
yourself.

## Formatting (not gated)

The tree is not currently `black`-clean (81 of 95 files at baseline), so there
is **no** formatting gate — adding one would fail every PR that touches
library code. Do not reformat files wholesale to "fix" this: bulk reformatting
destroys `git blame` and turns reviewable diffs into unreviewable ones. If the
maintainers later adopt a formatter, it will arrive as a single dedicated
reformat commit plus a gate, not piecemeal.

## See also

- [UW3 Style Charter](../UW3_STYLE_CHARTER.md) — the normative rules
- [Release process](release-process.md) — style gates must be green on the release branch
- `/check-patterns` (Claude command) — interactive audit of docs, notebooks and tests
1 change: 1 addition & 0 deletions docs/developer/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ guides/HOW-TO-WRITE-UW3-SCRIPTS
guides/notebook-style-guide
guides/GMSH_INTEGRATION_GUIDE
guides/CODE-REVIEW-PROCESS
guides/style-gates
guides/SPELLING_CONVENTION
guides/version-management
guides/branching-strategy
Expand Down
Loading
Loading