Skip to content

feat(ruby): M4 — validation hardening, strict unions, RBS sigs, thread soak - #2851

Draft
filip-michalsky wants to merge 1 commit into
filipmichalsky/ruby-sdk-m3from
filipmichalsky/ruby-sdk-beta
Draft

feat(ruby): M4 — validation hardening, strict unions, RBS sigs, thread soak#2851
filip-michalsky wants to merge 1 commit into
filipmichalsky/ruby-sdk-m3from
filipmichalsky/ruby-sdk-beta

Conversation

@filip-michalsky

@filip-michalsky filip-michalsky commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Part of the AP-2857 parity stack:

Stack: #2820 (spike) ← #2854 (M1–M2) ← #2855 (M3) ← this PR (M4)

Validation hardening

  • Closed protocol unions decode strictly (WireError when no variant matches); the generator marks unions that had scalar/null variants as open, so nullable/scalar cases keep passing through; structural mismatches (object/array where the other was expected) raise, JSON null passes everywhere
  • validation.rb (port of Python _validation.py): screenshot cross-field rules (fullPage+clip, quality only for jpeg), OTLP trace endpoint must end with /v1/traces, cache config (true/false/{threshold:}), create-config scalar constraints
  • Stagehand.create gains telemetry: and cache: for signature parity with Python; per-call cache options validated too

RBS signatures

  • sig/stagehand.rbs types the public API surface; validated by rake rbs (part of the default rake task) and shipped in the gem. Generated wire models stay untyped deliberately (their shape is owned by the protocol JSON).

Thread soak

  • New suite: concurrent senders × out-of-order responses × inbound llm.generate (handlers making nested RPC calls) × notifications, plus close-under-fire
  • SOAK=n scales the load; verified at SOAK=100 (~22k requests in 0.4 s, zero lost responses/replies/notifications, linear scaling)

Verification

  • 120 unit tests / 803 assertions + RBS validation, generator drift check clean, gem builds (with sig/)
  • Strict-union change re-verified live on local Chrome (context_and_response.rb for nullable navigation unions, custom_llm.rb for the now-strict LLM unions)

Remaining in the roadmap (future PRs on this stack)

  • M5: webmcp.rb canonical example (needs a WebMCP-enabled target page)
  • M6: ast-grep Ruby parity lanes, docs tabs, changesets/RubyGems lane, CI jobs, Windows launcher

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Aug 29, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bed74ec

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@filip-michalsky filip-michalsky changed the title feat(ruby): core page/locator interactions — milestone 1 toward v4 parity feat(ruby): full outbound method surface (76/77) — milestones 1–2 toward v4 parity Aug 29, 2026
@filip-michalsky filip-michalsky changed the title feat(ruby): full outbound method surface (76/77) — milestones 1–2 toward v4 parity feat(ruby): full protocol method surface (77/77) — milestones 1–3 toward v4 parity Aug 29, 2026
…k (M4)

- wire: closed protocol unions decode strictly (WireError when no variant
  matches); the generator now marks unions that had scalar/null variants as
  open so nullable/scalar cases keep passing through; structural mismatches
  (object/array where the other was expected) raise, JSON null passes
- validation.rb: port of Python _validation.py — screenshot cross-field
  rules (fullPage+clip, quality only for jpeg), OTLP trace endpoint must end
  with /v1/traces, cache config (true/false/{threshold:}), create-config
  scalar constraints (non-empty strings, booleans, positive integers,
  string maps)
- client: create() gains telemetry: and cache: (parity with Python's
  create signature); per-call cache options validated too
- sig/stagehand.rbs: public API signatures, validated by `rake rbs`
  (in the default rake task); shipped in the gem
- test/test_thread_soak.rb: concurrent senders vs out-of-order responses vs
  inbound llm.generate (with nested RPC calls from the handler) vs
  notifications, plus close-under-fire; SOAK=n scales the load (verified at
  SOAK=100: ~22k requests in 0.4s, no losses)
- 120 runs / 803 assertions; live-checked context_and_response.rb and
  custom_llm.rb on local Chrome after the strict-union change

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@filip-michalsky filip-michalsky changed the title feat(ruby): full protocol method surface (77/77) — milestones 1–3 toward v4 parity feat(ruby): full method surface + hardening (77/77) — milestones 1–4 toward v4 parity Aug 29, 2026
@filip-michalsky filip-michalsky changed the title feat(ruby): full method surface + hardening (77/77) — milestones 1–4 toward v4 parity feat(ruby): M4 — validation hardening, strict unions, RBS sigs, thread soak Aug 29, 2026
@filip-michalsky
filip-michalsky changed the base branch from filipmichalsky/ap-2857-spike-effort-scoping-for-ruby-in-stagehand-v4 to filipmichalsky/ruby-sdk-m3 August 29, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant