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.
Unreleased
[15.0.0] - 2026-07-06
Added
HeadMusic::Style::Guidelines::MinimumMelodicIntervals— a sufficiency gate on the number of moving melodic intervals, so a line that never (or barely) moves reads as a non-attempt rather than a flawed melody (MinimumMelodicIntervals.with(2)). The contour guides use it;StaticContourMelodyomits it so a repeated single pitch remains a legitimate static contour.weight:andgate:options onAnnotation.with— any ruleset entry can now carry a rubric weight or be marked as a gate, andConfigured#withlayers options so presets compose (e.g.MinimumNotes.with(5).with(gate: true))
Changed
- Breaking:
Analysis#fitnessis now a gated weighted rubric instead of an unweighted geometric mean: the product of the gate fitnesses multiplies a weighted arithmetic mean of the remaining (rubric) rules. Every fitness value shifts numerically; downstream consumers that compare grades against stored thresholds must recalibrate. - Non-attempts now grade zero: sufficiency guidelines (
MinimumNotes,MinimumMelodicIntervals) act as graded gate multipliers, so an empty or insufficient line scales the whole grade down to 0 instead of averaging against the other rules. - Contour guides weight
Contouredat the inverse golden ratio (φ⁻¹ ≈ 0.618) with their ten rubric peers sharing φ⁻² evenly, so a wrong-contour but otherwise perfect line grades exactly ~0.618 (HeadMusic::GOLDEN_RATIO_INVERSE) DiatonicandMaximumNotesare rate-normalized (fitness raised to 1/note-count), so grades are length-invariant: the same violation rate scores the same in an eight-note line as in a sixteen-note line- Broken-but-real work now lands on a deliberate soft floor (roughly 0.3–0.55): rate-normalized rules bottom out near φ⁻¹ and the arithmetic mean averages them, so a gate-passing melody that breaks most of the rubric grades substantially below perfect without collapsing toward the gated zero of a non-attempt
[14.0.0] - 2026-07-05
Added
HeadMusic::Style::Guidelines::Contoured— configurable guideline judging a melody against a chosen contour (Contoured.with(:arch)and five other keys:ascending,descending,valley,wave,static). Predicates are trend-based rather than strictly monotonic; a wrong contour receives a single mark spanning the melody. Unknown contour keys raiseArgumentErrorat guide-definition time.- Six contour guides subclassing
Guides::DiatonicMelody, each appending the configuredContouredguideline to the inherited ruleset:ArchContourMelody,AscendingContourMelody,DescendingContourMelody,StaticContourMelody,ValleyContourMelody,WaveContourMelody - Contour judgments deliberately complement
ConsonantClimax: an arch requires only an interior climax pitch level, leaving climax uniqueness and consonance to the existing guideline
[13.0.0] - 2026-07-05
Added
HeadMusic::Notation::NotationStyle— named notation traditions (british_brass_band,german,italian,concert_pitch) resolved as sparse overlays on adefaultstyle, backed bynotation_styles.yml, with.get/.defaultfactories and#notation_forHeadMusic::Notation::InstrumentNotation— the resolved notation value object (clef, sounding transposition, staves, and recorded register/clef alternatives) with value equalityInstrument#notation(style:)— notate an instrument through a chosen notation style, defaulting todefault
Changed
- Notation concerns (clef, sounding transposition, staff structure) now live in
NotationStyleinstead of on the instrument.Instrument’s notation methods (default_staves,default_clefs,sounding_transposition, etc.) delegate to the default style and resolve to the same values as before. Instrument#staff_schemesnow returns only the instrument’s default scheme; named schemes (brass-band, German/Italian bass clarinet, and register/clef alternatives) have moved into notation styles.
Removed
staff_schemesdata frominstruments.ymland the internalstaff_schemesplumbing onInstrument. Per-instrument notation conventions are now expressed as notation styles. (Breaking change — hence the major version bump.)
[12.6.0] - 2026-07-03
Added
DiatonicMelodyguide: a free diatonic melody not bound to cantus firmus start/end constraints (note-count range configurable, defaulting to 5–24)- Configurable guidelines — a guideline can now carry configuration into a
RULESETviaAnnotation.with(...)(wrapped inAnnotation::Configured):MinimumNotes/MaximumNotes— configurable note-count floor and ceiling (AtLeastEightNotes/UpToFourteenNotesretained as named defaults)NoteCountPerBar— configurablecountandrhythmic_value(unifiesOnePerBar,TwoPerBar,ThreePerBar,FourPerBar)DirectionChanges— configurablemaximum_notes_per_direction(unifiesModerateDirectionChangesandFrequentDirectionChanges)- Configurable thresholds on
SingableRange,MostlyConjunct,LimitOctaveLeaps, andSecondSpeciesBreak
Changed
- Extracted
HeadMusic::Style::Guides::Basefor shared guide analysis behavior;SpeciesMelodyandSpeciesHarmonynow inherit from it - Hoisted the guidelines common to every guide into
MELODIC_CORE/HARMONIC_COREconstants on the species base classes SingableRange’s message now reflects the configured range- Renamed the
qualityrake task tovalidate
[12.5.0] - 2026-04-08
Changed
- Improved fifth-species counterpoint guidelines
- Code quality improvements
Removed
- Combined 2+3+4 species guides and their guidelines
[12.4.0] - 2026-04-06
Added
- Fifth-species (florid) counterpoint guides
- Standard and alternate instrument tunings
Fixed
- Ukulele family stringings, tunings, and range data
[12.3.0] - 2026-02-25
Added
- Fourth-species counterpoint guides
Changed
- Code quality pass
[12.2.0] - 2026-02-24
Changed
- Improved guidelines for first-bar entry
[12.1.0] - 2026-02-24
Changed
- Refactored species guidelines into separate first-bar, middle-bar, and final-bar rules
- Unified
FinalBarWholeNoteandFinalBarDottedHalfNoteintoNoteFillsFinalBar
[12.0.1] - 2026-02-23
Changed
- Renamed triple-meter guides
[12.0.0] - 2026-02-21
Added
- Third-species 3:1 guidelines
- Allow a descending minor sixth as a singable interval
Changed
- Extracted shared base classes for guides and step-to-final-note guidelines
- Refactored third-species dissonance handling and other files to reduce code smells
[11.8.0] - 2026-02-16
Added
ThirdSpeciesMelodyandThirdSpeciesHarmonyguidesThirdSpeciesDissonanceTreatmentguidelineFourToOneguideline- Third-species counterpoint reference document
[11.7.0] - 2026-02-13
Added
- Parallel-perfect check for first species
Changed
Analysis#fitnessnow uses the geometric mean
[11.6.1] - 2026-02-12
Added
- Additional test coverage for the two-to-one guideline
Fixed
- Accept an implied rest in the first bar of second-species counterpoint
[11.6.0] - 2026-02-10
Added
- Second-species counterpoint style guides:
SecondSpeciesMelodyandSecondSpeciesHarmony - New guidelines for second-species counterpoint:
TwoToOne— enforces two half notes per cantus firmus whole note (with optional half-rest opening)WeakBeatDissonanceTreatment— dissonant weak beats must be passing tonesNoParallelPerfectOnDownbeats— forbids parallel perfect consonances on consecutive downbeatsNoParallelPerfectAcrossBarline— forbids parallel perfect consonances from weak beat to following downbeatNoStrongBeatUnisons— forbids unisons on interior downbeats
- Pedagogical reference document for second-species counterpoint (
references/second-species-counterpoint.md)
[11.0.0] - 2026-01-05
Changed
- BREAKING: Widened ActiveSupport dependency from
~> 7.0to>= 7.0, < 10to support Rails 8.x - Improved I18n initialization to be non-destructive:
- No longer overwrites
I18n.default_locale(allows Rails apps to control their default) - Adds HeadMusic locales to
available_localesinstead of replacing them - Only sets fallbacks if not already configured by the application
- No longer overwrites
- Updated CI workflow to test against both ActiveSupport 7.x and 8.x
Fixed
- Fixed compatibility issue with Rails 8.1.x applications
[10.0.0] - 2025-12-01
Changed
- Internal release for testing
[9.0.0] - 2025-10-24
Added
- Added
HeadMusic::Rudiment::Pitch::Parserfor strict pitch parsing - Added
HeadMusic::Rudiment::RhythmicValue::Parserfor rhythmic value parsing - Both parsers provide standardized
.parse()class method API
Changed
Pitch.from_namenow usesPitch::ParserinternallyRhythmicValue.getnow usesRhythmicValue::ParserinternallyNote.getnow parses “pitch rhythmic_value” strings inline without Parse module
Removed
- BREAKING: Removed
HeadMusic::Parse::Pitchclass - BREAKING: Removed
HeadMusic::Parse::RhythmicValueclass - BREAKING: Removed
HeadMusic::Parse::RhythmicElementclass - BREAKING: Removed entire
HeadMusic::Parsemodule
Migration Guide
If you were using the removed Parse classes, migrate as follows:
```ruby # Before (v8.x) parser = HeadMusic::Parse::Pitch.new(“C#4”) pitch = parser.pitch
After (v9.x)
pitch = HeadMusic::Rudiment::Pitch.get(“C#4”) # or for strict parsing: pitch = HeadMusic::Rudiment::Pitch::Parser.parse(“C#4”) ```
```ruby # Before (v8.x) parser = HeadMusic::Parse::RhythmicValue.new(“dotted quarter”) value = parser.rhythmic_value
After (v9.x)
value = HeadMusic::Rudiment::RhythmicValue.get(“dotted quarter”) # or for strict parsing: value = HeadMusic::Rudiment::RhythmicValue::Parser.parse(“dotted quarter”) ```
```ruby # Before (v8.x) parser = HeadMusic::Parse::RhythmicElement.new(“F#4 dotted-quarter”) note = parser.note
After (v9.x)
note = HeadMusic::Rudiment::Note.get(“F#4 dotted-quarter”) ```
[8.2.1] - 2025-06-21
Added
- Added missing modern instruments to all locales (ukulele family, electronic instruments, world instruments)
- Added pitched/unpitched instrument classifications to all non-English locales
- Added new instrument families: bass_drum, tambourine, and celesta
Changed
- Improved instrument family classifications (added fretted/unfretted, valve categorizations)
- Removed incorrect percussion classification from harpsichord and clavichord
Fixed
- Fixed Russian translation errors (tritone and perfect_unison)
8.2.0 - 2025-06-20
Added
- Added comprehensive GitHub Actions CI/CD workflows (test matrix, security scanning, automated releases)
- Added security tooling with bundler-audit for vulnerability scanning
- Added YARD documentation generation with kramdown support
- Added SimpleCov coverage tracking with 90% threshold and branch coverage
- Added Dependabot configuration for automated dependency updates
- Added inclusive CONTRIBUTING.md with comprehensive contribution guidelines
- Added complete CHANGELOG.md tracking version history
- Added GitHub issue templates (bug reports, feature requests) and PR template
- Added gemspec metadata fields for better gem documentation and security
- Added rubygems_mfa_required for enhanced security
Changed
- Standardized Ruby version requirement to 3.3.0 across all configuration files
- Updated and organized development dependencies (removed deprecated codeclimate-test-reporter)
- Enhanced .gitignore with modern patterns and restored Gemfile.lock tracking
- Improved RuboCop configuration (increased MultipleMemoizedHelpers max to 12)
- Enhanced Rakefile with quality, documentation, and coverage tasks
Removed
- Removed outdated Travis CI and CircleCI configurations (replaced with GitHub Actions)
8.1.1 - 2024-12-20
Changed
- Tweaked gemspec summary
8.1.0 - 2024-12-20
Added
- Enhanced solmization support
Changed
- Code cleanup and improvements
- Improved spec coverage
- Refactored melodic intervals to separate pitch and note concerns
8.0.2 - 2024-12-19
Fixed
- RuboCop style fixes
Changed
- Improved RuboCop configuration
8.0.0 - 2024-12-19
Changed
- Major reorganization: moved specs into folders
- Organized models into modules for better structure
- BREAKING: Module structure changes may require updates to require statements
7.0.5 - 2024-01-20
Changed
- Upgraded to Ruby 3.3.0
- Improvements to Spanish translations of recorder
7.0.4 - 2024-01-15
Added
- Rudiment translations
- Instrument classification translations
- Interval translations
7.0.3 - 2024-01-10
Added
- Russian instrument translations using Cyrillic characters
- Spanish translations for instruments
Changed
- Uncapitalized languages in Italian and Spanish translations
- Spanish translation corrections and improvements
- Translation file cleanup
7.0.2 - 2023-12-15
Changed
- Various improvements and bug fixes
7.0.1 - 2023-12-10
Changed
- Minor improvements and bug fixes
7.0.0 - 2023-12-01
Changed
- Major version bump indicating significant changes
- BREAKING: Check upgrade guide for migration instructions
6.0.1 - 2023-11-15
Fixed
- Bug fixes and improvements
6.0.0 - 2023-11-01
Changed
- Major architectural improvements
- BREAKING: API changes may require code updates
5.0.0 - 2023-10-15
Changed
- Significant refactoring of core components
- BREAKING: Check documentation for new API
4.0.1 - 2023-09-20
Fixed
- Minor bug fixes
4.0.0 - 2023-09-15
Added
- Expanded instrument support
- Instrument data improvements
Changed
- Enhanced Instrument class functionality
3.0.1 - 2023-08-20
Fixed
- Minor improvements and fixes
3.0.0 - 2023-08-15
Changed
- Major version update with architectural improvements
- BREAKING: Significant API changes
2.0.0 - 2023-07-01
Changed
- Major refactoring of core functionality
- BREAKING: API redesign
1.0.0 - 2023-06-01
Added
- First stable release
- Complete music theory rudiments implementation
- Comprehensive scale and interval support
- Basic composition and voice handling
0.29.0 - 2023-05-15
Added
- Additional music theory features
- Improved documentation
0.28.0 - 2023-05-01
Changed
- Performance improvements
- Code organization enhancements
Earlier versions
For changes in versions prior to 0.28.0, please refer to the git history.