Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning,
and yes, platform and engine support are part of the public API.
Please file a bug if you notice a violation of semantic versioning.
Unreleased
Added
- Added shared
Ast::Merge::Commentregion, attachment, and augmenter adoption over Psych comment tracking, including normalized analysis and wrapper attachment APIs plus shared-example compliance coverage - Added
add_template_only_sequence_itemsoption toSmartMergerfor preserving template-only list items during merge
Changed
- Adopted the shared
Ast::Merge::Layoutcontract for YAML document gaps, including shared layout compliance coverage over top-level mapping/sequence ownership - Rebased
Psych::Merge::PartialTemplateMergeronto the sharedAst::Merge::KeyPathPartialTemplateMergerBase, leaving YAML-specific child traversal, serialization, andSmartMergerwiring local while moving key-path navigation and missing-path insertion into the shared substrate - Rebased
Psych::Merge::CommentTrackeronto the shared
Ast::Merge::Comment::HashTrackerBase, keeping YAML-specific#extraction
heuristics and owner resolution local -
BREAKING:
ConflictResolver#merge_nodes_to_emittersignature simplified to
merge_nodes_to_emitter(template_nodes, dest_nodes, template_by_sig, depth: 0).
Removedprocessed_template_sigs,processed_dest_sigs, anddest_by_sig
parameters. Signature matching now uses cursor-based positional matching
(consumed indices + per-signature cursor) internally, ensuring multiple nodes
with the same signature are matched 1:1 in order rather than collapsed.
Thenested_dest_by_sigbuild inemit_recursive_mapping_mergewas also
removed as dead code. - Preserved normalized comment regions and attachments through YAML emission and merge paths while keeping document boundaries, recursive comment-heavy fixtures, and destination-leading / inline ownership stable under template preference
- Clarified the YAML removal-mode baseline so
remove_template_missing_nodes: truepreserves or promotes comment regions for removed destination-only mappings instead of silently dropping them - Adopted
Ast::Merge::TrailingGroups::DestIterateplus shared deferred-flush ordering for mappings and sequence items so template-only YAML additions keep their template-relative position even when destination keys or list items are reordered -
Psych::Merge::Emitternow reuses the sharedEmitterBasecomment-region and
attachment emission flow again, keeping only YAML-local deduplication and
tracked-column inline alignment behavior in the Psych layer - Upgraded
tree_haverdependency to~> 6.0
Deprecated
Removed
Fixed
- Fixed
.kettle-jem.ymlheader comment duplication: file-header comments (starting at line 1, separated from the first key by a blank line) are now treated as preamble via upstream ast-merge change, preventing duplication when template-only keys are inserted before the first key -
ConflictResolver#merge_nodes_to_emitternow preserves inter-node blank lines
from the destination, so visual spacing between YAML sections (e.g., between
name:andon:in GitHub Actions workflows) is maintained after merge - Fix recursive sequence item matching for mapping entries identified by
globally unique scalar keys such asvalueandorcid, preferring stable
identities over mutable fields likeemailso citation-style YAML sequences
merge 1:1 instead of duplicating author entries - Fix template-preference document boundary emission so top-level YAML prelude /
postlude comment regions and matched mapping-entry preludes are emitted from
the template side instead of being dropped or replaced by destination-only
boundaries in.kettle-jem.yml-style files - Fix top-level removal-mode separator-gap handling so promoted comments from a
removed destination-only mapping preserve the intended blank line before the
following destination comment block, while recursive sequence-item removal
continues to collapse item-spacing as required by the existing reproducible
fixture contract - Fix destination-preference document postlude emission so template-only
trailing footer comment blocks (such as the instructional footer in
.kettle-jem.yml-style files) are preserved when
add_template_only_nodes: true - Fix flow sequence duplication in recursive merge. YAML entries with flow sequence
values (e.g.,github: [pboling]) were duplicated becausecan_merge_recursively?
returnedtruefor sequences, causingemit_recursive_mergeto emit the key line,
thenemit_sequence_itemto re-emit the same physical line. Flow sequences (where
the value occupies the same line as the key) are now treated atomically. - Fix leading comment association when blank lines separate comments from the
first mapping entry.CommentTracker#leading_comments_beforenow skips blank lines
when searching upward for comments.emit_nodenow emits the blank line separator
between comments and the node when one existed in the original source.
Reported via kettle-jem self-test against.github/FUNDING.yml. - Fix recursive sequence emission so a template or destination item no longer
swallows the next sibling’s leading comment block from its physical line
range, preventing duplicated workflow-style section comments when inserting
template-only items. - Fix observation-based recursive sequence matching for composite items such as
nested sequences, allowing stable inner scalars to match outer siblings 1:1
so comment ownership and removal-mode promotion stay attached to the correct
item. - Fix document-level comment-only destination headers so, when the preferred
document has no nodes, the header is emitted once as a prelude instead of
being duplicated again as a trailing postlude after template-only additions. - Fix wrapped mapping / sequence value line ranges so a node no longer claims a
following sibling’s leading comment block in.kettle-jem.yml-style files,
preventing duplicated commented sections whenpatterns:is followed by a
commentedfiles:section. - Fix recursive YAML sequence emission so matched workflow-style items keep
parent-owned blank separators stable when destination-only nested mappings
(such as a preservedwith:block) survive the merge, preventing repeated
template runs from growing that blank-line region on each pass. - Fix supplemental document postlude deduplication so orphan regions already
owned by the preferred source are excluded regardless of their position
relative tolast_content_line.emit_supplemental_document_postludenow
buildsall_preferred_regionsby unioningpreferred_regionswith all
orphan regions from the preferred augmenter; thelast_content_linefilter
is kept for emission ordering only. Complemented by dropping:kindfrom
document_region_keyso:orphanvs:postludekind mismatches no longer
defeat the deduplication set. - Fixed multi-byte character (emoji) handling — upstream
ast-mergebyteslice→slicefix prevents corruption when merging content with multi-byte characters
Security
1.0.0 - 2026-02-19
- TAG: v1.0.0
- COVERAGE: 91.92% – 921/1002 lines in 14 files
- BRANCH COVERAGE: 73.00% – 311/426 branches in 14 files
- 97.39% documented
Added
- AGENTS.md
-
Psych::Merge::DiffMapper- Maps unified git diffs to YAML AST key paths- Inherits from
Ast::Merge::DiffMapperBase -
#map_hunk_to_paths- Maps diff hunks to YAML key paths (e.g.,["AllCops", "Exclude"]) -
#create_analysis- CreatesFileAnalysisfor YAML content - Tracks nested paths via indentation and MappingEntry location data
- Groups consecutive changed lines by their containing YAML node
- Inherits from
-
Psych::Merge::PartialTemplateMerger- Merges partial YAML templates into specific key paths- Navigate to specific key paths (e.g.,
["AllCops", "Exclude"]) in destination - Merge template content at that location while preserving rest of document
-
key_path:- Array of keys/indices to navigate to target location -
add_missing:- Whether to add template items not in destination (default:true) -
remove_missing:- Whether to remove destination items not in template (default:false) -
when_missing:- Behavior when key path not found (:skipor:add, default::skip) -
recursive:- Whether to recursively merge nested structures (default:true) - Returns
Resultobject withcontent,has_key_path,changed,stats,message
- Navigate to specific key paths (e.g.,
-
Psych::Merge::SmartMerger- New options for advanced merge control:-
recursive: true | false | Integer- Control recursive merging of nested structures-
true(default): Merge nested mappings/sequences recursively instead of replacing wholesale -
false: Replace entire matched nodes (original behavior) -
Integer > 0: Maximum recursion depth
-
-
remove_template_missing_nodes: false- Whentrue, removes destination nodes not present in template
-
-
Psych::Merge::ConflictResolver- Recursive merge implementation:-
#emit_recursive_merge- Recursively merge matched nodes -
#emit_recursive_mapping_merge- Merge nested mapping entries -
#emit_recursive_sequence_merge- Merge sequences with union semantics -
#can_merge_recursively?- Check if two nodes can be recursively merged - Handles both
MappingEntryand rawNodeWrappernodes
-
-
node_typingparameter for per-node-type merge preferences- Enables
preference: { default: :destination, special_type: :template }pattern - Works with custom merge_types assigned via node_typing lambdas
- Enables
-
regionsandregion_placeholderparameters for nested content merging - Initial release
Changed
- appraisal2 v3.0.6
- kettle-test v1.0.10
- stone_checksums v1.0.3
- ast-merge v4.0.6
- tree_haver v5.0.5
- tree_stump v0.2.0
- fork no longer required, updates all applied upstream
- Updated documentation on hostile takeover of RubyGems
- https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo
-
SmartMerger: Added
**optionsfor forward compatibility- Accepts additional options that may be added to base class in future
- Passes all options through to
SmartMergerBase
-
ConflictResolver: Added
**optionsfor forward compatibility- Now passes
match_refinerto base class instead of storing locally
- Now passes
-
MergeResult: Added
**optionsfor forward compatibility
Fixed
- ConflictResolver now applies Hash-based per-node-type preferences via
node_typing.