diff --git a/.claude/skills/optest/SKILL.md b/.claude/skills/optest/SKILL.md new file mode 100644 index 00000000..fb92cced --- /dev/null +++ b/.claude/skills/optest/SKILL.md @@ -0,0 +1,57 @@ +--- +name: optest +description: Raise a PyLops operator's test coverage above a threshold (default 90%) by adding or modifying tests. Use when the user asks to improve/raise/check test coverage for a specific PyLops operator class (e.g. "get FirstDerivative to 95% coverage", "improve test coverage for FFT"). +--- + +Goal: bring test coverage for a given PyLops operator class to at least a target +percentage (default **90%**). + +Expect the invocation to include an operator class name (e.g. `FirstDerivative`, +`FFT`) and optionally a target percentage. If the operator name is missing, ask +for it before proceeding. + +Follow this workflow precisely: + +1. **Locate the operator.** Find the source module that defines `class ` + (e.g. `grep -rln "^class \b" pylops/`) and the test file(s) that + already exercise it (`grep -rln "" pytests/`). + +2. **Measure baseline coverage** for this operator only: + ```bash + .pi/tools/operator_coverage.sh + ``` + Read the reported percentage and the list of *missing* line numbers. + +3. **Inspect the uncovered lines** in the source module. For each missing line, + identify what behaviour is untested: alternate dtypes, branches (e.g. + `kind`/`edge`/`order` options), error paths (`raise`/`NotImplementedError`), + adjoint vs forward, ND vs 1D, backend dispatch, etc. + +4. **Add or modify tests** in the existing `pytests/test_*.py` file for this + operator. Match the repo's conventions: + - Parametrize with `@pytest.mark.parametrize` over `par` dicts and `dtype`. + - Always include a `dottest(...)` adjoint check for new configurations. + - Use `assert_array_almost_equal` for forward/inverse comparisons. + - Keep the CuPy/`backend` guard pattern used at the top of the test file. + Do NOT weaken assertions or add trivial no-op tests just to hit lines. + +5. **Re-run** `.pi/tools/operator_coverage.sh ` and iterate steps 3–4 + until `COVERAGE_PCT >= `. If some lines are genuinely untestable on + the current backend (e.g. CUDA-only paths), say so explicitly and exclude + them from the target with justification rather than faking coverage. + +6. **Validate** the new tests actually pass and lint cleanly: + ```bash + make lint + ``` + (run the relevant pytest file directly if a full `make tests` is too slow). + +7. **Report** a short summary: starting %, final %, which test functions were + added/changed, and any lines deliberately left uncovered with the reason. + +The coverage-measurement tool lives at `.pi/tools/operator_coverage.sh` (repo +root, two levels up from the script's own location) — it locates the operator's +source module, runs pytest scoped to it, and prints coverage % plus missing +line numbers. Usage: `.pi/tools/operator_coverage.sh [extra +pytest args...]`. Runner selection: `$RUNNER` env var, else `uv run` if `uv` +is on `PATH`, else `python3 -m coverage`. diff --git a/AIPOLICY.md b/AIPOLICY.md new file mode 100644 index 00000000..04e00845 --- /dev/null +++ b/AIPOLICY.md @@ -0,0 +1,40 @@ +# PyLops AI Policy + +**Table of Contents** + +- [The Short Version](#the-short-version) +- [The Longer Version](#the-longer-version) + - [Philosophy](#philosophy) + - [Coding Agents](#coding-agents) + + +## The Short Version + +Use AI like you used Google and StackOverflow. Own the final solution like you owned it before. + +However, since AI still behaves differently from humans (it is undoubtedly better at certain tasks and worse at others), always acknowledge directly - e.g., let Claude Code author a PR that was strongly driven by it - or indirectly - e.g., explain in the PR where and how AI was used. This helps reviewers and maintainers to pay attention in different ways when reviewing a human-driven code vs an AI-driven code. + +## The Longer Version + +### Philosophy + +PyLops has always been a forward-thinking and inclusive project. At a time when Python was largely regarded as a scripting language for mundane data manipulation and for stitching together HPC software written in lower-level programming languages, we believed that solving large-scale inverse problems efficiently and scalably didn’t necessarily require reaching for those languages. Instead, we focused on achieving greater expressivity, stronger abstractions, and ease of use—all while retaining the power and performance needed for demanding applications. + +With the emergence of Coding Agents, the way we approach software development is changing, and we do not intend to be one of those communities that buries its head in the sand and carries on with business as usual. We instead encourage everyone to experiment with AI and Coding Agents and benefit from them in all stages of development. + +This however does not mean that we encourage our developers (especially newcomers) to vibe-code complex solutions with little to no control on the physical outcome - lines of code! AI and Coding Agents should be treated as colleagues during pair-coding sessions: they can help in the ideation phase, during development, and in later stages to ensure consistency and act as additional attentive reviewers. + +The only **strong recommendation** that we provide to anyone contributing code to PyLops is to be transparent about their use of AI/Coding Agents. We must recognize that AI still behaves differently from humans - it is undoubtedly better than us in certain tasks but it is still worse in other tasks. If we, reviewers and maintainers, know how a piece of code was generated, we can approach the review process slightly differently whether we review a human-driven code vs an AI-driven code. + +### Coding Agents + +In order to help our developers, we are committed to provide some of basic ingredients that allow Coding Agent to perform at their best. We aim to be as much as possible vendor-agnostic, and therefore we will provide equivalent versions of *.md* files, skills/commands, etc. that are suitable for one or another Coding Agent. + +More specifically, we currently provide: + +- ``AGENTS.md / CLAUDE.md``: basic set of instructions that tell coding agents how to work with our specific software project. + +- ``.pi/prompts/optest.md`` / ``.claude/skills/optest``: a skill to increase the test coverage of an operator; + + +🤖🤖 **This Policy was written by humans and polished by AI** 🤖🤖 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..37516287 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,24 @@ +# Agent Guide for PyLops + +## Where Things Live +- `pylops/`: library code. +- `pytests/`: pytest suite. +- `docs/`, `examples/`, `tutorials/`, `testdata/`: docs, examples, tutorial assets, and test data. +- `pyproject.toml`: build, test, lint, and packaging config. +- `Makefile`: preferred entry point for local work. + +## Working Here +- Prefer `make` targets. Use the `*_uv` variants when working in a `uv` environment. +- Common commands: `make dev-install_uv`, `make tests` or `make tests_uv`, `make lint` or `make lint_uv`, `make typeannot` or `make typeannot_uv`, `make docupdate` or `make docupdate_uv`. +- Packaging uses `hatchling`; keep build and version settings in `pyproject.toml`. + +## Style And Tests +- Follow the `ruff` rules in `pyproject.toml`. +- Keep imports tidy and follow PEP 8 rules. +- Follow `numpydoc` style for docstrings. +- Add or update tests in `pytests/` and examples in `examples/` and/or `tutorials/` when changing behavior or public APIs. + +## Contribution Flow +- Use `docs/source/contributing.rst` as the source of truth for longer contribution workflows. +- If functionality changes, update docs and run the relevant tests before handing off. +- Avoid editing generated artifacts or build output unless the task explicitly requires it.