Skip to content

Latest commit

 

History

History
261 lines (192 loc) · 9.05 KB

File metadata and controls

261 lines (192 loc) · 9.05 KB

AGENTS.md - commonmarker-merge Development Guide

🎯 Project Overview

commonmarker-merge is a format-specific implementation of the *-merge gem family for Markdown files using the Commonmarker parser. It provides intelligent Markdown file merging using AST analysis.

Core Philosophy: Intelligent Markdown merging that preserves structure, formatting, and links while applying updates from templates.

Repository: https://github.com/kettle-rb/commonmarker-merge Current Version: 1.0.1 Required Ruby: >= 3.2.0 (currently developed against Ruby 4.0.1)

⚠️ AI Agent Terminal Limitations

Terminal Output Is Available, but Each Command Is Isolated

CRITICAL: AI agents can reliably read terminal output when commands run in the background and the output is polled afterward. However, each terminal command should be treated as a fresh shell with no shared state.

Use this pattern:

  1. Run commands with background execution enabled.
  2. Fetch the output afterward.
  3. Make every command self-contained — do not rely on a previous cd, export, alias, or shell function.

Use mise for Project Environment

CRITICAL: The canonical project environment now lives in mise.toml, with local overrides in .env.local loaded via dotenvy.

⚠️ Watch for trust prompts: After editing mise.toml or .env.local, mise may require trust to be refreshed before commands can load the project environment. That interactive trust screen can masquerade as missing terminal output, so commands may appear hung or silent until you handle it.

Recovery rule: If a mise exec command in this repo goes silent, appears hung, or terminal polling stops returning useful output, assume mise trust is needed first and recover with:

mise trust -C /home/pboling/src/kettle-rb/commonmarker-merge
mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bundle exec rspec

Do this before spending time on unrelated debugging; in this workspace, silent mise commands are usually a trust problem.

mise trust -C /home/pboling/src/kettle-rb/commonmarker-merge

CORRECT:

mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bundle exec rspec

CORRECT:

eval "$(mise env -C /home/pboling/src/kettle-rb/commonmarker-merge -s bash)" && bundle exec rspec

WRONG:

cd /home/pboling/src/kettle-rb/commonmarker-merge
bundle exec rspec

WRONG:

cd /home/pboling/src/kettle-rb/commonmarker-merge && bundle exec rspec

Prefer Internal Tools Over Terminal

Use read_file, list_dir, grep_search, file_search instead of terminal commands for gathering information. Only use terminal for running tests, installing dependencies, and git operations.

Workspace layout

This repo is a sibling project inside the /home/pboling/src/kettle-rb workspace, not a vendored dependency under another repo.

NEVER Pipe Test Commands Through head/tail

Run the plain command and inspect the full output afterward. Do not truncate test output.

🏗️ Architecture: Format-Specific Implementation

What commonmarker-merge Provides

  • Commonmarker::Merge::SmartMerger – Markdown-specific SmartMerger implementation
  • Commonmarker::Merge::FileAnalysis – Markdown file analysis with section extraction
  • Commonmarker::Merge::NodeWrapper – Wrapper for Commonmarker AST nodes
  • Commonmarker::Merge::PartialTemplateMerger – Section-level partial merges
  • Commonmarker::Merge::MergeResult – Markdown-specific merge result
  • Commonmarker::Merge::ConflictResolver – Markdown conflict resolution
  • Commonmarker::Merge::FreezeNode – Markdown freeze block support
  • Commonmarker::Merge::DebugLogger – Commonmarker-specific debug logging

Key Dependencies

Gem Role
ast-merge (~> 4.0) Base classes and shared infrastructure
tree_haver (~> 5.0) Unified parser adapter (wraps Commonmarker)
commonmarker CommonMark Markdown parser (MRI only)
version_gem (~> 1.1) Version management

Parser Backend

commonmarker-merge uses the Commonmarker parser exclusively via TreeHaver's :commonmarker backend:

Backend Parser Platform Notes
:commonmarker Commonmarker MRI only CommonMark parser, native extension

📁 Project Structure

lib/commonmarker/merge/
├── smart_merger.rb              # Main SmartMerger implementation
├── partial_template_merger.rb   # Section-level merging
├── file_analysis.rb             # Markdown file analysis
├── node_wrapper.rb              # AST node wrapper
├── merge_result.rb              # Merge result object
├── conflict_resolver.rb         # Conflict resolution
├── freeze_node.rb               # Freeze block support
├── debug_logger.rb              # Debug logging
└── version.rb

spec/commonmarker/merge/
├── smart_merger_spec.rb
├── partial_template_merger_spec.rb
├── file_analysis_spec.rb
└── integration/

🔧 Development Workflows

Running Tests

# Full suite
mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bundle exec rspec

# Single file (disable coverage threshold check)
mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- env K_SOUP_COV_MIN_HARD=false bundle exec rspec spec/commonmarker/merge/smart_merger_spec.rb

# Commonmarker backend tests
mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bundle exec rspec --tag commonmarker

Coverage Reports

mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bin/rake coverage
mise exec -C /home/pboling/src/kettle-rb/commonmarker-merge -- bin/kettle-soup-cover -d

📝 Project Conventions

API Conventions

SmartMerger API

  • merge – Returns a String (the merged Markdown content)
  • merge_result – Returns a MergeResult object
  • to_s on MergeResult returns the merged content as a string

PartialTemplateMerger API

  • merge – Merges a template section into a specific location in destination
  • Used by ast-merge-recipe for section-level updates

Markdown-Specific Features

Heading-Based Sections:

# Section 1
Content for section 1

## Subsection 1.1
Nested content

# Section 2
Content for section 2

Freeze Blocks:

<!-- commonmarker-merge:freeze -->
Custom content that should not be overridden
<!-- commonmarker-merge:unfreeze -->

Standard content that merges normally

Link Reference Preservation:

[link text][ref]

[ref]: https://example.com

🧪 Testing Patterns

TreeHaver Dependency Tags

Available tags:

  • :commonmarker – Requires Commonmarker backend
  • :markdown_parsing – Requires Markdown parser

CORRECT:

RSpec.describe Commonmarker::Merge::SmartMerger, :commonmarker do
  # Skipped if Commonmarker not available
end

WRONG:

before do
  skip "Requires Commonmarker" unless defined?(CommonMarker)  # DO NOT DO THIS
end

💡 Key Insights

  1. Heading-based structure: Sections matched by heading text
  2. .text strips formatting: When matching by text, backticks and other formatting are removed
  3. Link references preserved: Reference-style links maintained during merge
  4. PartialTemplateMerger: Supports injecting template sections into specific locations
  5. Freeze blocks use HTML comments: <!-- commonmarker-merge:freeze -->
  6. MRI only: Commonmarker requires native extensions, MRI only

🚫 Common Pitfalls

  1. Commonmarker requires MRI: Does not work on JRuby or TruffleRuby
  2. NEVER use manual skip checks – Use dependency tags (:commonmarker)
  3. Text matching strips formatting – Match on plain text, not markdown syntax
  4. Do NOT load vendor gems – They are not part of this project; they do not exist in CI
  5. Use tmp/ for temporary files – Never use /tmp or other system directories
  6. Do NOT expect cd to persist – Every terminal command is isolated; use a self-contained mise exec -C ... -- ... invocation.
  7. Do NOT rely on prior shell state – Previous cd, export, aliases, and functions are not available to the next command.

🔧 Markdown-Specific Notes

Node Types

document         # Root node
heading          # # Heading
paragraph        # Regular text
code_block       # ```code```
list             # - item or 1. item
link             # [text](url)
image            # ![alt](src)

Text Matching Behavior

Source:     ### The `*-merge` Gem Family
.text:      "The *-merge Gem Family\n"

# Backticks, bold, italic stripped in .text

Merge Behavior

  • Headings: Matched by heading text (stripped of formatting)
  • Sections: Content from heading to next same-level heading
  • Paragraphs: Position-based within sections
  • Code blocks: Matched by language and content
  • Lists: Can be merged or replaced
  • Links: Reference-style links preserved
  • Freeze blocks: Protect customizations from template updates