Project

tree_haver

0.0
The project is in a healthy, maintained state
Backend registry, parser request/result contracts, and tree-sitter language-pack integration for Structured Merge.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0 ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 structuredmerge Logo by Aboling0, CC BY-SA 4.0

StructuredMerge Ruby

StructuredMerge Ruby provides Ruby gems for building merge-aware tools that need portable structured-merge contracts, fixture-backed behavior, and Ruby-native integration points.

The monorepo includes the core AST/review contracts, parser substrate support, format-specific merge gems, binary/ZIP planning helpers, provider adapters, and a Ruby packaging recipe gem.

Project links:

Package Family

StructuredMerge Ruby is a layered gem family. The lower layers provide parser, range, AST, merge, and template contracts; format gems apply those contracts to specific languages and data formats; provider gems bind a format family to a parser or serializer; workflow gems package the behavior for Git drivers, release automation, and monorepo maintenance.

Package README files keep this section short and link here. This root guide is the implementation inventory for Ruby users who need to choose gems, understand backend coverage, or wire a focused backend into a test suite.

The family is intentionally layered:

Core and Workflow Gems

Gem Layer What it provides
tree_haver Parser substrate Parser backend registry, byte ranges, node wrappers, source locations, binary tree contracts, and backend selection helpers.
ast-merge Merge substrate AST merge contracts, diagnostics, structural edit plans, review/replay vocabulary, nested merge orchestration, backend provider registration, and shared spec helpers.
ast-template Template substrate Template/session transport objects used by recipe tooling and language-specific templating layers.
ast-merge-git Git integration Merge-driver, diff-driver, conflict inspection, language registry, and command plumbing for smorg-rb.
smorg-rb Command package Ruby implementation command packaging and executable entry points.
kettle-jem Recipe tooling Template recipes, monorepo root materialization, gem maintenance helpers, and StructuredMerge Ruby release support.

Transformation Gems

Gem Layer What it provides
ast-crispr Generic AST edits Structured document surgery recipes for generated blocks and template-owned regions.
ast-crispr-ruby-prism Ruby AST edits Prism-backed Ruby source edits, including require insertion and template-managed Ruby regions.
ast-crispr-markdown-markly Markdown AST edits Markly-backed Markdown block replacement and README recipe support.

Format Gems

Gem Family What it provides
plain-merge Text Plain-text fallback contracts and conflict-preserving merge behavior.
json-merge JSON and JSONC Object/array-aware JSON merge behavior using the shared StructuredMerge merge substrate and tree-sitter JSON grammar coverage where the selected backend supplies it.
yaml-merge YAML YAML-family merge contracts, shared provider tags, and provider-neutral behavior.
toml-merge TOML TOML-family merge contracts and provider-neutral behavior.
dotenv-merge dotenv Environment-file merge behavior for key/value configuration files.
markdown-merge Markdown Markdown-family merge contracts, heading/table/list matching, link-reference handling, fenced-code flow, and provider-neutral behavior.
ruby-merge Ruby source Ruby source merge contracts and parser-backed source-language behavior.
rbs-merge RBS Ruby signature merge behavior, declaration matching, and template-owned signature updates using RBS and tree-sitter RBS grammar coverage where available.
bash-merge Bash source Shell source merge contracts and parser-backed shell-language behavior using tree-sitter Bash where available.
go-merge Go source Go source merge contracts for the cross-language StructuredMerge family.
rust-merge Rust source Rust source merge contracts for the cross-language StructuredMerge family.
typescript-merge TypeScript source TypeScript source merge contracts for the cross-language StructuredMerge family.
binary-merge Binary Binary tree planning contracts, byte-range ownership, diagnostics, and Kaitai Struct oriented structured binary support.
zip-merge Archives ZIP archive planning helpers, archive member ownership, and archive-aware merge contracts.

Provider Gems

Provider gems register themselves with the backend tag system used by ast-merge and tree_haver. That registry lets a spec suite run against a single selected backend, lets a format gem ask for a capability instead of a hard dependency, and keeps parser-specific behavior out of provider-neutral merge gems.

Gem Provides Runtime notes
psych-merge YAML provider Uses Ruby's Psych parser and emitter.
citrus-toml-merge TOML provider Uses a Citrus grammar and pure-Ruby parser path, commonly paired with toml-rb style TOML data handling.
parslet-toml-merge TOML provider Uses Parslet and pure-Ruby parser path, commonly paired with toml style TOML data handling.
commonmarker-merge Markdown provider Uses CommonMarker for CommonMark-oriented Markdown parsing.
kramdown-merge Markdown provider Uses Kramdown for Ruby-native Markdown parsing.
markly-merge Markdown provider Uses Markly for cmark-gfm-backed Markdown parsing and README templating support.
prism-merge Ruby provider Uses Prism for Ruby source parsing and Ruby-specific merge refiners.

Ruby Backend Notes

Ruby has the broadest backend surface in the StructuredMerge implementation set. tree_haver owns the parser backend registry and byte-range contracts; ast-merge owns provider registration and merge orchestration. The backend tags are capability names, not package preferences.

Backend or provider path Used by Notes
:TSLP source-family gems Uses tree-sitter-language-pack parser aggregation where available. This is the preferred tree-sitter provider path for broad language coverage.
:MRI source-family gems Uses ruby_tree_sitter; retained as the MRI-native tree-sitter backend name.
:rust source-family gems Uses tree_stump where that native Rust-backed parser path is selected.
:ffi source-family gems Uses FFI bindings to libtree-sitter; suitable where the runtime and native library support the needed ABI.
:java source-family gems Uses JVM tree-sitter bindings through java-tree-sitter / jtreesitter for JRuby-oriented parser runs.
Prism ruby-merge, prism-merge, ast-crispr-ruby-prism Ruby-native parser path for Ruby source and structured Ruby source edits.
Psych yaml-merge, psych-merge Ruby standard YAML parser/emitter path.
RBS rbs-merge Ruby signature parser path.
CommonMarker, Markly, Kramdown markdown-merge providers Markdown parser families with different CommonMark/GFM/Ruby-native tradeoffs.
Citrus, Parslet toml-merge providers Pure-Ruby TOML parser families used as provider-specific backend paths.
Kaitai Struct binary-merge Schema-oriented binary parsing support for structured binary work.

Backend Platform Compatibility

tree_haver supports multiple Ruby parser backends, but not every backend works on every Ruby runtime:

TreeHaver backend MRI JRuby TruffleRuby Notes
:TSLP (tree-sitter-language-pack) Aggregated tree-sitter provider used by StructuredMerge language-family gems where available.
:MRI (ruby_tree_sitter) C extension, MRI only.
:rust (tree_stump) Rust extension through Ruby native-extension tooling, MRI only.
:ffi (FFI + libtree-sitter) TruffleRuby FFI does not support the tree-sitter struct-by-value ABI.
:java (java-tree-sitter / jtreesitter) JRuby-oriented path that requires matching grammar JARs.
Prism Ruby parser, standard library in Ruby 3.4+.
Psych YAML parser/emitter, standard library.
Citrus Pure Ruby PEG parser.
Parslet Pure Ruby PEG parser.
CommonMarker Native Markdown parser used through commonmarker-merge.
Markly Native cmark-gfm parser used through markly-merge.
Kramdown Pure Ruby Markdown parser.

Legend: ✅ = works, ❌ = does not work, ❓ = not part of the supported runtime claim.

Install

Install the gems your tool needs:

bundle add ast-merge json-merge

Command

The Ruby implementation ships the implementation-specific smorg-rb command. Use that name in git configuration unless a package manager or local install has provided a smorg symlink.

Package-manager formulas may expose the selected implementation as smorg. For a local user-created symlink:

ln -s "$(command -v smorg-rb)" ~/.local/bin/smorg
git config merge.smorg-rb.driver 'smorg-rb merge-driver %O %A %B %P'
git config diff.smorg-rb.command 'smorg-rb diff-driver'
smorg-rb conflicts diff path/to/file-with-conflicts.go
smorg-rb languages --gitattributes

merge-driver updates Git's %A file by default, or writes to --output when used outside git. diff-driver accepts both the two-argument local form and the seven- or nine-argument forms Git passes to external diff commands. conflicts diff reports conflict-marker regions in a file that already contains Git conflict markers.

Semantic merge-driver coverage is fixture-backed for JSON. Other language and format paths are git-compatible command surfaces without semantic driver coverage.

Gems

Core:

  • tree_haver - parser substrate, byte ranges, backend adapters, and binary tree contracts.
  • ast-merge - AST merge contracts, diagnostics, planning, review, replay, and nested-merge vocabulary.
  • ast-template - template/session transport contracts.

Format libraries:

Provider and recipe gems:

Portability

The Ruby gems are developed against the shared StructuredMerge fixtures. Those fixtures define the cross-language behavior expected from the Go, TypeScript, Rust, and Ruby implementations. Conformance checks live in gem specs and in the shared spec/fixture tooling rather than in a static status document.

Development

Common checks:

  • mise run check
  • bundle exec rake
  • package-specific bundle exec rspec commands

Bundler path gems are the default isolation mechanism inside this monorepo. When this repository needs to consume sibling workspace projects outside the monorepo itself, prefer nomono-driven Bundler wiring rather than manual Ruby load-path changes.