# LLM review rules — openwrt/packages The review routine reads this at session start. General contribution rules (commit subject prefix, Signed-off-by, real-name author, line length) live in [`CONTRIBUTING.md`](../CONTRIBUTING.md). ## Review posture Separate formatting that changes what gets built from formatting that is only a matter of taste. The first kind is a real defect and belongs in a review: a space where make expects a tab in a recipe, indentation in `conffiles` or in an install scriptlet that ends up inside the generated file, CRLF line endings, a `define` block that is never closed. These break the build or ship a broken package, and severity does not depend on how small the diff looks. The second kind — alignment, blank lines, the order of `KEY:=value` entries, a house style a package has not followed for years — is secondary. Maintainers here would rather merge a correct change with a small style wart than hold it up over one, so: - Lead with correctness, security and packaging bugs. Keep cosmetic remarks few, mark them as optional, and say plainly which findings (if any) actually block a merge. - Do not restate what the formality bot already posted. Sign-off, no-reply e-mail, subject/body length, CRLF, `PKG_VERSION` / `PKG_RELEASE`, `conffiles` layout, patch headers and OpenWrt metadata are checked by [`formalities.json`](formalities.json). The rules below explain the reasoning behind those checks and cover what the bot cannot see — they are not a second checklist to run. - CI is a reference, not a gate. A red job can just as easily be a gap in the test harness as a defect in the PR. Describe what failed and leave the call to the maintainer instead of demanding a green run. ## Package Version and Release (`PKG_VERSION`, `PKG_RELEASE`) - **Reset release on upgrade.** When a package's `PKG_VERSION` is updated/upgraded, the `PKG_RELEASE` must be reset to `1`. - **Increment release on modification.** When modifying build logic, adding patches, changing dependencies (`DEPENDS`), or modifying configuration/scripts (e.g. init scripts, hotplug handlers) without updating `PKG_VERSION`, the `PKG_RELEASE` must be incremented. - **Do not increment release for minor changes.** Cosmetic edits (e.g., typos in comments, copyright updates, formatting/whitespace), changing the package maintainer (`PKG_MAINTAINER`), or updating source download info (`PKG_SOURCE_URL` / `PKG_HASH`) do not require incrementing `PKG_RELEASE`. ## Patches ### Patch regeneration OpenWrt patches are quilt-managed and **not** refreshed with `git format-patch`. When a patch's hunk headers, fuzz, or context need to be regenerated, the project-specific command is: - `make package//refresh` (e.g. `make package/lsof/refresh`) If a patch's metadata or format is incorrect, recommend using the matching `make package//refresh` command, not `git format-patch`. ### Patch metadata / format A patch that is a candidate for upstream submission should be upstream-ready, which means it carries: - A descriptive subject and body explaining why the patch is needed. - A valid `Signed-off-by` header matching the patch author. - An upstream reference, pull request link, or `Upstream-Status` indicating if/where the patch has been submitted upstream. This bar is not meant for every patch in the feed. Many are OpenWrt-specific hacks — cross-compile fixes, toolchain and path adjustments, musl workarounds — that will never be sent anywhere, and plenty are one or two lines whose intent is obvious from the diff itself. There a short subject is enough: do not ask for a written justification of a self-evident change, and do not ask for an upstream reference on a patch that has no upstream to go to. Reserve the full requirement for patches that are non-trivial or that change behaviour in a way a reader cannot infer. ## Package Sources and Mirrors - **Prefer archive tarballs over git clones.** `PKG_SOURCE_PROTO:=git` should only be used as a last resort if no release tarballs (xz, gz, bzip2, zip) are available. - **Use mirror macros.** Prefer predefined mirror macros (e.g., `@GITHUB`, `@SF`, `@GNU`, `@GNOME`, `@SAVANNAH`, `@APACHE`, `@KERNEL`) in `PKG_SOURCE_URL` rather than hardcoding the full domain. ## Avoid reuse of `PKG_NAME` - Do not reuse the `PKG_NAME` variable in `call`, `define`, and `eval` lines. Use the literal name of the package instead to improve readability. - *Correct:* `$(eval $(call BuildPackage,lsof))` - *Incorrect:* `$(eval $(call BuildPackage,$(PKG_NAME)))` ## Makefile indentation Which character to indent a `define` block with depends on what the block is — make only requires tabs where the block is a recipe: - **Two spaces** for metadata blocks, whose body is a list of `KEY:=value` lines: `define Package/` and `define KernelPackage/`. - **Tabs** for blocks whose body is shell run by make as a recipe: `define Build/*` (`Build/Configure`, `Build/Compile`, `Build/InstallDev`, …) and `define Package//install`. - **No indentation** for blocks that are written out verbatim as a file: `define Package//conffiles` (see below) and the `preinst` / `postinst` / `prerm` / `postrm` scriptlets. Both go through `BuildPackVariable` in `include/package-pack.mk`, which echoes the block into a generated file — leading whitespace ends up inside the resulting shell script rather than in a make recipe. - `define Package//description` (free-form prose) and `define Package//config` (Kconfig syntax, not `KEY:=value`) have no enforced convention. Two spaces dominate for the former and tabs for the latter, but neither is worth a comment on its own. Only raise indentation on lines the PR actually touches. A package that has used a different style throughout for years is not something a version bump has to fix. ## Package testing (CI / Runtime tests) - **Generic version check.** The CI automatically runs generic runtime checks on all package executables, executing them with version/help flags (e.g. `--version`, `--help`) and expecting the output to contain `PKG_VERSION`. - **Add `test-version.sh` for overrides.** If the package executables do not support these flags or do not output the version string, the generic test will fail. To override/bypass this check, a `test-version.sh` script must be added to the package's directory (e.g. checking the package name and returning 0). - **Add `test.sh` for custom tests.** A `test.sh` script can be added for custom runtime tests. Note that because generic tests are forced by default in CI, `test-version.sh` is still required if the executables fail the generic version check. - **Avoid quiet mode in grep.** Do not use `grep -q` (or `--quiet`) in `test.sh` or `test-version.sh` scripts when checking output or version strings. Leaving the matched lines in the output ensures that the printed version or status is logged and visible in CI/CD build logs. ## Init Scripts - **Use procd.** Service/init scripts (installed to `/etc/init.d/`) must use the procd process management system. They must include `USE_PROCD=1` and define `start_service()`. - **Avoid legacy backgrounding.** Do not use manually written daemon management (e.g. backgrounding with `&`, custom `stop()` loops, manual PID files) unless there is a strong, explicitly stated reason. - **Shebang.** All init scripts must use the shebang `#!/bin/sh /etc/rc.common`. ## Configuration Files (`conffiles`) - **Register config files.** If a package installs user-modifiable configuration files (typically under `/etc/config/` or `/etc/`), they must be registered in the `define Package//conffiles` section. - **Correct path formatting.** - Absolute paths must be used (starting with `/`). - Directories must end with a trailing slash `/`. - Individual files must NOT end with a trailing slash. - No indentation is allowed (do not start lines with spaces or tabs). ## Maintainer Info - **New packages require a maintainer.** When a new package is introduced, a `PKG_MAINTAINER` field must be defined in the Makefile, formatted as `Name `. ## Backports / cherry-picks PRs targeting `openwrt-NN.NN` branches or titled `[X.Y] ...` are backports. Their diffs should match the upstream commit on `master` verbatim. Code-style or packaging issues that already exist on the upstream commit belong on a fix-to-master PR, not on the backport — flag only deviations introduced by the cherry-pick itself, plus the missing `(cherry picked from commit )` trailer. `git cherry-pick -x` adds the trailer automatically. Not every stable-branch PR is a cherry-pick, though. A stable branch can legitimately carry a version that no longer exists on `master`: typically a minor update inside an LTS series that the branch stays pinned to, while `master` has already moved on to a newer major. Such a PR has no upstream commit to compare against and no `cherry picked from` trailer to ask for. Review it on its own merits and check only that the update stays inside the series the branch already ships.