chore(review): cut CodeRabbit round-trips and enforce the repeat defect classes - #6504
Conversation
…ct classes Review rounds were outrunning commits (#6499 hit 8 rounds over 6 commits) because auto_incremental_review re-ran a full pass on every fix push. The findings themselves were sound -- ~18 across 13 recent PRs, 1 Critical and 9 Major, zero style nitpicks -- so the fix is to shorten the loop and stop the same classes recurring, not to weaken the review. - auto_incremental_review: false, so fixes get batched into one push and re-reviewed once via `@coderabbitai review`. - Document the four recurring Major-finding classes in the code-review skill, which knowledge_base.code_guidelines already feeds to CodeRabbit -- one edit tightens both the authoring and reviewing ends. - Add two ast-grep rules enforcing the presence-vs-sentinel-zero class mechanically, since prose alone did not hold it: the audit found 9 live sites, including a temperature guard in NodeItemCompact.kt that the NodeItem.kt fix missed. Both rules validated against the tree; humidity (0 %RH unreachable, guard intentional and tested), rx_snr (no proto presence, unfixable app-side), replyId and packet.from are excluded. - Add two pre_merge_checks for what an AST rule cannot see: an unfixed sibling call site, and a test that would still pass if the fix were reverted. Warning, not error -- a false positive must not block a merge. - Drop three no-op tools entries; all 57 CodeRabbit tools default to enabled, so the block only needs to turn things off or configure them. - Pin learnings.scope to local, and skip a pre_merge title check since CI already lints PR titles. The nine flagged code sites are tracked separately; this change is config and documentation only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Ignoring CodeRabbit configuration file changes. For security, only the configuration from the base branch is applied for open source repositories. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughCodeRabbit configuration now controls incremental reviews, AST-grep rule loading, custom warning checks, and local learnings. Kotlin presence-semantics rules and recurring defect checklists were added to review guidance. ChangesReview automation and defect guidance
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.coderabbit.yaml (1)
117-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlign the SNR guidance with the
rx_snrexception.The signal rule explicitly excludes
rx_snrbecause the pinned protobuf lacks presence, but this custom check instructs reviewers to flag SNR zero defaults without that exception. Narrow the instruction to app-level fields with presence, or explicitly excluderx_snr, to avoid recreating the false positive this PR is removing.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.coderabbit.yaml around lines 117 - 120, Update the SNR portion of the custom review guidance in the configuration to exclude rx_snr, matching the existing signal-rule exception, or restrict the check to app-level SNR fields that support presence. Keep the zero-default warnings for the other listed physical measurements and preserve the humidity exception.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.coderabbit/ast-grep-rules/presence-vs-sentinel-zero-signal.yml:
- Around line 3-6: Update the presence-vs-sentinel-zero-signal rule to detect
Float zero literals in nullable RSSI patterns, including takeIf comparisons and
nullable fallback expressions, while preserving existing Int coverage and RSSI
exclusions in the separate float rule. Add regression fixtures covering both Int
and Float sentinel forms.
In @.skills/code-review/SKILL.md:
- Around line 16-17: Update the “Aggregates over empty sets” guidance in
SKILL.md to describe a zero fallback as introducing comparator-dependent bias,
rather than universally outranking real values. For RSSI specifically, state the
applicable ordering and explain the resulting ranking effect; preserve the
nullable aggregate and explicit missing-value comparator guidance.
---
Nitpick comments:
In @.coderabbit.yaml:
- Around line 117-120: Update the SNR portion of the custom review guidance in
the configuration to exclude rx_snr, matching the existing signal-rule
exception, or restrict the check to app-level SNR fields that support presence.
Keep the zero-default warnings for the other listed physical measurements and
preserve the humidity exception.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 59deeeb9-b279-4ce0-a3d5-ce70fccbf786
📒 Files selected for processing (4)
.coderabbit.yaml.coderabbit/ast-grep-rules/presence-vs-sentinel-zero-float.yml.coderabbit/ast-grep-rules/presence-vs-sentinel-zero-signal.yml.skills/code-review/SKILL.md
Three inconsistencies in the previous commit, two of them self-inflicted by describing #6498's end state as if it were already on main. - The "Sibling call sites" pre-merge check told reviewers to flag SNR zero defaults, while the ast-grep rule deliberately excludes rx_snr because it has no proto presence and cannot be fixed app-side. The check now carves out rx_snr while keeping app-level nullable SNR in scope. - The empty-aggregate warning claimed a 0 fallback "outranks every real negative RSSI", which is only true under a higher-is-better comparator; a plain min would pick 0 as the smallest instead. Reworded as a comparator-dependent bias, keeping the concrete ranking case. - The signal rule's message pointed at MetricFormatter.rssi(null), which does not exist on main -- the only overload is rssi(value: Int); the nullable one arrives with #6498. Message now states the requirement without naming an API that isn't there. Declined the suggestion to add Float RSSI patterns (?: 0f, takeIf { it != 0f }) to the signal rule. RSSI is an integer dBm value throughout -- proto rx_rssi: Int, Node.rssi: Int, MetricFormatter.rssi(value: Int) -- and no Float-typed rssi declaration exists, so those patterns would be dead. The rule now documents that scope and why, instead of over-claiming Int?/Float?. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Why
Review rounds were outrunning commits. PR #6499 took 8 CodeRabbit review rounds over 6 commits; #6498 took 5 over 4, #6497 5 over 3. The cause was mechanical, not qualitative:
auto_incremental_reviewdefaults totrue, so every single-commit fix push reopened a full review pass, which surfaced new findings mid-stream and multiplied the loop.The findings themselves are worth keeping. Across the last 13 non-bot PRs CodeRabbit produced ~18 findings — 1 Critical, 9 Major, 7 Minor, zero style nitpicks — and each one I checked was confirmed valid rather than argued down. They catch semantic bugs CI structurally cannot: presence-vs-zero, read-modify-write races across a suspend boundary, tests that pass for the wrong reason.
So this shortens the loop and stops the same classes recurring, rather than dialing the review down.
🛠️ Changes
Batch the reviews.
auto_review.auto_incremental_review: false— one review when the PR goes ready, then on demand via@coderabbitai reviewonce fixes are batched into a single push. #6499 would have been ~2 rounds instead of 8.Document the recurring classes. Four classes account for most Major findings, and none were written down: presence-vs-sentinel-zero, read–decide–write across a suspend boundary, tests that assert the end state instead of the path, and Room schema bumps without a migration test. They now lead
.skills/code-review/SKILL.md. Becauseknowledge_base.code_guidelines.filePatternsalready includes.skills/**/SKILL.md, this single edit tightens both the authoring and the reviewing end.Enforce class A mechanically. Prose alone did not hold it — an audit found 9 live sites still in the tree, including
(env.temperature ?: 0f) != 0finNodeItemCompact.ktthat theNodeItem.ktfix missed, so a node reporting exactly 0 °C shows no temperature in the compact row.tools.ast-grep.rule_dirsnow loads two Kotlin rules from.coderabbit/ast-grep-rules/.Two
pre_merge_checksfor what an AST rule cannot see, because it is about what is absent from a diff: an unfixed sibling call site, and a test that would still pass if the fix were reverted. Bothmode: warning, nevererror— these are judgment calls and a false positive must not block a merge.🧹 Cleanups
toolsentries. All 57 CodeRabbit tools default toenabled: true, so listinggitleaks/shellcheck/actionlintasenabled: truedid nothing; onlydetekt: falsewas load-bearing.presidio(PII),zizmor,buf,semgrepandtrivywere already running.knowledge_base.learnings.scope: local—autoalready resolves to local for public repos, but being explicit stops it shifting if visibility changes.pre_merge_checks.title: CI already lints PR titles inpull-request-target.yml, and duplicating CI is what created the noise this config removed.Reviewer notes
Scope: config and documentation only. No Kotlin changed. The nine flagged code sites — 6 float guards plus 2 RSSI display paths and 1 BLE advertisement default — are tracked as separate work, since one is a user-facing defect that deserves its own PR with regression tests.
The ast-grep rules are validated, not guessed. Run against the tree with
ast-grep scan -r <rule> core/ feature/ androidApp/ desktopApp/: 6 and 3 matches respectively, with these deliberate exclusions —relative_humidity,co2_humidityEnvironmentMetricsForGraphingTest.humidity_zeroFilteredOutasserts itrx_snrFloat = 0fupstream with no proto presence — genuinely unfixable app-side, so flagging it would be pure noisereplyId,packet.fromTwo ast-grep gotchas are captured in the rule files: patterns containing
?:must be quoted (YAML reads:as a mapping separator), and Rust's regex has no lookahead, so field names are anchored —co2otherwise matchedco2_humidity.Presence here is nullability, not
hasX(). The models are Wire-generated, so there is no presence accessor;EnvironmentMetrics.temperature/voltage/current/soil_temperatureare alreadyFloat? = null, which is why the zero-guards are discarding information the proto faithfully preserved. Notepacket.rx_rssiis stillInt = 0on the pinned2.7.26.130— nullability arrives with2.7.26.138in #6498, so the signal rule currently guards app-level nullable RSSI and becomes a proto regression guard once that lands.Testing Performed
No tests changed — spotless targets Kotlin and Kotlin-Gradle sources only, and no Kotlin or Gradle files are touched, so the baseline gradle run does not apply to this diff.
.coderabbit.yamlvalidated againstschema.v2.json: no unknown keys, no bad enums, nested array objects valid,custom_checksinstructions within the 10,000-char limit.core/,feature/,androidApp/,desktopApp/— match counts and exclusions as tabled above.coderabbit review --agent --include-untracked --base main) before pushing, which is the loop this PR sets up. It returned 2 Major findings on this very change, both applied: the signal rule's(rssi|snr)$constraint contradicted its own note thatrx_snris unfixable, and the checklist described== nullas a presence check when it tests absence.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores