diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f4a7b491..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,156 +0,0 @@ -# CLAUDE.md - -MkDocs + Material docs site for [TileOPs](https://github.com/tile-ai/TileOPs), -deployed to `gh-pages` by GitHub Actions. Served at `/TileOPs.github.io/`, the -subpath `site_url` carries. Palette and type come from -[TileFoundry](https://github.com/tile-ai/TileFoundry.github.io) — -`docs/assets/extra.css`. - -## Development - -```bash -bash scripts/dev.sh serve # or: build, bench -``` - -- Sets up a `.venv` from `requirements-docs.txt`, with uv when it is on PATH - and pip otherwise, and the `./TileOPs` checkout. - `build` applies `checks.yml`'s warning rule; `bench` calls `render_bench.sh`. -- Both are reused and stay at the revision they were cloned at. Pass `--update` - before trusting a local build against upstream. -- The checkout is required: `api/` reads its docstrings, `design/` mirrors its - `docs/design/`. Without it the build aborts. - -## Checks - -`.github/workflows/checks.yml`, on every push and pull request: - -| Command | Holds | -|---------|-------| -| `pytest` | The renderer, and `tests/golden/` byte for byte | -| `ruff check scripts hooks.py tests` | `pyproject.toml`. `E501` off — wrap prose by hand | -| `npx stylelint "docs/assets/**/*.css"` | No duplicate selector, no `color-mix()`. Why: an engine that cannot parse a function drops the whole declaration | -| `mkdocs build` | Any warning of ours fails. griffe's come from TileOPs' docstrings and do not gate this repo | -| `python scripts/check_api_pages.py` | Every `::: tileops..` under `docs/api/` is in that family's `__all__`. An exported op no page names is printed, not failed | - -- Keep the suite small; `pytest --collect-only -q` lists it. -- The parametric-workload test needs a checkout (`./TileOPs`, or `$TILEOPS`) and - skips without one. CI's Renderer job provides it. -- `tests/fixtures/` is a trimmed snapshot, `tests/golden/` the three data pages - it must produce. A change to what they say fails by design: read the diff, - then run `python tests/refresh_golden.py`. -- Add a unit test only for a rule the golden pages do not show. - -## Generated pages - -Never edit by hand — change what produces them. - -| Pages | Produced by | -|-------|-------------| -| `docs/api/` | mkdocstrings, from TileOPs docstrings | -| `docs/design/` | `include-markdown`, mirroring TileOPs `docs/design/` | -| `docs/benchmarks/` | `scripts/gen_bench_pages.py`, from the newest commit on the `snapshots` branch of [tile-ai/TileOPs-nightly](https://github.com/tile-ai/TileOPs-nightly) (`scripts/render_bench.sh` fetches it) | - -`hooks.py` rewrites the repo-relative paths mirrored content arrives with, and -expands the single `Benchmarks` nav entry to the pages the renderer produced. - -Which ops a `docs/api/` page names is written by hand and drifts as TileOPs adds -and removes ops. The deploy and the daily refresh run -`scripts/check_api_pages.py` against the checkout they just made. - -## Benchmarks pages - -One question per workload: how TileOPs compares to the fastest other -implementation of the same op on that workload. - -| Rule | Detail | -|------|--------| -| No aggregates | One table per op, one row per workload. Why: an op's workloads span shapes orders of magnitude apart, so a median matches no reproducible run | -| The colour is the verdict | `Ratio` sits right after the workload name: red behind, plain ink level, green ahead, grey where the only rival is an eager `-ref` | -| Device time | Compare `device_busy_ms`, never wall-clock span | -| Two questions | `Ratio`: is another kernel faster. `SOL`: how much faster the hardware allows anyone to go, its binding resource (`mem`/`comp`/`lat`) in a `Bound` column. Import the SOL arithmetic and thresholds from the checkout's roofline tool (M5); never re-derive them here | -| Which page an op lands on | The manifest entry's `family:`, through `_MANIFEST_FAMILY` — an op TileOPs adds needs no change here. One the manifest does not declare falls back to its package, then to keywords | -| Page order | `DATA_PAGES`: Elementwise, RoPE, Reduction, Normalization, Conv & Pool, GEMM, Quantization & Dequantization, Attention, MoE, Sampling, Linear Attention, SSM, Other. One page per family except `Conv & Pool` (two) and `Other` (FFT, mHC, Engram, the rest). `TopKSelectFwdOp` declares `family: attention`, so its row is on Attention, while the API Reference documents it on the Sampling page. The API Reference nav follows it, with FFT, mHC and Engram after SSM and Top-k on the Sampling page. `_BENCH_ORDER` in `hooks.py` repeats it — change all three together | -| Op order within a page | The order `docs/api/` names them, read by `api_op_order()`. An op no API page names comes last, ranked by verdict | -| Rows follow the manifest | One row group per manifest label, one row per dtype under it in a `dtype` column. Labels keep the snapshot's order, which is the manifest's; the key above the table repeats it. A row no manifest describes takes its id, trailing dtype names split off, as its label | -| Workload shapes | The snapshot names a workload but carries no shapes. `scripts/workload_shape.py` reads them from the spec manifest at the commit the benchmark ran on, joined by the `