diff --git a/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs
new file mode 100644
index 0000000..00134b4
--- /dev/null
+++ b/Semantics.Test/Quantities/GeneratorOutputInvariantTests.cs
@@ -0,0 +1,157 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Test.Quantities;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using ktsu.Semantics.Quantities;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+///
+/// Locks in invariants on the source generator's output. Issue #57 raised the concern that
+/// the generator's dedup keys could let two methods (or operators) with the same name and
+/// parameter types land on the same type — which the C# compiler already rejects, but this
+/// test makes the property explicit and regression-proof if the dedup logic changes.
+///
+[TestClass]
+public sealed class GeneratorOutputInvariantTests
+{
+ ///
+ /// For every generated quantity type in ktsu.Semantics.Quantities, no two public
+ /// static methods (including operators) share both the same name and the same parameter
+ /// type list. Walks the runtime assembly rather than re-parsing the .g.cs files because
+ /// the compiled types are the source of truth — anything the test sees is what consumers
+ /// would call.
+ ///
+ [TestMethod]
+ public void NoDuplicatePublicStaticMethodsOrOperatorsPerGeneratedType()
+ {
+ Assembly assembly = typeof(Mass<>).Assembly;
+ List generatedQuantityTypes = [.. CollectGeneratedQuantityTypes(assembly)];
+
+ // Sanity: we should be looking at a non-trivial set, otherwise the test is silently
+ // vacuous (e.g. namespace got renamed and the filter dropped everything).
+ Assert.IsTrue(
+ generatedQuantityTypes.Count > 50,
+ $"Expected to find many generated quantity types (got {generatedQuantityTypes.Count}). The filter likely needs updating.");
+
+ List failures = [];
+ foreach (Type type in generatedQuantityTypes)
+ {
+ MethodInfo[] staticMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
+
+ IEnumerable> groups = staticMethods.GroupBy(SignatureKey);
+ foreach (IGrouping group in groups)
+ {
+ int count = group.Count();
+ if (count > 1)
+ {
+ failures.Add($"{type.Name}: {group.Key} appears {count} times");
+ }
+ }
+ }
+
+ if (failures.Count > 0)
+ {
+ Assert.Fail(
+ $"Found duplicate public static method signatures on generated quantity types:\n " +
+ string.Join("\n ", failures));
+ }
+ }
+
+ ///
+ /// Cross-dimensional operator * overloads should exist in both operand orders so
+ /// either-order user code (mass * accel and accel * mass) compiles. The
+ /// generator's CollectAllOperators emits both directions; this test asserts the
+ /// commutativity property explicitly so a regression in the dedup keys would fail here
+ /// before it reaches a downstream consumer.
+ ///
+ [TestMethod]
+ public void EveryCrossDimensionalMultiplicationHasBothOperandOrders()
+ {
+ Assembly assembly = typeof(Mass<>).Assembly;
+ List types = [.. CollectGeneratedQuantityTypes(assembly)];
+
+ // Collect every observed operator * signature as a tuple (left, right, returnType).
+ HashSet<(string Left, string Right, string Result)> observed = [];
+ foreach (Type type in types)
+ {
+ foreach (MethodInfo m in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly))
+ {
+ if (m.Name != "op_Multiply")
+ {
+ continue;
+ }
+
+ ParameterInfo[] pars = m.GetParameters();
+ if (pars.Length != 2)
+ {
+ continue;
+ }
+
+ observed.Add((pars[0].ParameterType.Name, pars[1].ParameterType.Name, m.ReturnType.Name));
+ }
+ }
+
+ // For every cross-dimensional product (operands of distinct types), the swapped pair
+ // should also be present with the same return. Same-type products (T * T) are exempt
+ // because there is no swap — they're idempotent under reorder.
+ List missing = [];
+ foreach ((string left, string right, string result) in observed)
+ {
+ if (left == right)
+ {
+ continue;
+ }
+
+ if (!observed.Contains((right, left, result)))
+ {
+ missing.Add($"missing reverse pair: {right} * {left} -> {result} (forward {left} * {right} -> {result} exists)");
+ }
+ }
+
+ if (missing.Count > 0)
+ {
+ Assert.Fail(
+ "Cross-dimensional multiplication should be emitted in both operand orders, but found " +
+ $"{missing.Count} unmatched forward(s):\n " +
+ string.Join("\n ", missing));
+ }
+ }
+
+ private static IEnumerable CollectGeneratedQuantityTypes(Assembly assembly)
+ {
+ foreach (Type type in assembly.GetTypes())
+ {
+ if (type.Namespace != "ktsu.Semantics.Quantities")
+ {
+ continue;
+ }
+
+ if (!type.IsGenericTypeDefinition)
+ {
+ continue;
+ }
+
+ // Generated quantity types implement one of IVector0..IVector4 (closed over TSelf, T).
+ bool isQuantity = type.GetInterfaces().Any(static i =>
+ i.IsGenericType && i.Name.StartsWith("IVector", StringComparison.Ordinal));
+ if (!isQuantity)
+ {
+ continue;
+ }
+
+ yield return type;
+ }
+ }
+
+ private static string SignatureKey(MethodInfo m)
+ {
+ string parameterList = string.Join(",", m.GetParameters().Select(static p => p.ParameterType.FullName ?? p.ParameterType.Name));
+ return $"{m.Name}({parameterList})";
+ }
+}