From d27fba9cb695115e1a9a80595fb21e07a9de4e27 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Fri, 9 Oct 2026 10:59:23 -0400 Subject: [PATCH 01/11] Basis for java agent rule skill --- .agents/skills/spotbugs/SKILL.md | 83 +++++++++++++++++++ .../spotbugs/references/other-vehicles.md | 53 ++++++++++++ .claude/skills/spotbugs | 1 + 3 files changed, 137 insertions(+) create mode 100644 .agents/skills/spotbugs/SKILL.md create mode 100644 .agents/skills/spotbugs/references/other-vehicles.md create mode 120000 .claude/skills/spotbugs diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md new file mode 100644 index 00000000000..6a0bbec8a09 --- /dev/null +++ b/.agents/skills/spotbugs/SKILL.md @@ -0,0 +1,83 @@ +--- +name: spotbugs +description: >- + Enable one mechanically enforceable lint or static-analysis rule in blocking CI, + preferring SpotBugs. Use when adding a SpotBugs detector, turning a repetitive PR + review theme into a lint, adding a ForbiddenAPIs signature, or writing a custom + Gradle source check. +user-invocable: true +context: fork +allowed-tools: + - Bash + - Read + - Grep + - Glob + - Edit + - Write +--- + +# Add a SpotBugs check + +Grow the blocking SpotBugs job **one check at a time**. Do not turn this +into a style-guide dump or a Spotless / google-java-format gate. + +Background: [`gradle/spotbugs.gradle`](../../../gradle/spotbugs.gradle), +[`gradle/spotbugFilters/exclude.xml`](../../../gradle/spotbugFilters/exclude.xml), +[detector list](https://spotbugs-in-kengo-toda.readthedocs.io/en/lqc-list-detectors/detectors.html). +Fallbacks: [other vehicles](references/other-vehicles.md). + +## This repository + +- First-party production sources: every Java module that applies `gradle/java_no_deps.gradle` +- Tasks that may report: `spotbugsMain`, `spotbugsMain_java11` +- Run: `./gradlew spotbugsMain -PskipTests` (optionally qualify with `:module:spotbugsMain`) +- CI: `check_base` / `check_inst` / `check_profiling` / `check_debugger` run Gradle `check`, which includes those tasks + +Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored trees out unless the user explicitly expands the filter. + +`omitVisitors` in `gradle/spotbugs.gradle` is the deferred-check list. `exclude.xml` is the path/class filter. `@SuppressFBWarnings` is the local override. + +## Hard constraints + +- Enable **one** check per change. Prefer removing one name from `omitVisitors` over adding a new detector. +- Do not enable a detector family or bulk-remove `omitVisitors` entries. +- Keep `ignoreFailures = false` on Main tasks. Do not mark GitLab `check_*` jobs `allow_failure`. +- Do not enable SpotBugs on test or smoke-test source sets unless asked. +- Do not widen `exclude.xml`, `onlyAnalyze`, or the Main-only task filter unless asked. +- Do not use `@SuppressFBWarnings` as the way to land a noisy check. Fix the finding, or leave the visitor omitted. +- Do not treat this as a format change. Run `./gradlew spotlessApply` only if you touched Java/Gradle files that Spotless owns. +- Keep `omitVisitors` accurate: a deferred detector belongs in that list, not in a comment elsewhere. + +## Workflow + +1. Classify the rule. Prefer SpotBugs. Read `gradle/spotbugs.gradle` and the [detector list](https://spotbugs-in-kengo-toda.readthedocs.io/en/lqc-list-detectors/detectors.html). + - If a visitor in `omitVisitors` matches, that is the check to enable. + - If a visitor is already absent from `omitVisitors`, the check is already on. Stop. + - If no SpotBugs detector can express the rule, follow [other vehicles](references/other-vehicles.md). Do not invent a custom SpotBugs detector unless the user asks. +2. Remove **one** visitor name from `omitVisitors`. +3. Run SpotBugs from the repo root: + + ```bash + ./gradlew spotbugsMain -PskipTests + ``` + + If the rule is scoped to one module, run that module's `spotbugsMain` first, then a broader `spotbugsMain` before finishing. +4. If it fails: + - Mechanical first-party fixes in `src/main/java` (and `src/main/java11`) are OK in the same change. + - Do not edit generated, vendored, or smoke-test sources to silence SpotBugs. + - Do not paper over findings with a blanket `exclude.xml` match or a pile of `@SuppressFBWarnings`. + - If the cleanup is large or opinionated, put the visitor back in `omitVisitors` (name the failing classes) and stop. Ask before a repo-wide rewrite. +5. Keep the check only if `spotbugsMain` exits 0. + +## Local command + +```bash +./gradlew spotbugsMain -PskipTests +``` + +HTML reports: `*/build/reports/spotbugs/spotbugsMain.html`. +Bug codes in those reports (`NP_…`, `DCN_…`) are **not** the `omitVisitors` names. Visitors are detector class names (`FindNullDeref`, `DefaultEncodingDetector`). Suppressions use the bug code: + +```java +@SuppressFBWarnings(value = "NP_BOOLEAN_RETURN_NULL", justification = "…") +``` diff --git a/.agents/skills/spotbugs/references/other-vehicles.md b/.agents/skills/spotbugs/references/other-vehicles.md new file mode 100644 index 00000000000..6551c57a253 --- /dev/null +++ b/.agents/skills/spotbugs/references/other-vehicles.md @@ -0,0 +1,53 @@ +# Other vehicles (only if SpotBugs cannot express the rule) + +Use this file after the [SpotBugs skill](../SKILL.md) classification step finds no matching detector. Do not start here. + +Pick the **narrowest** vehicle that can fail CI with low false positives. One rule per change, same as SpotBugs. + +## ForbiddenAPIs — unconditional banned call or class + +Config: [`gradle/forbiddenApiFilters/main.txt`](../../../../gradle/forbiddenApiFilters/main.txt), +[`gradle/forbiddenapis.gradle`](../../../../gradle/forbiddenapis.gradle). + +Use when the rule is “never call this method/class” with **no location qualifier** (not “only in `@Advice`”, not “only in premain”). + +1. Append **one** signature (and optional `@defaultMessage`) to `main.txt`. +2. Do not enable test `forbiddenApis*` tasks (they are disabled on purpose). +3. Verify: + + ```bash + ./gradlew forbiddenApisMain -PskipTests + ``` + +Escape hatch already in the codebase: `@SuppressForbidden`. Do not invent a second one. + +## Custom Gradle check — path-scoped or structural + +Existing pattern: [`ConfigInversionLinter`](../../../../buildSrc/src/main/kotlin/datadog/gradle/plugin/config/ConfigInversionLinter.kt), +[`InstrumentationNamingPlugin`](../../../../buildSrc/src/main/kotlin/datadog/gradle/plugin/naming/InstrumentationNamingPlugin.kt). +JavaParser is already a `buildSrc` dependency. + +Use when the rule needs source structure or a path filter SpotBugs cannot name, for example: + +- only inside `@Advice.OnMethodEnter` / `@Advice.OnMethodExit` +- only under bootstrap / premain +- module-directory or config-inventory conventions + +Do **not** add the rule to `ConfigInversionLinter` unless it is about supported configuration. Register a dedicated verification task and a GitLab job (or attach it to an existing `check*` aggregator) so it is a merge gate. + +Verify with the new task, then `./gradlew spotlessApply` on the Gradle/Kotlin files you touched. + +## Custom SpotBugs detector + +Do not write one unless the user explicitly asks **and** ForbiddenAPIs plus a Gradle source check are both a poor fit. Custom detectors are bytecode visitors with `findbugs.xml` / `messages.xml` plugin wiring; they are a poor default agent output. + +## Do not use + +| Vehicle | Why | +|---|---| +| Spotless | Formatter, not a review-theme lint | +| CodeNarc | Groovy-only; new Groovy is already blocked | +| ErrorProne / NullAway | Wired only in `:dd-java-agent:agent-iast` | +| `static-analysis.datadog.yml` | No in-repo CI job; not a required check | +| CodeQL / Trivy | Security scanners; not PR merge gates | +| One-off GitHub Action scripts | Fine for PR metadata, not for source conventions | diff --git a/.claude/skills/spotbugs b/.claude/skills/spotbugs new file mode 120000 index 00000000000..e681b4890a7 --- /dev/null +++ b/.claude/skills/spotbugs @@ -0,0 +1 @@ +../../.agents/skills/spotbugs \ No newline at end of file From 00be7e0004c616dc14368985c9f530a5018c95bc Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:33:34 -0400 Subject: [PATCH 02/11] Instructions to allow suppression --- .agents/skills/spotbugs/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index 6a0bbec8a09..c5b720061e6 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -44,7 +44,7 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr - Keep `ignoreFailures = false` on Main tasks. Do not mark GitLab `check_*` jobs `allow_failure`. - Do not enable SpotBugs on test or smoke-test source sets unless asked. - Do not widen `exclude.xml`, `onlyAnalyze`, or the Main-only task filter unless asked. -- Do not use `@SuppressFBWarnings` as the way to land a noisy check. Fix the finding, or leave the visitor omitted. +- Do not use `@SuppressFBWarnings` as the way to land a noisy check. If the detector is too noisy, leave the visitor omitted. For an intentional local exception, keep the detector enabled and annotate that site with `@SuppressFBWarnings(value = "…", justification = "…")`. - Do not treat this as a format change. Run `./gradlew spotlessApply` only if you touched Java/Gradle files that Spotless owns. - Keep `omitVisitors` accurate: a deferred detector belongs in that list, not in a comment elsewhere. @@ -65,7 +65,7 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr 4. If it fails: - Mechanical first-party fixes in `src/main/java` (and `src/main/java11`) are OK in the same change. - Do not edit generated, vendored, or smoke-test sources to silence SpotBugs. - - Do not paper over findings with a blanket `exclude.xml` match or a pile of `@SuppressFBWarnings`. + - Do not paper over findings with a blanket `exclude.xml` match. A justified `@SuppressFBWarnings` on an intentional exception is OK; a pile of suppressions to make a noisy detector pass is not. - If the cleanup is large or opinionated, put the visitor back in `omitVisitors` (name the failing classes) and stop. Ask before a repo-wide rewrite. 5. Keep the check only if `spotbugsMain` exits 0. From de30dc6897cfd29ca2ba057e99357fe9e1c1194f Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:40:24 -0400 Subject: [PATCH 03/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index c5b720061e6..8fd65956dcb 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -54,7 +54,7 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr - If a visitor in `omitVisitors` matches, that is the check to enable. - If a visitor is already absent from `omitVisitors`, the check is already on. Stop. - If no SpotBugs detector can express the rule, follow [other vehicles](references/other-vehicles.md). Do not invent a custom SpotBugs detector unless the user asks. -2. Remove **one** visitor name from `omitVisitors`. +2. Enable one visitor in the shared SpotBugs convention. Remove it from `omitVisitors` if present, or explicitly enable it if it is disabled by default. Review all bug patterns it reports and use `@SuppressFBWarnings` with a justification for intentional exceptions. 3. Run SpotBugs from the repo root: ```bash From eecf082e3c96f92ffc3624d1b88b9f71bea4a138 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:41:03 -0400 Subject: [PATCH 04/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index 8fd65956dcb..37321e43658 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -66,7 +66,7 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr - Mechanical first-party fixes in `src/main/java` (and `src/main/java11`) are OK in the same change. - Do not edit generated, vendored, or smoke-test sources to silence SpotBugs. - Do not paper over findings with a blanket `exclude.xml` match. A justified `@SuppressFBWarnings` on an intentional exception is OK; a pile of suppressions to make a noisy detector pass is not. - - If the cleanup is large or opinionated, put the visitor back in `omitVisitors` (name the failing classes) and stop. Ask before a repo-wide rewrite. + - If the cleanup is large or opinionated, undo this change's visitor activation and stop. Report the failing classes and the changes they need to the main assistant, so it can ask the user before starting a repo-wide rewrite. 5. Keep the check only if `spotbugsMain` exits 0. ## Local command From 810bc627df6a1d776792c70f9ac6b63ec7102f93 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:42:12 -0400 Subject: [PATCH 05/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index 37321e43658..2871d370e98 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -52,7 +52,7 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr 1. Classify the rule. Prefer SpotBugs. Read `gradle/spotbugs.gradle` and the [detector list](https://spotbugs-in-kengo-toda.readthedocs.io/en/lqc-list-detectors/detectors.html). - If a visitor in `omitVisitors` matches, that is the check to enable. - - If a visitor is already absent from `omitVisitors`, the check is already on. Stop. + - If a matching visitor is absent from `omitVisitors`, check its defaults in the SpotBugs version in use and the task configuration. Stop only if the detector is already enabled. - If no SpotBugs detector can express the rule, follow [other vehicles](references/other-vehicles.md). Do not invent a custom SpotBugs detector unless the user asks. 2. Enable one visitor in the shared SpotBugs convention. Remove it from `omitVisitors` if present, or explicitly enable it if it is disabled by default. Review all bug patterns it reports and use `@SuppressFBWarnings` with a justification for intentional exceptions. 3. Run SpotBugs from the repo root: From b554899391fb45d478c062e8caecf51f94f88d45 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:43:06 -0400 Subject: [PATCH 06/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/SKILL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index 2871d370e98..2f858f3d5a6 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -43,7 +43,8 @@ Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored tr - Do not enable a detector family or bulk-remove `omitVisitors` entries. - Keep `ignoreFailures = false` on Main tasks. Do not mark GitLab `check_*` jobs `allow_failure`. - Do not enable SpotBugs on test or smoke-test source sets unless asked. -- Do not widen `exclude.xml`, `onlyAnalyze`, or the Main-only task filter unless asked. +- Production source sets include `main` and version-specific sets such as `main_java11`, `main_java17`, `main_java21` and `main_java25`, etc. Check the shared SpotBugs convention for the enabled sets and report any coverage gaps. +- Do not widen `exclude.xml`, `onlyAnalyze`, or the production-source task filter unless asked. - Do not use `@SuppressFBWarnings` as the way to land a noisy check. If the detector is too noisy, leave the visitor omitted. For an intentional local exception, keep the detector enabled and annotate that site with `@SuppressFBWarnings(value = "…", justification = "…")`. - Do not treat this as a format change. Run `./gradlew spotlessApply` only if you touched Java/Gradle files that Spotless owns. - Keep `omitVisitors` accurate: a deferred detector belongs in that list, not in a comment elsewhere. From 3153330ab4e2aa14ae999202e3ceb2a786fbcbf1 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:43:32 -0400 Subject: [PATCH 07/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/SKILL.md b/.agents/skills/spotbugs/SKILL.md index 2f858f3d5a6..30ddf924ac5 100644 --- a/.agents/skills/spotbugs/SKILL.md +++ b/.agents/skills/spotbugs/SKILL.md @@ -33,7 +33,7 @@ Fallbacks: [other vehicles](references/other-vehicles.md). - Run: `./gradlew spotbugsMain -PskipTests` (optionally qualify with `:module:spotbugsMain`) - CI: `check_base` / `check_inst` / `check_profiling` / `check_debugger` run Gradle `check`, which includes those tasks -Leave tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored trees out unless the user explicitly expands the filter. +Preserve tests, smoke tests (`:dd-smoke-tests`), generated sources, and vendored trees out unless the user explicitly expands the filter. `omitVisitors` in `gradle/spotbugs.gradle` is the deferred-check list. `exclude.xml` is the path/class filter. `@SuppressFBWarnings` is the local override. From 5234b1660f07d0309e32298589bdc6507c8a2778 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:44:09 -0400 Subject: [PATCH 08/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/references/other-vehicles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/references/other-vehicles.md b/.agents/skills/spotbugs/references/other-vehicles.md index 6551c57a253..fe1e79005bd 100644 --- a/.agents/skills/spotbugs/references/other-vehicles.md +++ b/.agents/skills/spotbugs/references/other-vehicles.md @@ -12,7 +12,7 @@ Config: [`gradle/forbiddenApiFilters/main.txt`](../../../../gradle/forbiddenApiF Use when the rule is “never call this method/class” with **no location qualifier** (not “only in `@Advice`”, not “only in premain”). 1. Append **one** signature (and optional `@defaultMessage`) to `main.txt`. -2. Do not enable test `forbiddenApis*` tasks (they are disabled on purpose). +2. Preserve existing task enablement (they are disabled on purpose). 3. Verify: ```bash From 5996536abe4551c14169619a30d18494ca57ede2 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:45:02 -0400 Subject: [PATCH 09/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/references/other-vehicles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/references/other-vehicles.md b/.agents/skills/spotbugs/references/other-vehicles.md index fe1e79005bd..18e966e82dc 100644 --- a/.agents/skills/spotbugs/references/other-vehicles.md +++ b/.agents/skills/spotbugs/references/other-vehicles.md @@ -16,7 +16,7 @@ Use when the rule is “never call this method/class” with **no location quali 3. Verify: ```bash - ./gradlew forbiddenApisMain -PskipTests + ./gradlew forbiddenApis -PskipTests ``` Escape hatch already in the codebase: `@SuppressForbidden`. Do not invent a second one. From 51e21932c7bc95a56e1a00a5236be39d64947454 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:46:07 -0400 Subject: [PATCH 10/11] Apply suggestion from @bric3 Co-authored-by: Brice Dutheil --- .agents/skills/spotbugs/references/other-vehicles.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.agents/skills/spotbugs/references/other-vehicles.md b/.agents/skills/spotbugs/references/other-vehicles.md index 18e966e82dc..9a32198b77d 100644 --- a/.agents/skills/spotbugs/references/other-vehicles.md +++ b/.agents/skills/spotbugs/references/other-vehicles.md @@ -11,7 +11,17 @@ Config: [`gradle/forbiddenApiFilters/main.txt`](../../../../gradle/forbiddenApiF Use when the rule is “never call this method/class” with **no location qualifier** (not “only in `@Advice`”, not “only in premain”). -1. Append **one** signature (and optional `@defaultMessage`) to `main.txt`. +1. Add or update one rule in the appropriate shared signature file, including all required overloads. + - For a new rule, set its own `@defaultMessage` before its signatures, or give each signature an explicit inline message. + - For an existing rule, update its signatures and message in place. Keep added overloads with that rule and check which signatures inherit a changed `@defaultMessage`. + + For example, when extending a `System.getenv()` ban to its other overload, keep both signatures under the same message: + + ```text + @defaultMessage Use ConfigHelper to access environment variables. + java.lang.System#getenv() + java.lang.System#getenv(java.lang.String) + ``` 2. Preserve existing task enablement (they are disabled on purpose). 3. Verify: From b619afb80172879bee0029855a766671cadbf997 Mon Sep 17 00:00:00 2001 From: Colin Higgins Date: Sun, 18 Oct 2026 21:57:38 -0400 Subject: [PATCH 11/11] Final feedback --- .agents/skills/spotbugs/references/other-vehicles.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.agents/skills/spotbugs/references/other-vehicles.md b/.agents/skills/spotbugs/references/other-vehicles.md index 9a32198b77d..75ccd354f6e 100644 --- a/.agents/skills/spotbugs/references/other-vehicles.md +++ b/.agents/skills/spotbugs/references/other-vehicles.md @@ -6,12 +6,18 @@ Pick the **narrowest** vehicle that can fail CI with low false positives. One ru ## ForbiddenAPIs — unconditional banned call or class -Config: [`gradle/forbiddenApiFilters/main.txt`](../../../../gradle/forbiddenApiFilters/main.txt), -[`gradle/forbiddenapis.gradle`](../../../../gradle/forbiddenapis.gradle). +Plugin: `de.thetaphi.forbiddenapis`. Grep for that id (or `apply plugin: "de.thetaphi.forbiddenapis"`) and follow `signaturesFiles` to the shared lists; do not add a new signature file. + +Two lists exist today: + +- `main.txt` — common rules, applied by the default plugin config +- `instrumentation.txt` — extra rules the instrumentation convention adds on top of `main.txt` + +Put a repo-wide ban in `main.txt`. Put a ban that should apply only to instrumentation modules in `instrumentation.txt`. Leave plugin/task enablement in the module configuration. Use when the rule is “never call this method/class” with **no location qualifier** (not “only in `@Advice`”, not “only in premain”). -1. Add or update one rule in the appropriate shared signature file, including all required overloads. +1. Add or update one rule in the matching signature file, including all required overloads. - For a new rule, set its own `@defaultMessage` before its signatures, or give each signature an explicit inline message. - For an existing rule, update its signatures and message in place. Keep added overloads with that rule and check which signatures inherit a changed `@defaultMessage`.