Skip to content

Claim slice 4a: Ruby include/extend/prepend as captures on the shared base-relations path #400

Closed

Description

@mpapis

I'd like to claim slice 4a from Adding a language: common stays common, following the maintainer's offer on #339 — the extraction PR (#396) has since landed.

Problem

Ruby's include/extend/prepend reach the base-relations path through a Ruby-only function, captureRubyMixinBases (src/ingest_relations.h), called from a lang == Lang::Ruby arm of the tags pass. The shared path (captureBases + isBaseTypeNodeIn) already handles the base clause of every other language — and Ruby's own < superclass — from the class node's clause children. The mixin directives are the one Ruby shape that bypasses it.

CONTRIBUTING.md row 4 lists this as: "4a Ruby include/extend/prepend as captures read by the shared path, retiring captureRubyMixinBases: S–M, Ruby."

Scope

  • Capture the mixin directive in queries/ruby/tags.scm under a shared, language-neutral capture name, structurally: the tags pass does not evaluate predicates (#eq?/#match? are silently ignored — pinned by test/matchgrammarcheck.sh; generalising the evaluator is slice 5a, not claimed here). So the pattern carries the shape, and C++ owns only the guards the query cannot express — the same division the shared import vocabulary uses for require (Shared import-capture vocabulary instead of ~21 per-language import extractors #358).
  • Route that capture through the shared base-relations path, so each mixin constant becomes an inherit ref exactly as today, and delete captureRubyMixinBases and its call site rather than leaving them beside the shared path.
  • No new Lang:: branch in shared code; no language-named capture kind.
  • Preserve — or pin as known gaps — the floors the current code states: a begin- or modifier-if-guarded directive, the do-block bodies of included/class_methods/Struct.new/Class.new/Module.new, and class << Registry (another object's singleton).

Acceptance

  • Red-first: a new arm that is red on main before the change; test/rubyinheritcheck.sh and test/chacheck.sh green.
  • Byte-identical output on every language the shared path already handles — the map, --deps --limit=100000, --skipped, and --callers/--callees/--impact/--uses on symbols the slice touches — over the fixtures of every language touched plus at least one real repository per language. Empty diff, or each difference named as intended.
  • ripwire src --clones no longer lists the group the slice folded; ripwire . --quality-delta=origin/main..HEAD gates 0.
  • test/qschemetripcheck.sh green, with kParserVer and its mirror bumped above main's (maintainers set the final number at merge).
  • A known-gap arm for anything the slice does not fix.

Relationship to other slices

Not 4b (base-clause node kinds moved into tags.scm) and not 4c (structural conformance). It does not depend on slice 5a: the design assumes predicates do not run.

Activity

  1. mpapis commented on Oct 15, 2026

    @mpapis
    ContributorAuthor

    Claimed and now implemented: the slice is up as #401 (refactor(ingest): read Ruby's mixin directives on the shared base-relations path). It carries the byte-identity battery, the family gates, the kParserVer 171 -> 173 bump with the re-pinned qschemetrip.hash, and one new rubyinheritcheck arm pinning the capture's text and position guards. The PR body states Closes #400, so this closes when it merges.

    Authored by @mpapis with AI assistance (DeepSeek V4.1 Flash / Qwen 3.8 Flash) under his supervision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions