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.1.0] - 2026-07-07

Added

  • HeadMusic::Content::Composition.to_musicxml for MusicXML export
  • HeadMusic::Content::Composition.to_abc for ABC Notation export. ABC can round-trip to and from Composition.

[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; StaticContourMelody omits it so a repeated single pitch remains a legitimate static contour.
  • weight: and gate: options on Annotation.with — any ruleset entry can now carry a rubric weight or be marked as a gate, and Configured#with layers options so presets compose (e.g. MinimumNotes.with(5).with(gate: true))

Changed

  • Breaking: Analysis#fitness is 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 Contoured at 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)
  • Diatonic and MaximumNotes are 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 raise ArgumentError at guide-definition time.
  • Six contour guides subclassing Guides::DiatonicMelody, each appending the configured Contoured guideline 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 a default style, backed by notation_styles.yml, with .get/.default factories and #notation_for
  • HeadMusic::Notation::InstrumentNotation — the resolved notation value object (clef, sounding transposition, staves, and recorded register/clef alternatives) with value equality
  • Instrument#notation(style:) — notate an instrument through a chosen notation style, defaulting to default

Changed

  • Notation concerns (clef, sounding transposition, staff structure) now live in NotationStyle instead 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_schemes now 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_schemes data from instruments.yml and the internal staff_schemes plumbing on Instrument. Per-instrument notation conventions are now expressed as notation styles. (Breaking change — hence the major version bump.)

[12.6.0] - 2026-07-03

Added

  • DiatonicMelody guide: 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 RULESET via Annotation.with(...) (wrapped in Annotation::Configured):
    • MinimumNotes / MaximumNotes — configurable note-count floor and ceiling (AtLeastEightNotes / UpToFourteenNotes retained as named defaults)
    • NoteCountPerBar — configurable count and rhythmic_value (unifies OnePerBar, TwoPerBar, ThreePerBar, FourPerBar)
    • DirectionChanges — configurable maximum_notes_per_direction (unifies ModerateDirectionChanges and FrequentDirectionChanges)
    • Configurable thresholds on SingableRange, MostlyConjunct, LimitOctaveLeaps, and SecondSpeciesBreak

Changed

  • Extracted HeadMusic::Style::Guides::Base for shared guide analysis behavior; SpeciesMelody and SpeciesHarmony now inherit from it
  • Hoisted the guidelines common to every guide into MELODIC_CORE / HARMONIC_CORE constants on the species base classes
  • SingableRange’s message now reflects the configured range
  • Renamed the quality rake task to validate

[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 FinalBarWholeNote and FinalBarDottedHalfNote into NoteFillsFinalBar

[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

  • ThirdSpeciesMelody and ThirdSpeciesHarmony guides
  • ThirdSpeciesDissonanceTreatment guideline
  • FourToOne guideline
  • Third-species counterpoint reference document

[11.7.0] - 2026-02-13

Added

  • Parallel-perfect check for first species

Changed

  • Analysis#fitness now 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: SecondSpeciesMelody and SecondSpeciesHarmony
  • 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 tones
    • NoParallelPerfectOnDownbeats — forbids parallel perfect consonances on consecutive downbeats
    • NoParallelPerfectAcrossBarline — forbids parallel perfect consonances from weak beat to following downbeat
    • NoStrongBeatUnisons — 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.0 to >= 7.0, < 10 to 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_locales instead of replacing them
    • Only sets fallbacks if not already configured by the application
  • 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::Parser for strict pitch parsing
  • Added HeadMusic::Rudiment::RhythmicValue::Parser for rhythmic value parsing
  • Both parsers provide standardized .parse() class method API

Changed

  • Pitch.from_name now uses Pitch::Parser internally
  • RhythmicValue.get now uses RhythmicValue::Parser internally
  • Note.get now parses “pitch rhythmic_value” strings inline without Parse module

Removed

  • BREAKING: Removed HeadMusic::Parse::Pitch class
  • BREAKING: Removed HeadMusic::Parse::RhythmicValue class
  • BREAKING: Removed HeadMusic::Parse::RhythmicElement class
  • BREAKING: Removed entire HeadMusic::Parse module

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.