Skip to content

Enforce strict version matching in doctor and recommend doctor on errors#3070

Merged
justin808 merged 16 commits intomainfrom
jg/doctor-strict-versions
Apr 7, 2026
Merged

Enforce strict version matching in doctor and recommend doctor on errors#3070
justin808 merged 16 commits intomainfrom
jg/doctor-strict-versions

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented Apr 5, 2026

Summary

  • Escalate doctor wildcard checks from warnings to errors — matching runtime VersionChecker behavior that hard-crashes on non-exact versions (^, ~, >=). Previously, doctor only warned about these patterns while the app would crash at boot.
  • Extend wildcard checks to cover Pro packagescheck_npm_wildcards and check_gem_wildcards now check both react-on-rails/react_on_rails and react-on-rails-pro/react_on_rails_pro.
  • Add doctor recommendation to all VersionChecker error messages — every runtime crash from version_checker.rb now tells users to run bundle exec rake react_on_rails:doctor.
  • Add doctor recommendation to configuration and packer_utils errors — config validation errors, autobundling errors, and compile conflicts all now suggest running doctor.
  • Doctor suggests sync_versions on version mismatches — error messages now include bundle exec rake react_on_rails:sync_versions WRITE=true as a fix.
  • FIX=true doctor auto-runs sync_versions — when doctor detects version issues and FIX mode is enabled, it automatically syncs package.json versions to match gem versions.
  • sync_versions now handles range specs instead of skipping them — previously ^16.5.0, ~16.5.0, >=16.5.0 were reported as "unsupported" and skipped. Now they're parsed, the range prefix is stripped, and the version is rewritten to the exact expected version.

Addresses review feedback from #2893 (review)

Test plan

  • version_checker_spec.rb — 74 examples, 0 failures
  • version_synchronizer_spec.rb — 20 examples, 0 failures (updated test for new range-handling behavior)
  • system_checker_spec.rb — 81 examples, 0 failures (updated tests for error vs warning escalation)
  • doctor_spec.rb — 152 examples, 0 failures
  • RuboCop — 0 offenses on all changed files

��� Generated with Claude Code


Note

Medium Risk
Tightens version validation from warnings to errors and adds auto-fix behavior, which may cause previously passing CI/boot flows to fail until versions are pinned exactly. Changes are mostly in diagnostic tooling but affect startup/runtime error paths and developer workflows.

Overview
Makes version hygiene strict and actionable: react_on_rails:doctor now treats non-exact gem/npm specs (^, ~, >=, etc.) as errors (including Pro gems/packages) and can auto-run sync_versions when FIX=true to rewrite range specs to exact expected versions.

Improves remediation messaging across the stack by adding a shared ReactOnRails::DOCTOR_RECOMMENDATION to configuration/autobundling validations and VersionChecker runtime crashes, and by updating mismatch errors to recommend bundle exec rake react_on_rails:sync_versions WRITE=true.

sync_versions is enhanced to parse and rewrite supported semver range prefixes (and npm alias variants) while refusing rewrites that would violate a declared >= lower bound; tests and a React 18/19-compatible act helper in the TanStack Router Pro test are updated accordingly.

Reviewed by Cursor Bugbot for commit 223edd4. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Optional automatic version synchronization that can update package files and report changes.
  • Bug Fixes

    • Non-exact version constraints and minor-version mismatches now produce errors (with clearer remediation steps).
    • Improved handling of workspace/local package specs and stricter version-matching diagnostics.
  • Chores

    • Diagnostic messages now include guidance to run the doctor task for remediation.
  • Tests

    • Updated tests and test helpers to reflect the new validation and sync behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a DOCTOR_RECOMMENDATION constant and appends it to many diagnostic messages; promotes non-exact gem/npm constraints to errors; adds automatic version synchronization (VersionSynchronizer auto-fix), refactors version parsing to track non-exact specs, and updates related tests.

Changes

Cohort / File(s) Summary
Core constant & message updates
react_on_rails/lib/react_on_rails/error.rb, react_on_rails/lib/react_on_rails/configuration.rb, react_on_rails/lib/react_on_rails/version_checker.rb, react_on_rails/lib/react_on_rails/packer_utils.rb
Adds ReactOnRails::DOCTOR_RECOMMENDATION and appends it to multiple raised error/warning messages and heredocs; message content/formatting changes only.
Doctor & diagnostics
react_on_rails/lib/react_on_rails/doctor.rb, react_on_rails/lib/react_on_rails/system_checker.rb
Adds auto_fix_versions (calls VersionSynchronizer with write), reorganizes wildcard/non-exact checks into helpers, and escalates non-exact/generic-range constraints to error-level diagnostics with updated ordering.
Version synchronization & parsing
react_on_rails/lib/react_on_rails/version_synchronizer.rb
Parsers now return a non_exact flag; supports npm alias parsing and strips forward-looking range prefixes for validation; avoids unnecessary updates for non-exact specs when appropriate.
Packer helpers
react_on_rails/lib/react_on_rails/packer_utils.rb
Autobundling-related error helpers now include the doctor recommendation in their multi-line messages.
System checker refactor
react_on_rails/lib/react_on_rails/system_checker.rb
Removes prior pattern-check methods, centralizes mismatch reporting via report_version_mismatch, and treats non-major mismatches as errors requiring sync.
Tests
react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb, react_on_rails/spec/lib/react_on_rails/version_synchronizer_spec.rb, packages/react-on-rails-pro/tests/tanstackRouter.test.ts
Updated expectations to reflect new error vs warning behavior, VersionSynchronizer write/rewrite outcomes, and act fallback logic in JS test helper.

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer
  participant Doctor as Doctor
  participant VS as VersionSynchronizer
  participant FS as FileSystem

  Dev->>Doctor: run doctor (--fix)
  Doctor->>VS: auto_fix_versions (sync write: true)
  VS->>VS: parse specs (parse_supported_spec / parse_npm_alias_spec / strip_range_prefix)
  alt changes detected
    VS->>FS: write updated package.json
  end
  VS-->>Doctor: return changes, unsupported_specs
  Doctor-->>Dev: emit diagnostics (messages include DOCTOR_RECOMMENDATION)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through json, gems, and versioned tracks,
I nibbled at ranges and straightened the facts,
A doctor's note now follows each warning and shout,
I synced what I could and left the rest without doubt,
Hop, fix, report — from my burrow, cheers and claps!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Enforce strict version matching in doctor and recommend doctor on errors' clearly and accurately summarizes the main changes: stricter version enforcement in the doctor tool and addition of doctor recommendations to error messages.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jg/doctor-strict-versions

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/version_synchronizer.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/error.rb
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Wrong version used for pro package install command
    • Updated check_npm_wildcard_for to choose the Pro gem version for react-on-rails-pro install commands instead of always using the base gem version.
  • ✅ Fixed: Duplicate Gemfile and npm wildcard checks produce repeated errors
    • Removed the extra Doctor-level wildcard check call from check_react_on_rails_versions so only SystemChecker emits those version-pattern errors once.

Create PR

Or push these changes by commenting:

@cursor push 060361f0e2
Preview (060361f0e2)
diff --git a/react_on_rails/lib/react_on_rails/doctor.rb b/react_on_rails/lib/react_on_rails/doctor.rb
--- a/react_on_rails/lib/react_on_rails/doctor.rb
+++ b/react_on_rails/lib/react_on_rails/doctor.rb
@@ -142,9 +142,8 @@
     end
 
     def check_react_on_rails_versions
-      # Use system_checker for comprehensive package validation instead of duplicating
+      # SystemChecker already validates wildcard/version-pattern constraints.
       checker.check_react_on_rails_packages
-      check_version_wildcards
       check_pro_package_consistency
       auto_fix_versions if fix
     end
@@ -565,8 +564,13 @@
       return unless npm_version
 
       if /[~^><*]/.match?(npm_version) || npm_version.include?(" ")
+        gem_version = if package_name == "react-on-rails-pro"
+                        ReactOnRails::Utils.react_on_rails_pro_version
+                      else
+                        ReactOnRails::VERSION
+                      end
         install_cmd = ReactOnRails::Utils.package_manager_install_exact_command(
-          package_name, ReactOnRails::VersionSyntaxConverter.new.rubygem_to_npm(ReactOnRails::VERSION)
+          package_name, ReactOnRails::VersionSyntaxConverter.new.rubygem_to_npm(gem_version)
         )
         checker.add_error(<<~MSG.strip)
           🚫 package.json uses a non-exact version for #{package_name}: #{npm_version}

diff --git a/react_on_rails/spec/lib/react_on_rails/doctor_spec.rb b/react_on_rails/spec/lib/react_on_rails/doctor_spec.rb
--- a/react_on_rails/spec/lib/react_on_rails/doctor_spec.rb
+++ b/react_on_rails/spec/lib/react_on_rails/doctor_spec.rb
@@ -84,6 +84,41 @@
     end
   end
 
+  describe "#check_react_on_rails_versions" do
+    let(:doctor) { described_class.new(verbose: false, fix: false) }
+    let(:checker) { doctor.instance_variable_get(:@checker) }
+
+    before do
+      allow(checker).to receive(:check_react_on_rails_packages)
+      allow(doctor).to receive(:check_pro_package_consistency)
+    end
+
+    it "relies on SystemChecker for version-pattern checks" do
+      expect(checker).to receive(:check_react_on_rails_packages)
+      expect(doctor).not_to receive(:check_version_wildcards)
+      expect(doctor).to receive(:check_pro_package_consistency)
+
+      doctor.send(:check_react_on_rails_versions)
+    end
+  end
+
+  describe "#check_npm_wildcard_for" do
+    let(:doctor) { described_class.new(verbose: false, fix: false) }
+
+    it "uses the Pro gem version in the install command for react-on-rails-pro" do
+      allow(ReactOnRails::Utils).to receive(:react_on_rails_pro_version).and_return("16.4.1")
+      expect(ReactOnRails::Utils).to receive(:package_manager_install_exact_command)
+        .with("react-on-rails-pro", "16.4.1")
+        .and_return("npm install react-on-rails-pro@16.4.1")
+
+      doctor.send(
+        :check_npm_wildcard_for,
+        { "react-on-rails-pro" => "^16.4.0" },
+        "react-on-rails-pro"
+      )
+    end
+  end
+
   describe "#check_react_on_rails_initializer" do
     let(:doctor) { described_class.new(verbose: false, fix: false) }
     let(:checker) { doctor.instance_variable_get(:@checker) }

You can send follow-ups to the cloud agent here.

Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 5, 2026

Review: Enforce strict version matching in doctor and recommend doctor on errors

Overall this is a well-structured PR that properly aligns the Doctor/SystemChecker diagnostic behavior with the runtime enforcement already in VersionChecker. The escalation from warnings to errors is justified, the FIX=true auto-remediation is a nice ergonomic improvement, and the range-spec handling in VersionSynchronizer fills a real gap. Test coverage is thorough.

I left inline comments for the issues below — one is a bug, the rest are design/consistency concerns.


Bug (should fix before merge)

check_npm_wildcard_for always uses ReactOnRails::VERSION for the pro package install suggestion (comment).
When package_name == "react-on-rails-pro", the suggested install command will reference the base gem version instead of the pro gem version. The fix is straightforward — use ReactOnRails::Utils.react_on_rails_pro_version when the package is pro.


Design concerns

FIX=true leaves prior errors in the checker output (comment).
Wildcard/mismatch errors are recorded first, then auto_fix_versions adds a success. The final report shows both: errors that were already resolved. If exit_with_status counts those errors as failures the process also exits non-zero after a successful fix, which would break CI workflows that use FIX=true.

check_npm_wildcards only scans two dependency sections (comment).
VersionSynchronizer checks all four sections (dependencies, devDependencies, optionalDependencies, peerDependencies), but the doctor wildcard check only merges the first two. A non-exact version in peerDependencies would be silently missed by doctor then rewritten by sync_versions.


Smaller issues

  • strip_range_prefix regex includes < and = (comment) — <=16.0.0 would be silently pinned to 16.0.0, discarding an intentional upper-bound constraint.
  • DOCTOR_RECOMMENDATION lives in error.rb (comment) — minor discoverability nit; a utility string alongside an error class is easy to overlook.
  • _gem_version parameter in check_version_patterns is now fully unused (comment) — worth cleaning up.

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This PR improves the developer experience by making wildcard version constraints hard errors (matching runtime behavior), adding bundle exec rake react_on_rails:doctor guidance to all relevant error messages, extending Pro-package coverage, and teaching sync_versions to rewrite range specs (^, ~, >=) rather than skip them.

Overall assessment: Safe to merge after fixing the wrong version in the Pro package install command suggestion (see inline comment). All other changes are clean improvements.

Confidence score: 4/5


File Analyses

File Confidence Summary
doctor.rb 3/5 Adds auto_fix_versions, escalates wildcard checks to errors, extends Pro checks; check_npm_wildcard_for uses wrong version for Pro install command
system_checker.rb 5/5 Escalates wildcard version checks from warnings to errors and extends checks to cover Pro packages
version_checker.rb 5/5 Adds DOCTOR_RECOMMENDATION to all runtime version error messages
version_synchronizer.rb 5/5 Adds range-prefix stripping so ^/~/>= specs are parsed and rewritten instead of skipped
error.rb 5/5 Introduces DOCTOR_RECOMMENDATION constant for consistent error messaging
configuration.rb 5/5 Appends DOCTOR_RECOMMENDATION to configuration validation error messages
packer_utils.rb 5/5 Appends DOCTOR_RECOMMENDATION to nested_entries and autobundling error messages
system_checker_spec.rb 5/5 Updates tests to expect errors instead of warnings for wildcard version patterns
version_synchronizer_spec.rb 5/5 Updates test to reflect new range-spec rewriting behavior instead of skipping

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant VC as VersionChecker (runtime)
    participant Doc as Doctor rake task
    participant SS as SystemChecker
    participant VS as VersionSynchronizer

    Dev->>VC: App boots
    VC-->>Dev: Error + DOCTOR_RECOMMENDATION if wildcard/mismatch

    Dev->>Doc: bundle exec rake react_on_rails:doctor [FIX=true]
    Doc->>SS: check_react_on_rails_packages
    SS-->>Doc: errors on wildcard constraints (npm & gem)
    Doc->>SS: check_version_wildcards (npm + gem, base + pro)
    SS-->>Doc: error if ^/~/>=  found
    Doc->>SS: check_pro_package_consistency
    SS-->>Doc: error on mismatched pro/base setup
    alt FIX=true
        Doc->>VS: sync(write: true)
        VS-->>Doc: rewrites range specs to exact versions
        Doc-->>Dev: versions synced
    else FIX=false
        Doc-->>Dev: Suggest sync_versions WRITE=true
    end
Loading

Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 5, 2026

Greptile Summary

This PR improves the developer experience by making wildcard version constraints hard errors (matching runtime behavior), adding bundle exec rake react_on_rails:doctor guidance to all relevant error messages, extending Pro-package coverage, and teaching sync_versions to rewrite range specs (^, ~, >=) rather than skip them. One P1 defect: check_npm_wildcard_for in doctor.rb always uses ReactOnRails::VERSION for the suggested install command, so when called for react-on-rails-pro the command will reference the base gem version instead of the Pro version.

Confidence Score: 4/5

Safe to merge after fixing the wrong version in the Pro package install command suggestion

One P1 bug where the doctor wildcard-fix command for react-on-rails-pro will suggest the wrong package version; all other changes are clean improvements with passing specs

react_on_rails/lib/react_on_rails/doctor.rb lines 568-570

Important Files Changed

Filename Overview
react_on_rails/lib/react_on_rails/doctor.rb Adds auto_fix_versions, escalates wildcard checks to errors, extends Pro checks; check_npm_wildcard_for uses wrong version for Pro install command
react_on_rails/lib/react_on_rails/system_checker.rb Escalates wildcard version checks from warnings to errors and extends checks to cover Pro packages
react_on_rails/lib/react_on_rails/version_checker.rb Adds DOCTOR_RECOMMENDATION to all runtime version error messages
react_on_rails/lib/react_on_rails/version_synchronizer.rb Adds range-prefix stripping so ^/~/>= specs are parsed and rewritten instead of skipped
react_on_rails/lib/react_on_rails/error.rb Introduces DOCTOR_RECOMMENDATION constant for consistent error messaging
react_on_rails/lib/react_on_rails/configuration.rb Appends DOCTOR_RECOMMENDATION to configuration validation error messages
react_on_rails/lib/react_on_rails/packer_utils.rb Appends DOCTOR_RECOMMENDATION to nested_entries and autobundling error messages
react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb Updates tests to expect errors instead of warnings for wildcard version patterns
react_on_rails/spec/lib/react_on_rails/version_synchronizer_spec.rb Updates test to reflect new range-spec rewriting behavior instead of skipping

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant VC as VersionChecker (runtime)
    participant Doc as Doctor rake task
    participant SS as SystemChecker
    participant VS as VersionSynchronizer

    Dev->>VC: App boots
    VC-->>Dev: Error + DOCTOR_RECOMMENDATION if wildcard/mismatch

    Dev->>Doc: bundle exec rake react_on_rails:doctor [FIX=true]
    Doc->>SS: check_react_on_rails_packages
    SS-->>Doc: errors on wildcard constraints (npm & gem)
    Doc->>SS: check_version_wildcards (npm + gem, base + pro)
    SS-->>Doc: error if ^/~/>=  found
    Doc->>SS: check_pro_package_consistency
    SS-->>Doc: error on mismatched pro/base setup
    alt FIX=true
        Doc->>VS: sync(write: true)
        VS-->>Doc: rewrites range specs to exact versions
        Doc-->>Dev: versions synced
    else FIX=false
        Doc-->>Dev: Suggest sync_versions WRITE=true
    end
Loading

Reviews (1): Last reviewed commit: "Enforce strict version matching in docto..." | Re-trigger Greptile

Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
react_on_rails/lib/react_on_rails/doctor.rb (1)

144-150: ⚠️ Potential issue | 🟠 Major

Run the version checks after FIX=true writes package.json.

Line 149 mutates the file only after checker.check_react_on_rails_packages and check_version_wildcards have already recorded errors from the old contents. A successful sync will still leave stale errors in checker.messages, so FIX=true rake react_on_rails:doctor can exit non-zero even though it already repaired the version drift.

♻️ Proposed fix
     def check_react_on_rails_versions
+      auto_fix_versions if fix
       # Use system_checker for comprehensive package validation instead of duplicating
       checker.check_react_on_rails_packages
       check_version_wildcards
       check_pro_package_consistency
-      auto_fix_versions if fix
     end

Also applies to: 585-602

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/lib/react_on_rails/doctor.rb` around lines 144 - 150, The
current check_react_on_rails_versions flow runs
checker.check_react_on_rails_packages and check_version_wildcards before
auto_fix_versions, causing stale errors in checker.messages after FIX=true
writes package.json; change the flow so that if fix is truthy you call
auto_fix_versions (which mutates package.json) before invoking
checker.check_react_on_rails_packages and check_version_wildcards, and clear or
re-run checker.messages (or reinstantiate the checker) after the auto-fix so the
subsequent checks reflect the updated file; apply the same reorder+clear logic
to the analogous block/method around the 585-602 region to prevent the same
stale-error issue.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@react_on_rails/lib/react_on_rails/doctor.rb`:
- Around line 568-579: The error message builds install_cmd using
ReactOnRails::VERSION which causes incorrect npm install suggestions for Pro
users; change the logic that computes install_cmd (where
ReactOnRails::Utils.package_manager_install_exact_command is invoked) to use
ReactOnRails::Utils.react_on_rails_pro_version when the package_name corresponds
to the Pro package (or when react_on_rails_pro_version is present) instead of
always using ReactOnRails::VERSION, then pass that computed version into
ReactOnRails::VersionSyntaxConverter and keep the rest of the checker.add_error
message intact so the fix hint points to the correct Pro gem version.
- Around line 527-544: The gem and npm wildcard checks are too permissive;
update check_gem_wildcard_for to examine all Gemfile lines for a given gem (not
just the first match) and detect missing or continuation-line version specs
(treat absence or version on following lines as non-exact) and update
check_npm_wildcard_for to stop using a simple blacklist and instead call or
reuse VersionChecker.semver_wildcard? to determine if an npm spec is non-exact
(treat numeric ranges like "19", "19.0", tags like "latest"/"beta", and range
operators as wildcards); keep using checker.add_error and checker.add_success
but base the decision on VersionChecker.semver_wildcard? (or equivalent
exact-match whitelist) and ensure the suggested exact gem version uses the same
ReactOnRails::VERSION / Utils.react_on_rails_pro_version logic already present.

In `@react_on_rails/lib/react_on_rails/system_checker.rb`:
- Around line 247-259: The code currently converts any gem/npm version mismatch
into a hard doctor error (add_error) and recommends sync_versions, but that
should not happen for workspace: or local path/URL installs which VersionChecker
explicitly skips and which VersionSynchronizer cannot rewrite; update the
mismatch branch in system_checker.rb to first detect local/workspace specs using
VersionChecker (call the existing helper that identifies skipped/local specs,
e.g. VersionChecker.local_spec? or VersionChecker.skipped_spec?) and if true do
NOT call add_error or recommend sync_versions (either skip the check or emit a
non-failing warning/message); otherwise keep the existing add_error with
gem_version, package_name, npm_version and the sync_versions fix text. Ensure
you reference and reuse the VersionChecker helper so local-link/monorepo setups
are not hard-errored.
- Around line 766-785: The current check_gemfile_version_pattern_for method only
matches a subset of non-exact operators; replace the fragile regex-based
detection with proper parsing using RubyGems API: for the found gem_line (in
check_gemfile_version_pattern_for) extract the version requirement (e.g. via
Gem::Requirement.extract or Gem::Requirement.new on the version string parsed
from gem_line) and call .exact? to decide if it’s an exact constraint; if not
exact, call add_error with the same message (using
ReactOnRails::Utils.react_on_rails_pro_version or ReactOnRails::VERSION for
#{gem_name}) so all non-exact operators like >, <, <=, >=, ~, ^ are reliably
caught.

In `@react_on_rails/lib/react_on_rails/version_synchronizer.rb`:
- Around line 149-156: The normalization in strip_range_prefix currently
discards whether the original spec was a range (non-exact), causing
detect_changes to treat range specs like exact pins; modify the
parsing/normalization so you preserve a boolean flag (e.g.,
parsed_spec[:non_exact]) when the original version_spec contained range prefixes
or non-exact forms, and update detect_changes to skip only when
normalized_current_version == expected_version AND parsed_spec[:non_exact] is
false (i.e., only skip exact-original specs); ensure this non_exact flag is set
where strip_range_prefix/related parsing runs and used in the detect_changes
comparisons that reference normalized_current_version and expected_version.

---

Outside diff comments:
In `@react_on_rails/lib/react_on_rails/doctor.rb`:
- Around line 144-150: The current check_react_on_rails_versions flow runs
checker.check_react_on_rails_packages and check_version_wildcards before
auto_fix_versions, causing stale errors in checker.messages after FIX=true
writes package.json; change the flow so that if fix is truthy you call
auto_fix_versions (which mutates package.json) before invoking
checker.check_react_on_rails_packages and check_version_wildcards, and clear or
re-run checker.messages (or reinstantiate the checker) after the auto-fix so the
subsequent checks reflect the updated file; apply the same reorder+clear logic
to the analogous block/method around the 585-602 region to prevent the same
stale-error issue.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b618e850-49ad-4a0d-9cc6-59ab5e2d7e9b

📥 Commits

Reviewing files that changed from the base of the PR and between eb06107 and 68f1ce8.

📒 Files selected for processing (9)
  • react_on_rails/lib/react_on_rails/configuration.rb
  • react_on_rails/lib/react_on_rails/doctor.rb
  • react_on_rails/lib/react_on_rails/error.rb
  • react_on_rails/lib/react_on_rails/packer_utils.rb
  • react_on_rails/lib/react_on_rails/system_checker.rb
  • react_on_rails/lib/react_on_rails/version_checker.rb
  • react_on_rails/lib/react_on_rails/version_synchronizer.rb
  • react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb
  • react_on_rails/spec/lib/react_on_rails/version_synchronizer_spec.rb

Comment thread react_on_rails/lib/react_on_rails/doctor.rb
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/version_synchronizer.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/version_synchronizer.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/error.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 5, 2026

Review Summary

The overall direction is solid — escalating wildcard constraints to errors, extending checks to Pro packages, and centralizing the "run doctor" guidance are all improvements. The FIX=true auto-sync and range-prefix stripping in VersionSynchronizer are well-implemented with appropriate atomic writes and edge-case handling.

Bugs

1. False positive success for unconstrained Gemfile entries (see inline on doctor.rb:534)

check_gem_wildcard_for reports ✅ Gemfile uses exact version when the gem line has no version argument at all (e.g., gem 'react_on_rails'). This is the riskiest case — any version is acceptable — and it silently passes the check.

2. Conflicting success + error for range specs in check_package_version_sync (see inline on system_checker.rb:226)

When npm_version is e.g. ^16.5.0, npm_to_rubygem strips the caret prefix via its digit-match regex, so the version comparison succeeds and reports ✅ versions match. Moments later, Doctor#check_npm_wildcard_for reports 🚫 non-exact version for the same package. Users get contradictory messages in a single doctor run. Fix: skip range specs in check_package_version_sync the same way workspace:/file:/link: are skipped.

Dead Code

3. check_version_patterns in system_checker.rb is unreachable (inline on line 739)

Its only call site (check_package_version_sync when versions match) was removed in this PR. Tests call it via send directly so they still pass, creating false coverage confidence.

4. check_gemfile_version_patterns (and check_gemfile_version_pattern_for) in system_checker.rb are unreachable (inline on line 756)

Removed from check_react_on_rails_packages in this PR without deleting the method. The logic was duplicated into Doctor#check_gem_wildcard_for. Two parallel implementations of the same check in different classes is fragile.

Minor

5. Silent intent change for > (strictly-greater-than) specs (inline on version_synchronizer.rb:155)

The range-prefix regex also matches bare > (not just >=). Stripping >16.5.0 to 16.5.0 rewrites the user's constraint to a version that may actually violate it.

6. DOCTOR_RECOMMENDATION placement in error.rb

Minor coupling concern — see inline comment.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Refactored SystemChecker methods are now unreachable dead code
    • Removed the now-unreachable wildcard/version-pattern methods from SystemChecker and deleted their direct private-method specs so only Doctor’s active wildcard checks remain.

Create PR

Or push these changes by commenting:

@cursor push e5fd6d7032
Preview (e5fd6d7032)
diff --git a/react_on_rails/lib/react_on_rails/system_checker.rb b/react_on_rails/lib/react_on_rails/system_checker.rb
--- a/react_on_rails/lib/react_on_rails/system_checker.rb
+++ b/react_on_rails/lib/react_on_rails/system_checker.rb
@@ -736,58 +736,6 @@
       MSG
     end
 
-    def check_version_patterns(npm_version, _gem_version)
-      # Check for version range patterns in package.json
-      return unless /^[\^~><*]/.match?(npm_version) || npm_version.include?(" ")
-
-      add_error(<<~MSG.strip)
-        🚫 NPM package uses a non-exact version: #{npm_version}
-
-        React on Rails requires exact version matching. Non-exact constraints will
-        cause a runtime error on app startup.
-
-        Fix: bundle exec rake react_on_rails:sync_versions WRITE=true
-      MSG
-    end
-
-    def check_gemfile_version_patterns
-      gemfile_path = ENV["BUNDLE_GEMFILE"] || "Gemfile"
-      return unless File.exist?(gemfile_path)
-
-      begin
-        gemfile_content = File.read(gemfile_path)
-        check_gemfile_version_pattern_for(gemfile_content, "react_on_rails")
-        if ReactOnRails::Utils.react_on_rails_pro?
-          check_gemfile_version_pattern_for(gemfile_content,
-                                            "react_on_rails_pro")
-        end
-      rescue StandardError
-        # Ignore errors reading Gemfile
-      end
-    end
-
-    def check_gemfile_version_pattern_for(gemfile_content, gem_name)
-      gem_line = gemfile_content.lines.find { |line| line.match(/^\s*gem\s+['"]#{gem_name}['"]/) }
-      return unless gem_line
-
-      return unless /['"][~^]/.match?(gem_line) || />=\s*/.match?(gem_line)
-
-      version = if gem_name == "react_on_rails_pro"
-                  ReactOnRails::Utils.react_on_rails_pro_version
-                else
-                  ReactOnRails::VERSION
-                end
-      add_error(<<~MSG.strip)
-        🚫 Gemfile uses a non-exact version constraint for #{gem_name}.
-
-        React on Rails requires exact version matching between the gem and npm package.
-        Non-exact constraints can cause versions to drift apart, leading to runtime errors.
-
-        Fix: Use an exact version in your Gemfile:
-          gem '#{gem_name}', '#{version}'
-      MSG
-    end
-
     def report_dependency_versions(package_json)
       all_deps = (package_json["dependencies"] || {}).merge(package_json["devDependencies"] || {})
 

diff --git a/react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb b/react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb
--- a/react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb
+++ b/react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb
@@ -220,72 +220,6 @@
     end
   end
 
-  describe "#check_version_patterns" do
-    it "errors on caret version patterns" do
-      checker.send(:check_version_patterns, "^16.0.0", "16.0.0")
-      expect(checker.errors?).to be true
-      expect(checker.messages.last[:content]).to include("non-exact version")
-    end
-
-    it "errors on tilde version patterns" do
-      checker.send(:check_version_patterns, "~16.0.0", "16.0.0")
-      expect(checker.errors?).to be true
-      expect(checker.messages.last[:content]).to include("non-exact version")
-    end
-
-    it "does not warn about exact versions" do
-      initial_message_count = checker.messages.count
-      checker.send(:check_version_patterns, "16.0.0", "16.0.0")
-      expect(checker.messages.count).to eq(initial_message_count)
-    end
-  end
-
-  describe "#check_gemfile_version_patterns" do
-    context "when Gemfile has version patterns" do
-      let(:gemfile_content) do
-        <<~GEMFILE
-          gem 'rails', '~> 7.0'
-          gem 'react_on_rails', '~> 16.0'
-          gem 'other_gem'
-        GEMFILE
-      end
-
-      before do
-        gemfile_path = ENV["BUNDLE_GEMFILE"] || "Gemfile"
-        allow(File).to receive(:exist?).with(gemfile_path).and_return(true)
-        allow(File).to receive(:read).with(gemfile_path).and_return(gemfile_content)
-        stub_const("ReactOnRails::VERSION", "16.0.0")
-      end
-
-      it "errors on non-exact version patterns" do
-        checker.send(:check_gemfile_version_patterns)
-        expect(checker.errors?).to be true
-        expect(checker.messages.last[:content]).to include("non-exact version constraint")
-      end
-    end
-
-    context "when Gemfile has exact versions" do
-      let(:gemfile_content) do
-        <<~GEMFILE
-          gem 'rails', '7.0.0'
-          gem 'react_on_rails', '16.0.0'
-        GEMFILE
-      end
-
-      before do
-        gemfile_path = ENV["BUNDLE_GEMFILE"] || "Gemfile"
-        allow(File).to receive(:exist?).with(gemfile_path).and_return(true)
-        allow(File).to receive(:read).with(gemfile_path).and_return(gemfile_content)
-      end
-
-      it "does not warn about exact versions" do
-        initial_message_count = checker.messages.count
-        checker.send(:check_gemfile_version_patterns)
-        expect(checker.messages.count).to eq(initial_message_count)
-      end
-    end
-  end
-
   describe "#check_react_on_rails_npm_package" do
     context "when package.json exists with react-on-rails" do
       let(:package_json_content) do

You can send follow-ups to the cloud agent here.

Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
react_on_rails/lib/react_on_rails/doctor.rb (1)

610-627: Consider surfacing unsupported/missing specs from auto-fix results.

The VersionSynchronizer.sync returns unsupported_specs and missing_source_specs in its Result struct, but these are not reported to the user. When auto-fix can't handle certain specs (e.g., upper-bound constraints like < or <=), the user may benefit from knowing why no changes were made.

💡 Optional enhancement to report skipped specs
   if result.changes.any?
     checker.add_success("  ✅ FIX=true: Synced package.json versions (#{result.changes.length} update(s))")
     result.changes.each do |change|
       checker.add_info("    #{change[:section]}.#{change[:package]}: #{change[:from]} -> #{change[:to]}")
     end
   else
     checker.add_info("  ℹ️  FIX=true: No package.json version changes needed")
   end
+
+  if result.unsupported_specs.any?
+    checker.add_info("  ℹ️  FIX=true: Skipped unsupported specs: #{result.unsupported_specs.join(', ')}")
+  end
+
+  if result.missing_source_specs.any?
+    checker.add_info("  ℹ️  FIX=true: Missing source versions: #{result.missing_source_specs.join(', ')}")
+  end
 rescue StandardError => e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/lib/react_on_rails/doctor.rb` around lines 610 - 627, The
auto_fix_versions method currently ignores result.unsupported_specs and
result.missing_source_specs from ReactOnRails::VersionSynchronizer.sync; update
auto_fix_versions to check result.unsupported_specs and
result.missing_source_specs after obtaining result and report them via
checker.add_warning or checker.add_info (e.g., "  ⚠️  FIX=true: Unsupported
specs skipped: ..." and "  ⚠️  FIX=true: Missing source specs: ...") so users
see which packages were skipped and why; locate this logic in the
auto_fix_versions method and use the existing checker object to surface these
lists when they are non-empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@react_on_rails/lib/react_on_rails/doctor.rb`:
- Around line 583-608: In check_npm_wildcard_for, skip specs that are local or
workspace links by returning success (or skipping validation) when npm_version
starts with "workspace:", "file:" or "link:" (same guard used in
system_checker.rb) before applying
ReactOnRails::VersionSynchronizer::EXACT_VERSION_REGEX; update the logic in
check_npm_wildcard_for to detect these prefixes and avoid flagging them as
errors when present.

In `@react_on_rails/lib/react_on_rails/system_checker.rb`:
- Around line 739-751: Remove the dead-version-pattern helper methods from
SystemChecker: delete check_version_patterns, check_gemfile_version_patterns,
and check_gemfile_version_pattern_for along with any private helper references
and their tests; ensure no other code calls these methods (search for those
exact method names) and leave Doctor#check_version_wildcards as the single
source of truth for wildcard/non-exact version checks to avoid duplicate errors.

---

Nitpick comments:
In `@react_on_rails/lib/react_on_rails/doctor.rb`:
- Around line 610-627: The auto_fix_versions method currently ignores
result.unsupported_specs and result.missing_source_specs from
ReactOnRails::VersionSynchronizer.sync; update auto_fix_versions to check
result.unsupported_specs and result.missing_source_specs after obtaining result
and report them via checker.add_warning or checker.add_info (e.g., "  ⚠️ 
FIX=true: Unsupported specs skipped: ..." and "  ⚠️  FIX=true: Missing source
specs: ...") so users see which packages were skipped and why; locate this logic
in the auto_fix_versions method and use the existing checker object to surface
these lists when they are non-empty.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cfc3dd28-58da-4d05-a288-5e50fdfc03c0

📥 Commits

Reviewing files that changed from the base of the PR and between 68f1ce8 and 33a2a60.

📒 Files selected for processing (4)
  • react_on_rails/lib/react_on_rails/doctor.rb
  • react_on_rails/lib/react_on_rails/system_checker.rb
  • react_on_rails/lib/react_on_rails/version_synchronizer.rb
  • react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb
✅ Files skipped from review due to trivial changes (1)
  • react_on_rails/lib/react_on_rails/version_synchronizer.rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • react_on_rails/spec/lib/react_on_rails/system_checker_spec.rb

Comment thread react_on_rails/lib/react_on_rails/doctor.rb
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb
@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed

All 15 review threads resolved across 4 reviewers (claude[bot], cursor[bot], greptile-apps[bot], coderabbitai[bot]).

Fixed (items 1-6)

# Issue Fix Commit
1 Pro version bug: check_npm_wildcard_for always used ReactOnRails::VERSION for pro package install command Branch on package_name == "react-on-rails-pro" to use react_on_rails_pro_version 33a2a60dc
2 Duplicate wildcard checks + FIX=true stale errors: Both SystemChecker and Doctor checked version patterns; auto_fix_versions ran after checks leaving stale errors Removed duplicate checks from SystemChecker flow; moved auto_fix_versions before all checks 33a2a60dc + 5f775850d
3 sync_versions skipped non-exact specs when version matched: ^16.5.0 with gem 16.5.0 was treated as "no change needed" Added non_exact flag to parse_supported_spec; detect_changes now always rewrites non-exact specs 33a2a60dc
4 strip_range_prefix silently normalised <= constraints: <=16.5.0 was pinned to 16.5.0, discarding upper-bound semantics Narrowed regex to only strip ^, ~, >=, > — excludes <= and < 33a2a60dc
5 Hard-error on workspace/local specs: workspace:*, file:, link: specs caused doctor errors despite being valid Added early return in check_package_version_sync for workspace/local protocols 33a2a60dc
6 Only checked 2 of 4 npm dep sections: peerDependencies and optionalDependencies were missed Now uses VersionSynchronizer::PACKAGE_SECTIONS for all 4 sections 33a2a60dc

Skipped with rationale (replied + resolved)

# Issue Rationale
7 Tighten exact version detection for "19"/"latest" Already addressed: check_npm_wildcard_for uses EXACT_VERSION_REGEX whitelist; check_gem_wildcard_for uses Gem::Requirement.exact?. Edge cases aren't realistic for react-on-rails packages.
8 Use Gem::Requirement.exact? in SystemChecker Doctor-level check already uses it. SystemChecker method is now dead code (superseded).
9 DOCTOR_RECOMMENDATION location in error.rb Minor discoverability nit; keeping co-located with Error class.
10 Unused _gem_version parameter Method is now dead code (no callers). Separate cleanup.

Tests

253 specs passing, 0 failures. RuboCop clean.


Posted by I (Claude Code) addressing review feedback on PR #3070.

Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 5, 2026

Review

The overall direction is solid — aligning doctor's strictness with the runtime VersionChecker behavior and surfacing actionable fix commands is the right call. A few issues need attention before merging:

Bugs

1. check_npm_wildcard_for will false-positive on workspace/file/link specs (inline comment on doctor.rb:588)
workspace:*, file:../foo, link:../bar don't match EXACT_VERSION_REGEX and fall through to the error branch. The same guard present in system_checker.rb:226 is missing here, so monorepos using workspace protocols will get spurious "non-exact version" errors.

2. No-version Gemfile entry is reported as success (inline comment on doctor.rb:535)
gem 'react_on_rails' with no version argument yields version_match = nil, which triggers the add_success path. An unconstrained gem is actually looser than a wildcard and should be flagged as an error.

Dead Code

3. Three unreachable methods remain in system_checker.rb (inline comment on system_checker.rb:739)
check_version_patterns, check_gemfile_version_patterns, and check_gemfile_version_pattern_for have no callers after this PR's refactor. They should be deleted — the comment at line 222 already documents that Doctor#check_version_wildcards is the single source of truth, but the orphaned methods contradict that intent and risk being re-wired later.

Improvement

4. auto_fix_versions silently drops unsupported/missing-source specs (inline comment on doctor.rb:618)
result.unsupported_specs and result.missing_source_specs are never surfaced to the user after FIX=true. A user may think all packages were fixed when some (e.g. workspace:* entries) were silently skipped.

Minor Observations

  • The rubocop:disable Metrics/CyclomaticComplexity on detect_changes is fine as a short-term measure, but the method now handles 3 distinct spec types (exact, range-prefixed, npm-alias) — worth a TODO comment or a follow-up ticket if you'd like to keep it clean.
  • DOCTOR_RECOMMENDATION being defined in error.rb is slightly surprising placement. constants.rb or a dedicated recommendations.rb might be a more natural home, but this is purely a style concern.

Comment thread react_on_rails/lib/react_on_rails/system_checker.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb
Comment thread react_on_rails/lib/react_on_rails/doctor.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/doctor.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 6, 2026

Code Review: PR #3070

Overall this is a solid, well-motivated PR. The alignment between doctor's static checks and the runtime VersionChecker crash behavior is a real pain-point fix, the FIX=true auto-sync flow is cleanly designed, and the test coverage is thorough. A few issues worth addressing before merge:


Bug — = prefix misclassified as non-exact in non_exact_range_spec?

Inline comment on system_checker.rb:251

In npm's semver spec =16.5.0 is a valid exact pin (equivalent to bare 16.5.0). The current regex /\A[\^~><*=]/ causes it to be silently skipped by check_package_version_sync, and then incorrectly flagged by check_npm_wildcard_for with the misleading message "non-exact version… will cause a runtime error". To compound it, strip_range_prefix in VersionSynchronizer has no = case, so sync_versions WRITE=true can't fix it either. Drop = from the character class (or add = support throughout the sync path).


Hardening — Unescaped gem name interpolated into regex

Inline comment on doctor.rb:532

gem_name is interpolated directly into /…#{gem_name}…/ on lines 532, 540, and 541 without Regexp.escape. Safe today (react_on_rails / react_on_rails_pro contain only word chars), but fragile. Worth a one-line fix.


UX nit — "FIX=true only updates package.json" shown on clean runs

Inline comment on doctor.rb:730

The info message fires unconditionally, so users who run FIX=true on an already-clean project see confusing "update Gemfile constraints manually" advice even when no Gemfile changes were relevant. Gate it on result.changes.any?.


Minor — Unbounded Gemfile traversal in build_gem_declaration_line

Inline comment on doctor.rb:562

Correct in all real-world cases (the nil-guard terminates the loop), but the loop will walk to the end of a Gemfile that has a trailing-comma line followed by many blank/comment lines. A small lookahead cap (e.g. 20 lines) would prevent unexpected slowness on malformed or very large Gemfiles.


Positive notes

  • Escalating warning → error in both check_gem_wildcards and check_npm_wildcards is the right call — the runtime already hard-crashes on non-exact versions, so the doctor was giving a false sense of safety.
  • auto_fix_versions running before the subsequent checks (so the fixed state is what gets validated) is the correct ordering and is well-commented.
  • expected_below_lower_bound? is a thoughtful guard — silently skipping auto-rewrite when the gem version would violate the declared >= lower bound avoids surprising downgrades.
  • The write_atomically temp-file pattern with pid/thread/hex suffix is solid; the ensure cleanup is correct.
  • Test coverage for the new paths (alias specs, multiline Gemfile declarations, keyword-style versions, lower-bound violations) is comprehensive.

- Remove = from non_exact_range_spec? regex: =16.5.0 is a valid exact
  pin in npm semver, not a range. Including it caused false "non-exact
  version" errors in doctor output.
- Add = to strip_range_prefix so VersionSynchronizer can auto-fix
  =X.Y.Z specs during sync.
- Guard the FIX=true info message behind result.changes.any? so it
  only appears when changes were actually made.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed in 223edd4

I (Claude Code) triaged 4 unresolved review comments from claude[bot].

Fixed (2):

  • system_checker.rb:251 — Removed = from non_exact_range_spec? regex. =16.5.0 is a valid exact pin in npm semver, not a range. Also added = to strip_range_prefix in VersionSynchronizer so auto-fix handles =X.Y.Z specs.
  • doctor.rb:730 — Guarded the FIX=true info message with result.changes.any? so it only appears when changes were actually made.

Skipped with rationale (2):

  • doctor.rb:532 — Unescaped gem_name in regex: current callers only pass react_on_rails and react_on_rails_pro (no regex metacharacters). Defensive improvement, not a current bug.
  • doctor.rb:562 — Unbounded traversal guard: nil guard handles termination safely; pathological Gemfiles are not a realistic scenario.

All 4 threads replied to and resolved.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because on-demand usage is turned off. To enable Bugbot Autofix, turn on on-demand usage and set a spend limit in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 223edd4. Configure here.


def non_exact_range_spec?(npm_version)
npm_version.match?(/\A[\^~><*]/) || npm_version.include?(" ")
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing = in non_exact_range_spec? character class

Medium Severity

The non_exact_range_spec? regex /\A[\^~><*]/ is missing the = character that the PR discussion explicitly says was added. Explicit-equals npm specs like =16.5.0 won't be caught, allowing them to flow into check_package_version_sync's version-comparison code instead of being silently delegated to Doctor. This contradicts the comment at lines 225–227 stating "Non-exact version checks are handled by Doctor#check_version_wildcards to avoid duplicate diagnostics," resulting in both SystemChecker and Doctor reporting on the same spec.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 223edd4. Configure here.

# frozen_string_literal: true

module ReactOnRails
DOCTOR_RECOMMENDATION = "For detailed diagnostics, run: bundle exec rake react_on_rails:doctor"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DOCTOR_RECOMMENDATION string constant is semantically unrelated to error classes, yet it now loads alongside ReactOnRails::Error whenever react_on_rails/error is required. This couples an operational message to a foundational error-class file and can create ordering confusion for any autoloader that expects error.rb to define only error classes.

Consider moving it to a dedicated constants file (e.g. lib/react_on_rails/constants.rb) or hoisting it into the top-level lib/react_on_rails.rb where other module-level constants live:

Suggested change
DOCTOR_RECOMMENDATION = "For detailed diagnostics, run: bundle exec rake react_on_rails:doctor"
# frozen_string_literal: true
module ReactOnRails
DOCTOR_RECOMMENDATION = "For detailed diagnostics, run: bundle exec rake react_on_rails:doctor"
class Error < StandardError
end
end

(No functional change needed here if the placement is intentional, but a comment explaining why it lives in error.rb would help future readers.)


def check_gem_wildcard_for(gemfile_content, gem_name)
lines = gemfile_content.lines
line_index = lines.index { |line| line.match(/^\s*gem\s+['"]#{gem_name}['"]/) }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gem_name is interpolated directly into a Regexp literal without escaping. The two current call-sites pass "react_on_rails" and "react_on_rails_pro" — both safe — but this is a latent robustness issue if the method is ever called with an arbitrary string.

Suggested change
line_index = lines.index { |line| line.match(/^\s*gem\s+['"]#{gem_name}['"]/) }
line_index = lines.index { |line| line.match(/^\s*gem\s+['"]#{Regexp.escape(gem_name)}['"]/) }

next unless deps.key?(package_name)

check_npm_wildcard_for(deps, package_name)
break # only report once per package (avoid duplicates if listed in multiple sections)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The break correctly avoids double-reporting a package that appears in multiple sections, but it silently picks whichever section happens to be enumerated first (PACKAGE_SECTIONS order: dependenciesdevDependencies → …). If a package appears in both dependencies and devDependencies with different versions, the second entry is completely ignored.

This is probably acceptable for the common case, but a one-line comment would clarify the intent and prevent a future reader from thinking the break is a bug:

Suggested change
break # only report once per package (avoid duplicates if listed in multiple sections)
break # report once per package; first-found section wins (avoids duplicate diagnostics)

Comment on lines +730 to +732
if result.changes.any?
checker.add_info(" ℹ️ FIX=true only updates package.json; update Gemfile constraints manually if needed.")
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Gemfile-constraint guidance is only shown when result.changes.any?, so it is never displayed when FIX=true but npm is already synced while the Gemfile still has wildcard constraints. In that scenario auto_fix_versions runs, finds nothing to write, and the user silently misses the hint that they still need to fix Gemfile by hand.

The note should also appear when there are unsupported/skipped specs (which includes Gemfile wildcards that couldn't be auto-fixed):

Suggested change
if result.changes.any?
checker.add_info(" ℹ️ FIX=true only updates package.json; update Gemfile constraints manually if needed.")
end
if result.changes.any? || result.unsupported_specs.any? || result.missing_source_specs.any?
checker.add_info(" ℹ️ FIX=true only updates package.json; update Gemfile constraints manually if needed.")
end

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 6, 2026

Review: Enforce strict version matching in doctor and recommend doctor on errors

Overall this is a well-structured PR that closes a real UX gap — the old behaviour where doctor only warned while the runtime hard-crashed was confusing. The test coverage is solid and the refactors are clean. A few things worth addressing before merging:


Breaking change needs an UPGRADING note

The escalation of minor version mismatches from warnings to errors (in SystemChecker#report_version_mismatch) and non-exact Gemfile constraints from warnings to errors (in Doctor#check_gem_wildcard_for) will cause bundle exec rake react_on_rails:doctor to exit non-zero for any project that previously passed doctor with only warnings about imprecise pinning. CI pipelines that run doctor as a gate check will break on upgrade.

The CHANGELOG has a line about it, but this deserves an entry in UPGRADING.md (or equivalent) explicitly calling out:

  • doctor now exits 1 on non-exact version constraints (previously only a warning)
  • recommended migration: pin both Gemfile and package.json to exact versions before upgrading this gem

auto_fix_versions swallows synchronizer diagnostic output

StringIO.new is passed as io: to suppress the synchronizer's own print output, which is intentional (doctor re-reports via checker). However, if synchronizer.sync raises a ReactOnRails::Error (e.g. unreadable package.json), that exception propagates through the rescue StandardError at the bottom of auto_fix_versions — correctly caught. Looks fine, just worth a test confirming the warning message surfaces rather than silently swallowing.


strip_range_prefix is npm-only — worth a comment

The Gemfile path uses Gem::Requirement.new(...).exact? which handles all Ruby operators correctly, so this is not a bug. But strip_range_prefix in version_synchronizer.rb handles ^, ~, >=, and = as npm operators. A brief comment clarifying it is npm-only would prevent future confusion with Ruby's ~> (pessimistic constraint).


Inline comments posted on specific lines

  • error.rb L4DOCTOR_RECOMMENDATION semantically misplaced in the error-class file
  • doctor.rb L532gem_name interpolated into Regexp without Regexp.escape
  • doctor.rb L730-732 — Gemfile constraint guidance missing when npm is already synced but Gemfile still has wildcards
  • doctor.rb L625break comment clarification for first-section-wins behaviour

@justin808 justin808 merged commit f03084c into main Apr 7, 2026
61 checks passed
@justin808 justin808 deleted the jg/doctor-strict-versions branch April 7, 2026 00:21
justin808 added a commit that referenced this pull request Apr 8, 2026
…e-dedup

* origin/main: (51 commits)
  Fix Content-Length mismatch and null renderingRequest errors in node renderer (#3069)
  Improve memory debugging docs with simpler heap snapshot approach (#3072)
  Enforce strict version matching in doctor and recommend doctor on errors (#3070)
  Remove immediate_hydration feature from codebase (#2834)
  Fix infinite fork loop when node renderer worker fails to bind port (#2881)
  Fix TanStack Router SSR hydration mismatch in Pro async path (#2932)
  Improve node renderer error messages for malformed render requests (#3068)
  Add interactive mode prompt to create-react-on-rails-app (#3063)
  docs: replace hardcoded version numbers with unversioned install commands (#2893)
  Remove Contributing section from docs sidebar (#3064)
  Consolidate docs comparison pages into single evaluation entry (#3065)
  Docs route cleanup: canonicalize worst verbose URL slugs (#3067)
  Add agent summary blocks to high-value docs pages (#3066)
  Fix brittle positional assertions in create-app tests (#2923)
  Auto-resolve renderer password from ENV in Rails Pro (#2921)
  Standardize bundle env vars from =yes to =true (#2925)
  Fix Pro generator multiline and template-literal rewrites (#2918)
  Fix spec/dummy Procfile.dev SERVER_BUNDLE_ONLY to match template convention (#2922)
  Add llms docs entry points (#2916)
  Bump version to 16.6.0.rc.0
  ...

# Conflicts:
#	packages/create-react-on-rails-app/src/create-app.ts
justin808 added a commit that referenced this pull request Apr 8, 2026
…lacement-2835-main

* origin/main: (44 commits)
  Fix Content-Length mismatch and null renderingRequest errors in node renderer (#3069)
  Improve memory debugging docs with simpler heap snapshot approach (#3072)
  Enforce strict version matching in doctor and recommend doctor on errors (#3070)
  Remove immediate_hydration feature from codebase (#2834)
  Fix infinite fork loop when node renderer worker fails to bind port (#2881)
  Fix TanStack Router SSR hydration mismatch in Pro async path (#2932)
  Improve node renderer error messages for malformed render requests (#3068)
  Add interactive mode prompt to create-react-on-rails-app (#3063)
  docs: replace hardcoded version numbers with unversioned install commands (#2893)
  Remove Contributing section from docs sidebar (#3064)
  Consolidate docs comparison pages into single evaluation entry (#3065)
  Docs route cleanup: canonicalize worst verbose URL slugs (#3067)
  Add agent summary blocks to high-value docs pages (#3066)
  Fix brittle positional assertions in create-app tests (#2923)
  Auto-resolve renderer password from ENV in Rails Pro (#2921)
  Standardize bundle env vars from =yes to =true (#2925)
  Fix Pro generator multiline and template-literal rewrites (#2918)
  Fix spec/dummy Procfile.dev SERVER_BUNDLE_ONLY to match template convention (#2922)
  Add llms docs entry points (#2916)
  Bump version to 16.6.0.rc.0
  ...

# Conflicts:
#	CHANGELOG.md
@justin808 justin808 mentioned this pull request Apr 8, 2026
2 tasks
justin808 added a commit that referenced this pull request Apr 8, 2026
### Summary

Adds missing changelog entries to the `[Unreleased]` section for PRs
merged since `v16.6.0.rc.0`. Analyzed 19 commits on `origin/main` since
the last tag, identified 1 missing user-visible PR (#3069), and skipped
10 non-user-visible PRs (docs, tests, internal refactors).

**New entries added:**
- **Added**: `[Pro] Configurable HTTP keep-alive timeout for node
renderer connections` (PR #3069)
- **Fixed**: `[Pro] Fixed SSR failures from stale persistent HTTP/2
connections` (PR #3069)

**Entries already present** (added in prior changelog updates): PRs
#2834, #2881, #2918, #2921, #2923, #2932, #3063, #3068, #3070.

**Skipped** (not user-visible): #2893 (docs), #2916 (docs), #2922 (test
fix), #2923 (test fix), #2925 (internal refactor), #3064 (docs), #3065
(docs), #3066 (docs), #3067 (docs), #3072 (docs).

### Pull Request checklist

- [x] ~Add/update test to cover these changes~
- [x] ~Update documentation~
- [x] Update CHANGELOG file

### Other Information

No code changes — CHANGELOG.md only.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk because this PR only changes documentation (`CHANGELOG.md`)
and does not modify runtime code.
> 
> **Overview**
> Updates `CHANGELOG.md` *[Unreleased]* to include missing Pro release
notes for PR `#3069`, documenting the new
`renderer_http_keep_alive_timeout` config and the associated fix for SSR
failures from stale persistent HTTP/2 connections to the node renderer.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8d1a480. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Interactive mode selection prompt for CLI tool when no explicit mode
is specified
* Configurable keep-alive timeout setting for Pro users (default 30
seconds)

* **Bug Fixes**
  * Enhanced validation and error handling for invalid request payloads
  * Improved template literal handling in code generation
  * Better HTTP connection stability with enhanced diagnostic messaging

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit that referenced this pull request Apr 12, 2026
…ors (#3070)

## Summary

- **Escalate doctor wildcard checks from warnings to errors** — matching
runtime VersionChecker behavior that hard-crashes on non-exact versions
(^, ~, >=). Previously, doctor only warned about these patterns while
the app would crash at boot.
- **Extend wildcard checks to cover Pro packages** —
`check_npm_wildcards` and `check_gem_wildcards` now check both
`react-on-rails`/`react_on_rails` and
`react-on-rails-pro`/`react_on_rails_pro`.
- **Add doctor recommendation to all VersionChecker error messages** —
every runtime crash from version_checker.rb now tells users to run
`bundle exec rake react_on_rails:doctor`.
- **Add doctor recommendation to configuration and packer_utils errors**
— config validation errors, autobundling errors, and compile conflicts
all now suggest running doctor.
- **Doctor suggests `sync_versions` on version mismatches** — error
messages now include `bundle exec rake react_on_rails:sync_versions
WRITE=true` as a fix.
- **`FIX=true` doctor auto-runs `sync_versions`** — when doctor detects
version issues and FIX mode is enabled, it automatically syncs
package.json versions to match gem versions.
- **`sync_versions` now handles range specs instead of skipping them** —
previously `^16.5.0`, `~16.5.0`, `>=16.5.0` were reported as
"unsupported" and skipped. Now they're parsed, the range prefix is
stripped, and the version is rewritten to the exact expected version.

Addresses review feedback from
#2893 (review)

## Test plan

- [x] `version_checker_spec.rb` — 74 examples, 0 failures
- [x] `version_synchronizer_spec.rb` — 20 examples, 0 failures (updated
test for new range-handling behavior)
- [x] `system_checker_spec.rb` — 81 examples, 0 failures (updated tests
for error vs warning escalation)
- [x] `doctor_spec.rb` — 152 examples, 0 failures
- [x] RuboCop — 0 offenses on all changed files

��� Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Tightens version validation from warnings to errors and adds auto-fix
behavior, which may cause previously passing CI/boot flows to fail until
versions are pinned exactly. Changes are mostly in diagnostic tooling
but affect startup/runtime error paths and developer workflows.
> 
> **Overview**
> Makes version hygiene **strict and actionable**:
`react_on_rails:doctor` now treats non-exact gem/npm specs (`^`, `~`,
`>=`, etc.) as errors (including Pro gems/packages) and can auto-run
`sync_versions` when `FIX=true` to rewrite range specs to exact expected
versions.
> 
> Improves remediation messaging across the stack by adding a shared
`ReactOnRails::DOCTOR_RECOMMENDATION` to configuration/autobundling
validations and `VersionChecker` runtime crashes, and by updating
mismatch errors to recommend `bundle exec rake
react_on_rails:sync_versions WRITE=true`.
> 
> `sync_versions` is enhanced to parse and rewrite supported semver
range prefixes (and npm alias variants) while refusing rewrites that
would violate a declared `>=` lower bound; tests and a React
18/19-compatible `act` helper in the TanStack Router Pro test are
updated accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
223edd4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Optional automatic version synchronization that can update package
files and report changes.

* **Bug Fixes**
* Non-exact version constraints and minor-version mismatches now produce
errors (with clearer remediation steps).
* Improved handling of workspace/local package specs and stricter
version-matching diagnostics.

* **Chores**
* Diagnostic messages now include guidance to run the doctor task for
remediation.

* **Tests**
* Updated tests and test helpers to reflect the new validation and sync
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit that referenced this pull request Apr 12, 2026
### Summary

Adds missing changelog entries to the `[Unreleased]` section for PRs
merged since `v16.6.0.rc.0`. Analyzed 19 commits on `origin/main` since
the last tag, identified 1 missing user-visible PR (#3069), and skipped
10 non-user-visible PRs (docs, tests, internal refactors).

**New entries added:**
- **Added**: `[Pro] Configurable HTTP keep-alive timeout for node
renderer connections` (PR #3069)
- **Fixed**: `[Pro] Fixed SSR failures from stale persistent HTTP/2
connections` (PR #3069)

**Entries already present** (added in prior changelog updates): PRs
#2834, #2881, #2918, #2921, #2923, #2932, #3063, #3068, #3070.

**Skipped** (not user-visible): #2893 (docs), #2916 (docs), #2922 (test
fix), #2923 (test fix), #2925 (internal refactor), #3064 (docs), #3065
(docs), #3066 (docs), #3067 (docs), #3072 (docs).

### Pull Request checklist

- [x] ~Add/update test to cover these changes~
- [x] ~Update documentation~
- [x] Update CHANGELOG file

### Other Information

No code changes — CHANGELOG.md only.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk because this PR only changes documentation (`CHANGELOG.md`)
and does not modify runtime code.
> 
> **Overview**
> Updates `CHANGELOG.md` *[Unreleased]* to include missing Pro release
notes for PR `#3069`, documenting the new
`renderer_http_keep_alive_timeout` config and the associated fix for SSR
failures from stale persistent HTTP/2 connections to the node renderer.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8d1a480. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Interactive mode selection prompt for CLI tool when no explicit mode
is specified
* Configurable keep-alive timeout setting for Pro users (default 30
seconds)

* **Bug Fixes**
  * Enhanced validation and error handling for invalid request payloads
  * Improved template literal handling in code generation
  * Better HTTP connection stability with enhanced diagnostic messaging

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit that referenced this pull request Apr 12, 2026
…ors (#3070)

## Summary

- **Escalate doctor wildcard checks from warnings to errors** — matching
runtime VersionChecker behavior that hard-crashes on non-exact versions
(^, ~, >=). Previously, doctor only warned about these patterns while
the app would crash at boot.
- **Extend wildcard checks to cover Pro packages** —
`check_npm_wildcards` and `check_gem_wildcards` now check both
`react-on-rails`/`react_on_rails` and
`react-on-rails-pro`/`react_on_rails_pro`.
- **Add doctor recommendation to all VersionChecker error messages** —
every runtime crash from version_checker.rb now tells users to run
`bundle exec rake react_on_rails:doctor`.
- **Add doctor recommendation to configuration and packer_utils errors**
— config validation errors, autobundling errors, and compile conflicts
all now suggest running doctor.
- **Doctor suggests `sync_versions` on version mismatches** — error
messages now include `bundle exec rake react_on_rails:sync_versions
WRITE=true` as a fix.
- **`FIX=true` doctor auto-runs `sync_versions`** — when doctor detects
version issues and FIX mode is enabled, it automatically syncs
package.json versions to match gem versions.
- **`sync_versions` now handles range specs instead of skipping them** —
previously `^16.5.0`, `~16.5.0`, `>=16.5.0` were reported as
"unsupported" and skipped. Now they're parsed, the range prefix is
stripped, and the version is rewritten to the exact expected version.

Addresses review feedback from
#2893 (review)

## Test plan

- [x] `version_checker_spec.rb` — 74 examples, 0 failures
- [x] `version_synchronizer_spec.rb` — 20 examples, 0 failures (updated
test for new range-handling behavior)
- [x] `system_checker_spec.rb` — 81 examples, 0 failures (updated tests
for error vs warning escalation)
- [x] `doctor_spec.rb` — 152 examples, 0 failures
- [x] RuboCop — 0 offenses on all changed files

��� Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Tightens version validation from warnings to errors and adds auto-fix
behavior, which may cause previously passing CI/boot flows to fail until
versions are pinned exactly. Changes are mostly in diagnostic tooling
but affect startup/runtime error paths and developer workflows.
> 
> **Overview**
> Makes version hygiene **strict and actionable**:
`react_on_rails:doctor` now treats non-exact gem/npm specs (`^`, `~`,
`>=`, etc.) as errors (including Pro gems/packages) and can auto-run
`sync_versions` when `FIX=true` to rewrite range specs to exact expected
versions.
> 
> Improves remediation messaging across the stack by adding a shared
`ReactOnRails::DOCTOR_RECOMMENDATION` to configuration/autobundling
validations and `VersionChecker` runtime crashes, and by updating
mismatch errors to recommend `bundle exec rake
react_on_rails:sync_versions WRITE=true`.
> 
> `sync_versions` is enhanced to parse and rewrite supported semver
range prefixes (and npm alias variants) while refusing rewrites that
would violate a declared `>=` lower bound; tests and a React
18/19-compatible `act` helper in the TanStack Router Pro test are
updated accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
223edd4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Optional automatic version synchronization that can update package
files and report changes.

* **Bug Fixes**
* Non-exact version constraints and minor-version mismatches now produce
errors (with clearer remediation steps).
* Improved handling of workspace/local package specs and stricter
version-matching diagnostics.

* **Chores**
* Diagnostic messages now include guidance to run the doctor task for
remediation.

* **Tests**
* Updated tests and test helpers to reflect the new validation and sync
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit that referenced this pull request Apr 12, 2026
### Summary

Adds missing changelog entries to the `[Unreleased]` section for PRs
merged since `v16.6.0.rc.0`. Analyzed 19 commits on `origin/main` since
the last tag, identified 1 missing user-visible PR (#3069), and skipped
10 non-user-visible PRs (docs, tests, internal refactors).

**New entries added:**
- **Added**: `[Pro] Configurable HTTP keep-alive timeout for node
renderer connections` (PR #3069)
- **Fixed**: `[Pro] Fixed SSR failures from stale persistent HTTP/2
connections` (PR #3069)

**Entries already present** (added in prior changelog updates): PRs
#2834, #2881, #2918, #2921, #2923, #2932, #3063, #3068, #3070.

**Skipped** (not user-visible): #2893 (docs), #2916 (docs), #2922 (test
fix), #2923 (test fix), #2925 (internal refactor), #3064 (docs), #3065
(docs), #3066 (docs), #3067 (docs), #3072 (docs).

### Pull Request checklist

- [x] ~Add/update test to cover these changes~
- [x] ~Update documentation~
- [x] Update CHANGELOG file

### Other Information

No code changes — CHANGELOG.md only.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk because this PR only changes documentation (`CHANGELOG.md`)
and does not modify runtime code.
> 
> **Overview**
> Updates `CHANGELOG.md` *[Unreleased]* to include missing Pro release
notes for PR `#3069`, documenting the new
`renderer_http_keep_alive_timeout` config and the associated fix for SSR
failures from stale persistent HTTP/2 connections to the node renderer.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8d1a480. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Interactive mode selection prompt for CLI tool when no explicit mode
is specified
* Configurable keep-alive timeout setting for Pro users (default 30
seconds)

* **Bug Fixes**
  * Enhanced validation and error handling for invalid request payloads
  * Improved template literal handling in code generation
  * Better HTTP connection stability with enhanced diagnostic messaging

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant