Skip to content
This repository was archived by the owner on Mar 12, 2023. It is now read-only.

bump pry to 0.14 - #120

Open
fig wants to merge 42 commits into
0x2c7:masterfrom
fig:master
Open

fig wants to merge 42 commits into
0x2c7:masterfrom
fig:master

Conversation

@fig

@fig fig commented Jan 3, 2023

Copy link
Copy Markdown

Bump pry to 0.14 for Ruby 3.2 compatibility.

fig and others added 30 commits January 3, 2023 18:45
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Update test to find first existing gem path instead of using Gem.path.first
which may not exist in Ruby 3.4.6 fresh installations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Check both rubylibdir and sitelibdir for stdlib classification since
  Ruby 3.4.6 moves some components like RubyGems to site_ruby
- Change evaluation detection from exact string match to regex pattern
  to handle Ruby 3.4.6's new eval signature format

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Allow Reline as default Readline implementation in Ruby 3.4+
- Accept forwardable.rb delegation as valid (not monkey-patched)
- Add RUBYOPT=-W0 to integration tests to suppress bundler warnings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…rary classification

The previous test subject (URI::HTTP) has been gemified.
Ruby 4.0 removed two libraries that byebug loads unconditionally when
ruby_jard requires 'byebug/core':

- readline: Ruby 3.4 shipped a stdlib readline.rb shim that aliased
  Readline to Reline. Ruby 4.0 dropped it, so byebug/history.rb fails
  with "Sorry, you can't use byebug without Readline". The readline
  gem (0.0.4) provides the same shim, and Jard's PryProxy and
  ReplInterceptor also rely on ::Readline.
- irb: now a bundled gem instead of a default gem, so
  byebug/commands/irb.rb raises LoadError under Bundler unless irb is
  declared in the bundle.

Declaring both as runtime dependencies lets ruby_jard load under
Ruby 4.0. Byebug 12's C extension already compiles on 4.0, so no
debugger swap is needed. On Ruby 4.0.7 the integration suite now has
the same failures as unmodified master on Ruby 3.4.7, and none that
are specific to 4.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruby 4.0 ships io-wait 0.4, which removes IO#ready?. The PTY output
bridge thread called @output_reader.ready? while draining output as
the REPL exits. On 4.0 that raises NoMethodError. The thread's
catch-all `rescue StandardError; retry` swallowed the error, so the
state never reached `exited`, and ReplInterceptor#stop spun forever
waiting for it.

The user-visible symptom: every control command (next, step,
continue, up, down, ...) was accepted at the prompt and then hung, so
the debugger never resumed the program.

IO#wait_readable(0) is the non-blocking equivalent. It returns the IO
when data is waiting and nil otherwise, and it is in core IO on every
supported Ruby (3.2 through 4.0), so no io/wait require is needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since Ruby 3.4, Thread::Backtrace::Location#label includes the owner
of the method ("JardMergeSort::Sorter#sort", "Array#each"), while
base_label is still the bare method name. The backtrace screen
treated any label/base_label difference as a block, rescue or ensure
frame and appended the label's first word. Every normal method frame
therefore rendered as

  JardMergeSort::Sorter in sort (JardMergeSort::Sorter#sort)

which repeats the class name and pushes the location onto a second
line.

Block, rescue and ensure labels always contain a space ("block in
Klass#foo", "block (2 levels) in foo"), and qualified method names
never do. Only take the suffix path when the label has a space. The
display is then identical on Ruby 3.2 through 4.0: "sort" for methods
and "sort (block)" for blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruby 3.3 changed the path of code run through Kernel#eval from
"(eval)" to "(eval at /absolute/caller.rb:LINE)". The backtrace and
source screens printed that verbatim, for example

  Object in test1 at (eval at /home/me/app/evaluation_example.rb:11):2

The long absolute path overflowed the backtrace row, and the two line
numbers are ambiguous: the trailing :2 is relative to the evaluated
string, not the caller.

PathDecorator now renders every evaluation path as "(eval)" plus the
eval-relative line number. This matches the display on older Rubies
and the existing integration fixtures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two VM changes broke how the backtrace screen shows frames that have
no Ruby source of their own:

- Since Ruby 3.3, core methods such as Integer#times are written in
  Ruby and report an "<internal:numeric>" path. The Application filter
  hid them as internal code, and they lost their [c] marker, so
  navigating up/down could land on a frame with no source to show.
- On Ruby 4.0 (via byebug's debug-inspector locations), C frames such
  as Range#each report path=nil and lineno=0 instead of the caller's
  location, so they rendered as "[c] Range in each at ???".

Frame now treats both kinds as native frames. c_frame? is true for
them, and frame_file, frame_line and the new display_location resolve
to the nearest non-native caller. Ruby 3.4+'s own caller_locations
does the same, and older Rubies reported it that way too. The class
and method label still come from the frame itself, so the screen
shows "[c] Integer in times at example.rb:11" again. Path filtering
and up/down skipping behave as on Ruby 3.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Random::Formatter#random_bytes is defined in random/formatter.rb on
every supported Ruby (3.2 through 4.0), so Jard correctly classifies
the frame as <stdlib:random>. The fixture still expected
<stdlib:securerandom> from Rubies where the method lived in
securerandom.rb, so this spec failed on every version in the CI
matrix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Some integration screens embed text formatted by Ruby itself. Ruby 3.4
changed backtrace labels from `sleep' to 'Kernel#sleep', and CI still
covers 3.2 and 3.3, so no single fixture can pass on every version.

JardIntegrationTest now looks for sibling fixtures named
"name.ruby-X.Y.expected" and uses the highest one not newer than the
running Ruby, falling back to "name.expected". Add a 3.4+ variant of
the interruption evaluation fixture using the new backtrace format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruby 3.4 changed Hash#inspect to print symbol keys as `key: value`
instead of `:key=>value`, so the hashes the pager spec renders no
longer match the recorded screens. Add a versioned fixture with the
new format. Only the hash syntax differs from pager.expected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec simulates a gem replacing Readline with Reline and expects
Jard to fall back to direct input with a "Key bindings are disabled"
warning. Since Ruby 3.4, Readline is Reline out of the box, and
ReplInterceptor#interceptable? deliberately accepts it there (see
"Fix Ruby 3.4.6 Reline interceptor compatibility"). Key bindings keep
working and no warning is printed.

Add a 3.4+ fixture without the warning lines. Ruby 3.2 and 3.3 still
use the original fixture and still expect the fallback warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With Ruby 3.4+, `jard output` and other paged output opened less at
24 rows regardless of the real terminal height. The rest of the
debugger screen stayed visible above the pager.

less writes to a stream whose window size it cannot always query, and
then falls back to 24 rows unless LINES/COLUMNS are set. On older
Rubies Jard's ::Readline was the GNU readline C extension, which
exports LINES and COLUMNS as a side effect. Since Ruby 3.4 ::Readline
is Reline, which does not, so less lost the size.

LessPager already knows the console size, so pass it to less
explicitly through the popen environment. The variables are skipped
when the size is unknown (non-TTY output).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summarise the user-visible fixes on this branch under an Unreleased
heading. The version number is left for the release to decide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The four "inside irb" placement specs launched `bundle exec irb`, which
loads the developer's ~/.irbrc (or $IRBRC / ~/.config/irb/irbrc). Any
custom prompt or startup output then broke the first screen assertion.
Run irb with -f so no rc file is read.

The fixtures also expected the old default prompt `irb(main):001:0>`.
irb 1.9 dropped the trailing indent level (`irb(main):001>`), and the
gemspec now requires irb ~> 1.15, so every supported Ruby gets the new
prompt. Update the fixtures instead of adding versioned variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paged output (long results, `jard output`) opened less with pry's
output as its stdout/stderr. When key bindings are enabled, that is
the ReplInterceptor's internal PTY, not the user's terminal. Recent
less releases (e.g. 704) read keystrokes from the terminal they write
to, so less listened on the PTY: G, /search and q were echoed as text
after its ":" prompt and never acted on. less also sized itself from
the PTY, which has no window size, and fell back to 24 rows.

The pager comment already said less must work on the real tty, the
same one as Console#output, and the redirected-stdout path already
did that. Use Console#output in every case.

This also supersedes "Pass terminal size to less when paging": that
LINES/COLUMNS workaround only hid the 24-row symptom of the same
root cause. It is removed here and is no longer needed. Pager,
show_output and standard_streams specs pass on Ruby 3.4.7 and 4.0.7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test bundle includes activerecord, whose activesupport dependency
requires securerandom >= 0.3. Bundler therefore activates the
securerandom gem (0.4.1) on every Ruby instead of the default gem that
ships with Ruby. The fixture was recorded against the old stdlib file,
so the two screens after `jard filter include securerandom` could
never match. Stepping now lands in SecureRandom.gen_random_urandom in
<securerandom 0.4.x>, not Random::Formatter#random_bytes in
<stdlib:securerandom>.

Re-record those two screens from the gem's flow. They are masked like
the originals: pane contents, the source line number and the gem
version are wildcards. The scenario still exercises its intent,
stepping into an explicitly included library and then excluding it.

Pin securerandom ~> 0.4.0 in the test group so a future release
cannot silently change the code path the fixture depends on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spec/gemfiles/Gemfile-byebug-{9.1.0,10.0.2,11.1.0} were meant for a
CI matrix over byebug versions. Nothing references them anymore, and
they pin byebug 9-11, which conflicts with the gemspec's
`byebug ~> 12.0`, so Bundler could not even resolve them.

The root Gemfile resolves on every Ruby in the CI matrix (3.2 to 4.0),
so no per-Ruby Gemfiles are needed. If a future dependency drops an
older Ruby, reintroduce a gemfiles/ directory and set BUNDLE_GEMFILE
in the matrix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
actions/checkout@v2 targets Node 12, which GitHub Actions has
retired. Runners force it onto a newer Node and emit deprecation
warnings on every job. v4 is the current major version, and every
input this workflow uses (repository, path, ref) is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record the planning done while reviving the fork so it survives beyond
one conversation:

- roadmap/fork-release-strategy.md: using the fork from git now, the
  RubyGems naming decision (ask for ownership of ruby_jard vs publish
  under a new name), a pre-publish checklist, and proposed support and
  dependency policies.
- roadmap/debug-gem-port.md: moving the backend from byebug to Ruby's
  debug gem. Covers how much code carries over, the debug extension
  points it would use (with source references), risks, lessons from
  the earlier failed attempt, and a phased plan with exit criteria and
  rough effort estimates.

Exclude roadmap/ from spec.files so these planning docs are not
shipped in the packaged gem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Ruby 3.3 in CI, Jard disabled its key bindings and printed "One of
Jard's dependencies (PTY or Readline) is not available or patched by
another gem". 95 integration specs failed on that job.

Ruby 3.3 moved readline-ext to a bundled gem. Bundler does not load it
unless it is in the Gemfile, so the readline shim falls back to Reline
and ::Readline == Reline. ReplInterceptor#interceptable? only accepted
Reline when RUBY_VERSION >= 3.4 and treated it as "patched" on older
Rubies. What matters is what ::Readline is, not the Ruby version.

Use one check everywhere. Accept ::Readline when input=/output= are
GNU Readline C methods (no source location) or Reline's forwardable
delegators, and reject anything else as patched by another gem.

The readline_patched example simulated a patch with `Readline = Reline`,
which is now a legitimate setup. Make it patch Readline.input= the way
a monkey-patching gem would, so the fallback path stays covered on all
Rubies with the original fixture. The Ruby 3.4+ fixture variant is no
longer needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fig and others added 12 commits September 24, 2026 23:26
irb 1.18 prints a startup banner (logo, version, tip) when launched
through its exe/irb, which is how CI's bundle runs it. The four "inside
irb" placement specs expect the prompt on the first line, so they
failed in every CI job. Locally the banner never showed because an older
irb was locked, or because rbenv's binstub starts irb via a different
path.

Pass --nobanner. irb added that flag in the same release as the banner
(1.18), so require irb >= 1.18 in the Gemfile's test group to make the
spec environment deterministic. The gemspec's runtime requirement
(irb ~> 1.15) is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spec_helper retries examples tagged `integration: true` up to three
times, because tmux screen captures are timing-sensitive under load.
The scenario_1/2/3 and skip specs drive tmux like every other
integration spec but were never tagged. They were the ones that failed
intermittently in parallel runs (a final "jard >>" prompt not yet drawn
when the screen was captured), and they pass consistently when run
alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
YAML reads an unquoted `4.0` in the matrix as the number 4, so the job
was named "test-ubuntu (4)" and setup-ruby received "4". That resolved
to the latest 4.x only by luck. Quote every version so each job tests
exactly the Ruby it names.

ruby-head (Ruby 4.1 development) fails at `bundle install` because
byebug 12's C extension does not compile against it. Nothing in this
repo can fix that. Keep the job as an early warning but mark it
continue-on-error, so it no longer turns the whole run red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI's rubocop job failed with 382 offenses, mostly from cops added in
the recent RuboCop/rubocop-rspec upgrades, plus deprecation warnings.

- Load rubocop-rspec with `plugins:` instead of the deprecated
  `require:`.
- Set NewCops: disable and SuggestExtensions: false. This keeps the
  project's existing rule set and silences the "cops not configured"
  and extension-suggestion notices. Enabling new cops would add ~210
  offenses across ~40 cops, which is a separate style decision.
- Exclude the programs the integration specs debug (spec/examples and
  the scenario_1 helpers), not just *_example.rb. Their source lines
  are captured in screen fixtures, so reformatting them would shift the
  recorded screens. Calls such as `jard` there are the point, not a
  Lint/Debugger problem.
- RSpec/NoExpectationExample: exclude spec/integration. Those examples
  assert through JardIntegrationTest#assert_screen.
- Naming/VariableNumber: stop checking symbols. The numbered symbols
  are test-data keys.
- RSpec/IndexedLet: disable. Numbered lets are a deliberate convention
  for specs comparing interchangeable fixtures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Style/OptionalBooleanParameter flagged two positional booleans:
ReplProcessor#process_commands(redraw) and the integration helper's
JardIntegrationTest#screen_content(allow_duplication). Bare `true` or
`false` at a call site says nothing about what it controls. Make both
keyword arguments and update every caller
(`process_commands(redraw: false)`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mostly RuboCop autocorrections, each checked for equivalence:

- String concatenation to interpolation, where every operand is a
  String (slices or String-returning helpers).
- `[n..-1]` to `[n..]`, identical for String and Array, including
  negative starts.
- Drop `.freeze` on regexp literals, which are frozen since Ruby 3.0.
- Hash#each with an ignored key to #each_value in ScreenAdjuster, where
  the receiver comes from group_by.
- Flatten a nested conditional and redundant parentheses; the logic is
  unchanged.
- Session#lock forwards its block to Mutex#synchronize.
- Specs: `eq(true/false/nil)` to `be(...)`/`be_nil`, and
  `integration: true` to `:integration` metadata.
- Remove disable directives RuboCop reports as redundant.

Inline exceptions, each with a reason:

- Console#initialize keeps STDIN/STDOUT. It needs the real process
  streams, not $stdin/$stdout, which the debugged program may have
  reassigned.
- LayoutPicker keeps Layouts#each: RubyJard::Layouts is not a Hash and
  has no #each_value, so that autocorrection would raise NoMethodError.
- ThreadInfo spec keeps `eq(thread_info)` on itself, because it tests
  that #== is reflexive.

RuboCop now reports no offenses. The full suite passes on Ruby 3.2.3
and 4.0.7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gemfile.lock is not committed, and the Gemfile allowed any RuboCop
>= 1.81.7, so CI and local runs resolved different linters. CI
installed RuboCop 1.91.0 / rubocop-rspec 3.10.2 while a local lockfile
held 1.81.7 / 3.7.0. The two disagreed about Lint/InterpolationCheck:
the older version reported a needed disable directive as redundant,
and removing it made the newer version fail CI.

Pin both to a minor series (~> 1.91.0, ~> 3.10.0), which admits only
bug-fix releases. Every environment then lints with the same cops.
Bump deliberately when adopting a newer RuboCop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec types `puts "Input #{i}"` into the debugger REPL, so the
single-quoted string must keep #{i} literal. Autocorrecting it to double
quotes would interpolate `i` in the spec process and send different
keystrokes. RuboCop 1.81 wrongly reported the disable directive as
redundant, and it was removed in "Fix remaining RuboCop offenses".
Put it back with a comment explaining why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Job-level continue-on-error only changes the workflow run's overall
result. Each failed job is still reported as a failed check on the
commit, so the ruby-head jobs put a red ✗ on every commit and PR even
though the Rspec run itself succeeded. GitHub Actions has no
"allowed failure" state for checks.

Move the Ubuntu and macOS test jobs, unchanged apart from the matrix,
into a reusable workflow (test-suite.yml) that takes the Ruby versions
as a JSON input. Call it from:

- rspec.yml on push/PR, with the supported Rubies 3.2 to 4.0. Commit
  and PR checks now reflect only what the gem supports.
- ruby-head.yml weekly (Mondays 06:00 UTC) and on manual dispatch,
  with ["head"]. It remains an early warning: a failed scheduled run
  notifies the repo owner and shows on the Actions tab. It currently
  fails because byebug 12 does not build on Ruby 4.1 development.

Sharing one job definition keeps the head and supported runs from
drifting apart. PR check names gain a prefix
("test / test-ubuntu (3.2)"). There is no branch protection yet, so no
required-check settings need updating.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Linting isn't part of the spec run, but it lived in the Rspec workflow,
so a style offense showed up as a failing "Rspec" run. Give it a
dedicated RuboCop workflow with the same triggers (pushes to master and
pull requests) and unchanged steps. It still lints on Ruby 3.2, the
oldest supported version, which matches TargetRubyVersion in
.rubocop.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The gh-release job deployed the Docusaurus site under website/ to
GitHub Pages on every push to master, authenticating with an SSH key
from the GH_PAGES_DEPLOY secret. That secret belonged to the upstream
repository and does not exist in this fork, so every push to master
failed with "Permission denied (publickey)".

The fork does not publish the site, so remove the job. The remaining
`checks` job, a test build of the site, only ever ran on pull requests,
so drop the push trigger as well. Otherwise every push to master would
start a workflow run with nothing to do. Whether to keep website/ at all
is an open question in roadmap/fork-release-strategy.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant