RcppParallel 6.x rewrote its build: src/Makevars.in no longer has the
`USE_TBB=Linux` block the registry patch edited, so the patch could never
apply and every build logged "Patch for RcppParallel did not apply cleanly".
The workaround it implemented is also obsolete. 6.x bundles oneTBB 2022 and
builds it with cmake, which works on musl and with g++ 8-15, so there is no
longer a reason to link a system TBB -- and linking one publishes a binary
that needs a TBB the consumer does not have.
What is still broken upstream is the link order. configure.R names the TBB
directory with `-Wl,-L`, and gcc expands its own search dirs into `-L` options
ahead of anything forwarded verbatim with `-Wl,`, so on a build host with a
distro TBB installed `-ltbb` resolves to that library and RcppParallel.so
records its SONAME instead of the bundled `libtbb.so`. The new patch passes a
plain `-L` instead.
Verified on alpine 3.24, redhat 8 and ubuntu noble: RcppParallel gets NEEDED
libtbb.so with RPATH $ORIGIN/../lib and loads with every system libtbb moved
away, and rstan 2.32.7 compiles and loads against it with no makevars override
-- RcppParallel::CxxFlags() already emits -DTBB_INTERFACE_NEW -- so the rstan
entry is dropped too.
Summary:
- replace RcppParallel/system-tbb.patch with bundled-tbb-link-order.patch
- scope the RcppParallel entry to >=6.0.0 and widen its platforms to "*"
- drop the rstan entry, made redundant by the bundled oneTBB
- exclude local/patches/*.patch from the whitespace-mutating hooks, which
rewrote context lines in every diff
## Summary
Adds the curated **patch registry** and wiring that drives bincraft's new package-patching mechanism (see bincraft PR `feat/package-patching`).
Lets specific packages be patched (env/configure/Makevars overrides or source diffs) before pak installs them — including as transitive dependencies — so compiler-/OS-specific failures like RcppParallel's bundled TBB stop cascading.
## What's included
- `local/patches/registry.json` — initial entry: RcppParallel with `RCPP_PARALLEL_USE_TBB=0` for alpine / ubuntu-2604, plus `local/patches/README.md` schema docs.
- `local/validate-patches.R` — validates schema, referenced patch files, and ambiguous overlaps; clean failure + exit 1 (no stacktrace).
- `.pre-commit-config.yaml` — a `validate-patches` hook (re-runs when the registry or the validator changes).
- `local/build-one.R` / `local/build-all.R` — pass `patches = "local/patches"` to `bincraft::build_binary_package()`.
- `specs/2026-06-30-package-patching-design.md` and `plans/2026-06-30-package-patching-implementation.md`.
## ⚠️ Merge ordering (blocker)
This PR adds a `patches = ...` argument to `build_binary_package()` calls.
The `.crow/*.yaml` workflows currently pin bincraft **v4.2.3**, which does not accept that argument — CI will error with `unused argument (patches=...)` until:
1. bincraft **v4.3.0** is released (PR `feat/package-patching`), and
2. the pin is bumped in `.crow/build-all-versions-install-deps.yaml`, `.crow/build-all-versions.yaml`, and `.crow/process-updates.yaml`.
The `.crow` pin bump will be added to this PR once bincraft v4.3.0 is tagged. Do not merge before then.
Reviewed-on: #103
## Summary
Builds R-minor-sensitive CRAN packages once per installed R minor version (into per-minor S3 slots `…/contrib/<x.y>/`) and everything else once into the generic slot, driven by bincraft 4.2.0's ABI classifier. Both the full and iterative pipelines are covered.
## What's in here
**Detection / precompute**
- `local/r-minor-helpers.R` — pure `classify_from_metadata()` (NeedsCompilation / risky `LinkingTo`) + `parse_build_args()`, with unit tests.
- `local/packages-to-build.R` — adds a per-package `r_minor_sensitive` flag: cheap CRAN-metadata rules first, source download + `bincraft::needs_per_minor_recompile()` only for the ambiguous compiled subset (fail-safe to sensitive). Classified once per package, applied to all versions.
**Full build**
- `local/build-all.R` — passes the per-row `is_r_minor_sensitive` flag; new `--sensitive-only` mode builds just the risky subset.
- `.crow/build-all-versions-{amd64,arm64}.yaml` — install-deps persists the sensitive subset; build step runs a sensitive-only pass under each non-primary `/opt/R/*` minor; new step uploads the generic index plus a per-minor index for each minor.
**Iterative build**
- All 14 `.crow/process-updates-*.yaml` — primary pass uses `r_minor_detection = 'classifier'`; a sensitive-only multi-R pass builds risky updates under each other minor; per-minor index upload added.
**Tooling / housekeeping**
- Pins bincraft `v4.1.1` → `v4.2.0` across all workflows; removes the superseded standalone `build-r-minor-sensitive-packages.yaml`.
- Adds prek/pre-commit hooks (prettier, markdownlint, editorconfig-checker, yamllint, air) and applies them repo-wide; excludes the verbatim GPL `LICENSE.md` and auxiliary shell scripts.
- Design + implementation docs under `docs/superpowers/`.
## Requires before merge
- A `v4.2.0` git tag must be pushed on the bincraft repo (codefloe.com/rpkgs/bincraft) — the workflow install steps pin `@v4.2.0`. The full-build install-deps clones `main`, so it is unaffected.
Reviewed-on: #84