ktsu.Semantics.Paths 3.0.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package ktsu.Semantics.Paths --version 3.0.0
                    
NuGet\Install-Package ktsu.Semantics.Paths -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ktsu.Semantics.Paths" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ktsu.Semantics.Paths" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="ktsu.Semantics.Paths" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ktsu.Semantics.Paths --version 3.0.0
                    
#r "nuget: ktsu.Semantics.Paths, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ktsu.Semantics.Paths@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ktsu.Semantics.Paths&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=ktsu.Semantics.Paths&version=3.0.0
                    
Install as a Cake Tool

ktsu.Semantics.Paths

Polymorphic, strongly-typed file system path types that keep files, directories, absolute, and relative paths distinct at compile time.

License NuGet Version NuGet Version NuGet Downloads GitHub commit activity GitHub contributors GitHub Actions Workflow Status

ktsu.Semantics.Paths is one package in the ktsu.Semantics family. It builds on ktsu.Semantics.Strings, which supplies the underlying SemanticString<T> machinery.

Introduction

ktsu.Semantics.Paths models a file system path as a type, not a bare string. The type encodes two independent facts: whether the path names a file or a directory, and whether it is absolute or relative. That gives concrete types like AbsoluteFilePath, RelativeDirectoryPath, and orientation-agnostic FilePath / DirectoryPath, all implementing a shared IPath interface hierarchy. You can hold mixed paths in a List<IPath> and filter by capability with OfType<IFilePath>().

Paths are canonicalized on creation (separators normalized, trailing separators trimmed), convert implicitly to string so they drop into any System.IO API, and compose with a / operator that returns the correctly-typed result.

Features

  • Interface hierarchy: IPath with IFilePath, IDirectoryPath, IAbsolutePath, IRelativePath, and the four combinations (IAbsoluteFilePath, IAbsoluteDirectoryPath, IRelativeFilePath, IRelativeDirectoryPath).
  • Eight concrete path types: AbsolutePath, RelativePath, FilePath, DirectoryPath, AbsoluteFilePath, AbsoluteDirectoryPath, RelativeFilePath, RelativeDirectoryPath.
  • Path decomposition: FileName, FileExtension, FullFileExtension (for .tar.gz), DirectoryPath, FileNameWithoutExtension, plus the FileName / FileExtension / DirectoryName primitive value types.
  • Composition with /: directory / relativePath, directory / FileName, and similar, each returning the right result type.
  • Absolute/relative conversions: AsAbsolute(), AsAbsolute(baseDirectory), and AsRelative(baseDirectory).
  • Directory navigation: Parent, Depth, IsRoot, GetAncestors(), IsChildOf, IsParentOf, and strongly-typed GetContents() enumeration.
  • Filesystem checks: Exists, IsFile, IsDirectory.
  • Validation and canonicalization inherited from the semantic string framework, driven by path attributes such as [IsAbsolutePath], [IsFileName], and [IsFileExtension].

Installation

Package Manager Console

Install-Package ktsu.Semantics.Paths

.NET CLI

dotnet add package ktsu.Semantics.Paths

Package Reference

<PackageReference Include="ktsu.Semantics.Paths" Version="x.y.z" />

Usage Examples

Basic Example

using ktsu.Semantics.Paths;

// Build paths with the typed factory, then compose with the '/' operator
AbsoluteDirectoryPath projectDir = AbsoluteDirectoryPath.Create(@"C:\repos\app");
RelativeFilePath rel = RelativeFilePath.Create(@"src\Program.cs");

AbsoluteFilePath source = projectDir / rel;   // C:\repos\app\src\Program.cs
FileName name = source.FileName;              // Program.cs
FileExtension ext = source.FileExtension;     // .cs
AbsoluteDirectoryPath dir = source.AbsoluteDirectoryPath;

if (source.Exists)
{
    // implicit conversion to string drops straight into System.IO
    string text = System.IO.File.ReadAllText(source);
}

Absolute and relative conversions

using ktsu.Semantics.Paths;

AbsoluteDirectoryPath root = AbsoluteDirectoryPath.Create(@"C:\data");
AbsoluteFilePath file = AbsoluteFilePath.Create(@"C:\data\logs\app.log");

RelativeFilePath relative = file.AsRelative(root);        // logs\app.log
AbsoluteFilePath backAgain = relative.AsAbsolute(root);   // C:\data\logs\app.log

AbsoluteFilePath renamed = file.ChangeExtension(FileExtension.Create(".bak"));
bool nested = file.IsChildOf(root);                       // true

AsAbsolute() with no argument resolves a relative path against the current working directory. The baseDirectory overload of AsAbsolute exists on the relative path types only.

Polymorphic collections and typed enumeration

using ktsu.Semantics.Paths;

List<IPath> all =
[
    AbsoluteFilePath.Create(@"C:\data.txt"),
    RelativeDirectoryPath.Create(@"logs\app"),
    FilePath.Create(@"document.pdf"),
];

List<IFilePath> files = all.OfType<IFilePath>().ToList();
List<IAbsolutePath> absolutes = all.OfType<IAbsolutePath>().ToList();

// GetContents() yields correctly-typed children
AbsoluteDirectoryPath project = AbsoluteDirectoryPath.Create(@"C:\project");
foreach (IPath entry in project.GetContents())
{
    switch (entry)
    {
        case AbsoluteFilePath f:
            Console.WriteLine($"file: {f.FileName} ({f.FileExtension})");
            break;
        case AbsoluteDirectoryPath d:
            Console.WriteLine($"dir:  {d.Name} at depth {d.Depth}");
            break;
    }
}

GetContents() returns an empty sequence rather than throwing when the directory is missing or access is denied.

API Reference

Interface hierarchy

Interface Extends Notable member
IPath (none) marker
IFilePath IPath AbsoluteFilePath AsAbsolute()
IDirectoryPath IPath AsAbsolute(), IEnumerable<IPath> GetContents()
IAbsolutePath IPath AbsolutePath AsAbsolute()
IRelativePath IPath AbsolutePath AsAbsolute()
IAbsoluteFilePath IFilePath, IAbsolutePath typed AsAbsolute()
IAbsoluteDirectoryPath IDirectoryPath, IAbsolutePath typed AsAbsolute()
IRelativeFilePath IFilePath, IRelativePath typed AsAbsolute()
IRelativeDirectoryPath IDirectoryPath, IRelativePath typed AsAbsolute()

Concrete types and creation

All concrete types are sealed records created through the inherited static factory Create(...) (accepting string, char[], or ReadOnlySpan<char>). Create throws ArgumentException on invalid input and ArgumentNullException on null.

Type Kind Interface
AbsolutePath untyped absolute IAbsolutePath
RelativePath untyped relative IRelativePath
FilePath orientation-agnostic file IFilePath
DirectoryPath orientation-agnostic directory IDirectoryPath
AbsoluteFilePath absolute file IAbsoluteFilePath
AbsoluteDirectoryPath absolute directory IAbsoluteDirectoryPath
RelativeFilePath relative file IRelativeFilePath
RelativeDirectoryPath relative directory IRelativeDirectoryPath

The primitive component types FileName, FileExtension, and DirectoryName are semantic strings in their own right.

Common members

Name Type Description
Exists bool True if the path is an existing file or directory.
IsFile / IsDirectory bool Filesystem-backed checks.
FileName FileName Filename portion (file paths).
FileExtension / FullFileExtension FileExtension Last extension / everything from the first dot.
DirectoryPath DirectoryPath Directory portion of a file path.
Parent / Name / Depth / IsRoot directory members Directory navigation.
AsAbsolute() typed absolute path Resolve against the current working directory.
AsAbsolute(AbsoluteDirectoryPath) typed absolute path Resolve a relative path against a base (relative types only).
AsRelative(AbsoluteDirectoryPath) typed relative path Make relative to a base directory.
GetContents() IEnumerable<IPath> Strongly-typed directory children.
operator / typed result Combine a directory with a relative path, FileName, or DirectoryName.

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

License

This project is licensed under the MIT License. See the LICENSE.md file for details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (24)

Showing the top 5 NuGet packages that depend on ktsu.Semantics.Paths:

Package Downloads
ktsu.AppDataStorage

A .NET library for persistent application data storage using JSON serialization. Provides a simple inherit-and-use pattern with automatic file management, thread-safe operations, debounced saves, backup recovery, and singleton access. Stores data in the user's app data folder with support for custom subdirectories and file names.

ktsu.ImGui.Popups

A professional library for modal dialogs and popup components in ImGui.NET, providing message boxes, input prompts with validation (string, int, float), searchable selection lists with type-safe generics, and an advanced filesystem browser with open/save modes, directory navigation, and pattern filtering support.

ktsu.ImGui.App

A comprehensive .NET library that provides complete application scaffolding for Dear ImGui applications, featuring window management, DPI-aware rendering, precision PID-controlled frame limiting with comprehensive auto-tuning, advanced font handling with Unicode/emoji support, texture management, and debug tooling. Built on Silk.NET for cross-platform OpenGL support and Hexa.NET.ImGui for modern Dear ImGui bindings.

ktsu.SingleAppInstance

A lightweight .NET library that ensures only one instance of an application is running at a time. Uses a JSON-serialized PID file with multi-attribute process verification (PID, name, start time, executable path) for accurate instance detection, built-in race condition handling for simultaneous startups, and backward compatibility with legacy PID formats. Supports .NET 10.0 through .NET Standard 2.0.

ktsu.ImGui.Widgets

A comprehensive library of custom widgets and UI components for ImGui.NET, featuring radial progress bars with countdown/count-up timers, tabbed interfaces with drag-and-drop support, type-safe combo boxes, resizable divider containers, powerful search boxes with fuzzy matching, icons with event handling, flexible grid layouts, and scoped utilities for IDs and disabling elements.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.2.6 82 9/4/2026
3.2.5 426 9/3/2026
3.2.4 474 9/2/2026
3.2.3 479 9/1/2026
3.2.2 537 8/31/2026
3.2.1 640 8/28/2026
3.2.0 1,117 8/27/2026
3.1.4 967 8/25/2026
3.1.3 1,047 8/24/2026
3.1.2 808 8/21/2026
3.1.1 1,292 8/19/2026
3.1.0 469 8/19/2026
3.0.1 779 8/18/2026
3.0.0 1,106 8/15/2026
2.9.14 1,040 8/14/2026
2.9.13 120 8/14/2026
2.9.12 110 8/14/2026
2.9.11 121 8/14/2026
2.9.10 283 8/14/2026
2.9.9 112 8/14/2026
Loading failed

## v3.0.0 (major)

Changes since v2.0.0:

- [major] Sonar: clear all 24 open issues and the one security hotspot ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] MSTEST0058/0061: fix the two MSTest analyzer diagnostics ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S4136/S4144: group overloads and drop duplicate private factories ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S3776: reduce cognitive complexity in seven methods ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S3267: clear the last two generator loops ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S1172: drop the last four unused generator parameters ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S3267: simplify two generator loops with LINQ ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S1192: name the literals the generators emit ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Add a local SonarCloud check; simplify AdjustForContrast; test PatternValidationRule ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fix a sentence-case bug, harden the pattern regex, tidy the generator ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Extract the shared delimiter-separated casing rules ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Adopt ktsu.Sdk 2.27.0: KTSU0001 package references ([@matt-edmondson](https://github.com/matt-edmondson))
- Merge remote-tracking branch 'origin/main' into chore/sonarcloud-cleanup-2 ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Cover the untested casing and relative-path branches ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Cover PropertyTemplate shorthand; drop the duplicated const docs ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] S4136: group AsAbsolute overloads in the relative path types ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fix SonarCloud issues: S2223, S1192, S6610, S6580, S3358 ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fold the generator tests into Semantics.Test so their coverage is collected ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Add source generator tests to cover the generator pipeline ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] MSTEST0037: use the intent-revealing assertions ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] MSTEST0068: CollectionAssert.AreEqual -> Assert.AreSequenceEqual ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Migrate file headers to the one-line ktsu-dev form ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fix SonarCloud BLOCKER issues in test suite ([@matt-edmondson](https://github.com/matt-edmondson))
- Sync .serena\.gitignore ([@KtsuTools](https://github.com/KtsuTools))
- Sync .runsettings ([@KtsuTools](https://github.com/KtsuTools))
- Sync .editorconfig ([@KtsuTools](https://github.com/KtsuTools))
- Sync .gitattributes ([@KtsuTools](https://github.com/KtsuTools))
- Sync global.json ([@KtsuTools](https://github.com/KtsuTools))
- [minor] Return the root itself from AbsoluteDirectoryPath.Parent ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fix directory detection in SemanticRelativePath.Make ([@matt-edmondson](https://github.com/matt-edmondson))
- Make the new path tests platform-agnostic ([@matt-edmondson](https://github.com/matt-edmondson))
- Emit CRLF from the generators and re-enable package validation ([@matt-edmondson](https://github.com/matt-edmondson))
- [minor] Compare semantic strings by value and expose path values on interfaces ([@matt-edmondson](https://github.com/matt-edmondson))
- [minor] Add color adjustment operations across color spaces ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] Fix Oklch assertion in color cross-conversion tests ([@matt-edmondson](https://github.com/matt-edmondson))
- [minor] Add cross-space conversions between all color types ([@matt-edmondson](https://github.com/matt-edmondson))
- fix(music): use ValueTuple.GetHashCode instead of System.HashCode for netstandard2.0 compatibility ([@matt-edmondson](https://github.com/matt-edmondson))
- refactor(music): split Progression.TryParse into helpers to cut cognitive complexity and remove always-true check (SonarQube S3776/S2583) ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(music): update examples and references for Parse/TryParse rename and chart-style progressions ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): chart-style Arrangement ToString + Parse/TryParse + structural equality ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): chart-style Section ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music)!: replace bar-delimited Progression.Parse with chart-style ToString/Parse/TryParse + structural equality; migrate call sites ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): rename Form.FromPattern to Parse/TryParse, canonical ToString, structural equality ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Rest canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Note canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): ChordEvent canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): canonical Chord ToString, TryParse, ParseRoot via Notation ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Key canonical ToString + Parse/TryParse; roman-numeral accidental via Notation ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Scale canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Tempo canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Velocity canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): TimeSignature canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Duration canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): Interval canonical ToString + Parse/TryParse ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): rename Mode.FromName to Parse/TryParse, canonical ToString ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): typed Pitch factory, rename FromName to Parse/TryParse, canonical ToString ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): typed PitchClass factory, Parse/TryParse, canonical ToString ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add NoteLetter and Accidental enums ([@matt-edmondson](https://github.com/matt-edmondson))
- docs: implementation plan for music type-safe factories and canonical round-trip ToString ([@matt-edmondson](https://github.com/matt-edmondson))
- docs: revise music factories spec with canonical round-trip ToString and chart-style aggregate format ([@matt-edmondson](https://github.com/matt-edmondson))
- docs: design spec for music type-safe factories and Parse/TryParse convention ([@matt-edmondson](https://github.com/matt-edmondson))
- [patch] docs: add per-package READMEs and turn root README into a family index ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(music): document the analysis aggregate layer ([@matt-edmondson](https://github.com/matt-edmondson))
- test(music): lock guard/coverage contracts; dedupe chromatic scale check ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Form pattern extraction and named-form recognition ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Arrangement container ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Section structural unit ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add chromatic chord identification ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add key inference by diatonic fit ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(music): switch key inference to quality-weighted scoring ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add cadence detection ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add roman-numeral labeling and functional classification ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Progression.Parse bar-delimited chord syntax ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Progression core (construction, totals, empty rejection) ([@matt-edmondson](https://github.com/matt-edmondson))
- fix(music): drop CA1859 pragma; use IMusicalEvent helper in ChordEvent test ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add ChordEvent harmonic event type ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(music): implementation plan for analysis aggregate layer ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(music): design spec for analysis aggregate layer ([@matt-edmondson](https://github.com/matt-edmondson))
- test(strings): add As<T> round-trip test for Uuid ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): reconcile spec As<T> test bullet with implemented roster ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): document Identifiers package in README ([@matt-edmondson](https://github.com/matt-edmondson))
- chore(strings): finalize Identifiers package and document it ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add JwtToken identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add Iban identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add Isbn identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- style(strings): add trailing newline to IsCreditCardNumberAttribute.cs ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): use pattern-matching form in Tasks 5-6 (IDE0078) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add CreditCardNumber identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add Ulid identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): align plan Tasks 3-7 with repo conventions (ThrowsExactly, no using System, Ensure.NotNull) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(strings): add Uuid identifier type ([@matt-edmondson](https://github.com/matt-edmondson))
- chore(strings): scaffold Semantics.Strings.Identifiers package ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): correct empty-string handling in spec; add implementation plan ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(strings): spec for Semantics.Strings.Identifiers (Phase 0) ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(color): correct Oklab round-trip tolerance note in plan ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add NamedColors and gamma-regression tests ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add Oklab mix, lerp, distance, and gradient ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add WCAG luminance, contrast, and accessibility adjustment ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add HSL and HSV conversions ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add Oklab and Oklch perceptual spaces ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add hex and byte conversions (sRGB-interpreted) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): add Srgb space and gamma-correct sRGB<->linear boundary ([@matt-edmondson](https://github.com/matt-edmondson))
- docs(color): add semantic-domains roadmap, Semantics.Color spec and plan ([@matt-edmondson](https://github.com/matt-edmondson))
- style(color): strip UTF-8 BOM and add final newline (editorconfig) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(color): scaffold Semantics.Color with canonical linear Color type ([@matt-edmondson](https://github.com/matt-edmondson))
- docs: cover Semantics.Music score primitives, frequency, inversions, roman parsing ([@matt-edmondson](https://github.com/matt-edmondson))
- [minor] feat(music): score primitives, frequency bridge, inversions/transpose, roman-numeral parsing ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): parse roman numerals back into chords (inverse of RomanNumeralOf) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add chord inversions and Transpose on Chord/Scale/Key ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Pitch<->frequency (A440) and interval cents ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add score primitives (Velocity, Tempo, Note, Rest) with real-time conversion ([@matt-edmondson](https://github.com/matt-edmondson))
- Merge feature/semantics-music-types: musical value types ([@matt-edmondson](https://github.com/matt-edmondson))
- [minor] feat(music): musical value types (pitch, interval, scale, chord, key, duration) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Key with roman-numeral function; spell chromatic degrees conventionally (flat-preference) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Chord engine with parsing, tones, and voicing (full HeatDeathRomance vocabulary) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add TimeSignature with bar and beat durations ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add rational Duration with arithmetic and dotted/tuplet support ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Scale and ScaleDegree with degree resolution ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Mode with full standard scale catalog (diatonic, jazz, symmetric, pentatonic) ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Interval with octave folding and pitch difference ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): add Pitch with MIDI/name conversion and transpose ([@matt-edmondson](https://github.com/matt-edmondson))
- feat(music): scaffold Semantics.Music with PitchClass ([@matt-edmondson](https://github.com/matt-edmondson))
- fix(packaging): unblock the 2.0 release pipeline [patch] ([@matt-edmondson](https://github.com/matt-edmondson))