From a72c2a1114577c03b63da7ce110d7be732decfb1 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:37:56 -0500 Subject: [PATCH 01/38] claude autosave 2026-08-07T03:37:56Z --- src/dart/lib/src/version.dart | 398 ++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 src/dart/lib/src/version.dart diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart new file mode 100644 index 0000000..2b0bb67 --- /dev/null +++ b/src/dart/lib/src/version.dart @@ -0,0 +1,398 @@ +/// Version parsing, comparison, and requirement matching — the Dart mirror of +/// `zed_interfaces::version` (Rust). +/// +/// Deliberately dependency-free. Reaching for `pub_semver` here would look +/// cheaper, but its dialect differs from Cargo's in exactly the places that +/// matter: a bare `1.0.0` is an *exact* constraint there and a caret range in +/// Cargo, and partial versions (`^1.2`) are spelled differently again. Three +/// implementations of one contract cannot afford a translation layer whose +/// edge cases nobody reads — so the algebra is written out, and +/// `conformance/cases/version-resolution.json` proves it agrees with Rust. +library; + +/// A parsed semantic version. Build metadata is dropped on purpose: semver +/// precedence ignores it, so `2.0.0+incompatible` and `2.0.0` are one identity. +class SemVer implements Comparable { + const SemVer(this.major, this.minor, this.patch, [this.pre = const []]); + + final int major; + final int minor; + final int patch; + + /// Dot-separated prerelease identifiers; empty for a stable release. + final List pre; + + bool get isStable => pre.isEmpty; + + @override + int compareTo(SemVer other) { + for (final pair in [ + [major, other.major], + [minor, other.minor], + [patch, other.patch], + ]) { + final ordering = pair[0].compareTo(pair[1]); + if (ordering != 0) return ordering; + } + return _comparePre(pre, other.pre); + } + + @override + bool operator ==(Object other) => other is SemVer && compareTo(other) == 0; + + @override + int get hashCode => Object.hash(major, minor, patch, pre.join('.')); + + @override + String toString() { + final core = '$major.$minor.$patch'; + return pre.isEmpty ? core : '$core-${pre.join('.')}'; + } +} + +/// Semver §11: a prerelease is *lower* than the release it precedes; numeric +/// identifiers order numerically and rank below alphanumeric ones; when one set +/// is a prefix of the other, the longer set is higher. +int _comparePre(List a, List b) { + if (a.isEmpty && b.isEmpty) return 0; + if (a.isEmpty) return 1; + if (b.isEmpty) return -1; + for (var i = 0; i < a.length && i < b.length; i++) { + final left = a[i]; + final right = b[i]; + final leftNum = int.tryParse(left); + final rightNum = int.tryParse(right); + final ordering = switch ((leftNum, rightNum)) { + (final int l, final int r) => l.compareTo(r), + (int(), null) => -1, + (null, int()) => 1, + _ => left.compareTo(right), + }; + if (ordering != 0) return ordering; + } + return a.length.compareTo(b.length); +} + +final RegExp _semverRe = RegExp( + r'^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$', +); + +SemVer? _parseStrict(String raw) { + final match = _semverRe.firstMatch(raw); + if (match == null) return null; + final pre = match.group(4); + // Leading zeros are illegal in semver numeric identifiers; calendar versions + // hit this constantly (`2026.06.01`) and are normalized separately. + for (final segment in [match.group(1)!, match.group(2)!, match.group(3)!]) { + if (segment.length > 1 && segment.startsWith('0')) return null; + } + return SemVer( + int.parse(match.group(1)!), + int.parse(match.group(2)!), + int.parse(match.group(3)!), + pre == null || pre.isEmpty ? const [] : pre.split('.'), + ); +} + +/// `2026.07.24` -> `2026.7.24`, `2026.07` -> `2026.7.0`, `2026` -> `2026.0.0`. +/// Leading zeros are stripped (semver forbids them) and 1–3 numeric segments are +/// padded. An optional `-prerelease` suffix survives. Null if not calendar-like. +String? normalizeCalver(String raw) { + var input = raw.startsWith('v') ? raw.substring(1) : raw; + String? pre; + final dash = input.indexOf('-'); + if (dash > 0 && dash < input.length - 1) { + pre = input.substring(dash + 1); + input = input.substring(0, dash); + } + final parts = []; + for (final segment in input.split('.')) { + if (segment.isEmpty || !segment.split('').every((c) => '0123456789'.contains(c))) { + return null; + } + final value = int.tryParse(segment); + if (value == null) return null; + parts.add(value); + } + if (parts.isEmpty || parts.length > 3) return null; + while (parts.length < 3) { + parts.add(0); + } + final core = '${parts[0]}.${parts[1]}.${parts[2]}'; + return pre == null ? core : '$core-$pre'; +} + +/// Drop Go's `+incompatible` (and any build metadata) from a bare Go tag. +String? _normalizeGo(String raw) { + final input = raw.startsWith('v') ? raw.substring(1) : raw; + final core = input.split('+').first; + return _parseStrict(core) == null ? null : core; +} + +const _pep440Labels = { + 'a': (label: 'alpha', prerelease: true), + 'alpha': (label: 'alpha', prerelease: true), + 'b': (label: 'beta', prerelease: true), + 'beta': (label: 'beta', prerelease: true), + 'c': (label: 'rc', prerelease: true), + 'rc': (label: 'rc', prerelease: true), + 'pre': (label: 'rc', prerelease: true), + 'preview': (label: 'rc', prerelease: true), + 'dev': (label: 'dev', prerelease: true), + 'post': (label: 'post', prerelease: false), + 'rev': (label: 'post', prerelease: false), + 'r': (label: 'post', prerelease: false), +}; + +/// `1.2.3rc1` -> `1.2.3-rc.1`, `1.2a1` -> `1.2.0-alpha.1`, `1.2.3.post1` -> +/// `1.2.3+post.1` (semver has no "after the release" ordering). Conservative: +/// only the common shapes, null otherwise. +String? _normalizePep440(String raw) { + var input = (raw.startsWith('v') ? raw.substring(1) : raw).toLowerCase(); + final marker = input.indexOf(RegExp('[a-z]')); + if (marker < 0) return null; + var release = input.substring(0, marker); + final suffix = input.substring(marker); + while (release.endsWith('.')) { + release = release.substring(0, release.length - 1); + } + final nums = []; + for (final segment in release.split('.')) { + if (segment.isEmpty) continue; + final value = int.tryParse(segment); + if (value == null) return null; + nums.add(value); + } + if (nums.length > 3) return null; + while (nums.length < 3) { + nums.add(0); + } + final core = '${nums[0]}.${nums[1]}.${nums[2]}'; + + final digit = suffix.indexOf(RegExp(r'\d')); + final label = digit < 0 ? suffix : suffix.substring(0, digit); + final number = digit < 0 ? '0' : suffix.substring(digit); + if (int.tryParse(number) == null) return null; + final mapped = _pep440Labels[label]; + if (mapped == null) return null; + return mapped.prerelease + ? '$core-${mapped.label}.$number' + : '$core+${mapped.label}.$number'; +} + +/// Parse a published version string, tolerating the foreign spellings zed +/// federates: a bare `v` prefix, calendar versions, Go's `+incompatible`, and a +/// subset of PEP 440. Null for a genuinely opaque tag. +SemVer? parseVersion(String raw) { + final direct = _parseStrict(raw); + if (direct != null) return direct; + if (raw.startsWith('v')) { + final stripped = _parseStrict(raw.substring(1)); + if (stripped != null) return stripped; + } + for (final normalize in [_normalizeGo, normalizeCalver, _normalizePep440]) { + final normalized = normalize(raw); + if (normalized != null) { + final parsed = _parseStrict(normalized.split('+').first); + if (parsed != null) return parsed; + } + } + return null; +} + +/// One `` bound. +class Comparator { + const Comparator(this.op, this.version); + + final String op; + final SemVer version; + + bool matches(SemVer candidate) { + final ordering = candidate.compareTo(version); + return switch (op) { + '=' => ordering == 0, + '>' => ordering > 0, + '>=' => ordering >= 0, + '<' => ordering < 0, + '<=' => ordering <= 0, + _ => false, + }; + } + + @override + String toString() => '$op$version'; +} + +/// A requirement is either a range (semver algebra) or an exact tag. An opaque +/// package's requirement is always the latter. +sealed class Requirement { + const Requirement(); + + /// Parse in **Cargo's dialect**: a bare `1.2.3` is a caret range, and only + /// `=1.2.3` pins one version. Anything that is not a legible range becomes an + /// exact tag, which is how opaque versions are requested. + factory Requirement.parse(String input) { + final comparators = _parseComparators(input); + return comparators == null + ? ExactRequirement(input) + : RangeRequirement(comparators); + } + + bool matches(String version); +} + +class ExactRequirement extends Requirement { + const ExactRequirement(this.tag); + + final String tag; + + @override + bool matches(String version) => version == tag; +} + +class RangeRequirement extends Requirement { + const RangeRequirement(this.comparators); + + final List comparators; + + @override + bool matches(String version) { + final parsed = parseVersion(version); + if (parsed == null) return false; + return comparators.every((c) => c.matches(parsed)); + } +} + +/// Does this string *look* like a range? Used to tell a typo (`^1.x.y`) from a +/// legitimate opaque tag (`legacy-api`), which is the difference between an +/// invalid requirement and one that simply matches nothing. +bool looksLikeRange(String input) => + input.startsWith(RegExp(r'[\^~><=]')) || + input.contains('*') || + input.contains(',') || + input.trim().split(RegExp(r'\s+')).length > 1; + +/// Split a numeric-ish version into 1–3 parts plus an optional prerelease, +/// so `1.2` and `2026` can expand into full bounds. +({List parts, List pre})? _partial(String raw) { + var input = raw.startsWith('v') ? raw.substring(1) : raw; + input = input.split('+').first; + List pre = const []; + final dash = input.indexOf('-'); + if (dash > 0 && dash < input.length - 1) { + pre = input.substring(dash + 1).split('.'); + input = input.substring(0, dash); + } + if (input.isEmpty) return null; + final parts = []; + for (final segment in input.split('.')) { + // `1.*` and `1.x` mean "unbounded from here"; stop and let the caller + // widen, exactly as a missing segment would. + if (segment == '*' || segment == 'x' || segment == 'X') break; + final value = int.tryParse(segment); + if (value == null) return null; + parts.add(value); + } + if (parts.isEmpty || parts.length > 3) return null; + return (parts: parts, pre: pre); +} + +SemVer _atLeast(List parts, List pre) => SemVer( + parts[0], + parts.length > 1 ? parts[1] : 0, + parts.length > 2 ? parts[2] : 0, + pre, +); + +/// Cargo's caret: the upper bound is the next version that changes the +/// left-most non-zero segment. `^0.2.3` is `<0.3.0`, `^0.0.3` is `<0.0.4`. +SemVer _caretUpper(List parts) { + if (parts[0] != 0) return SemVer(parts[0] + 1, 0, 0); + if (parts.length == 1) return const SemVer(1, 0, 0); + if (parts[1] != 0) return SemVer(0, parts[1] + 1, 0); + if (parts.length == 2) return const SemVer(0, 1, 0); + if (parts[2] != 0) return SemVer(0, 0, parts[2] + 1); + return const SemVer(0, 0, 1); +} + +/// Cargo's tilde: only the last specified segment may grow. +SemVer _tildeUpper(List parts) => switch (parts.length) { + 1 => SemVer(parts[0] + 1, 0, 0), + _ => SemVer(parts[0], parts[1] + 1, 0), +}; + +List? _parseComparators(String input) { + final trimmed = input.trim(); + if (trimmed.isEmpty) return null; + if (trimmed == '*') return const []; + + final comparators = []; + for (final token in trimmed.split(RegExp(r'\s*,\s*|\s+'))) { + if (token.isEmpty) continue; + final expanded = _expand(token); + if (expanded == null) return null; + comparators.addAll(expanded); + } + return comparators.isEmpty ? null : comparators; +} + +List? _expand(String token) { + if (token == '*') return const []; + + final match = RegExp(r'^(\^|~|>=|<=|>|<|=)?\s*(.+)$').firstMatch(token); + if (match == null) return null; + final op = match.group(1) ?? '^'; // Cargo: a bare version is a caret range. + final rest = match.group(2)!.trim(); + final partial = _partial(rest); + if (partial == null) return null; + final parts = partial.parts; + final pre = partial.pre; + + switch (op) { + case '^': + return [ + Comparator('>=', _atLeast(parts, pre)), + Comparator('<', _caretUpper(parts)), + ]; + case '~': + return [ + Comparator('>=', _atLeast(parts, pre)), + Comparator('<', _tildeUpper(parts)), + ]; + case '=': + // `=1.2` is not "exactly 1.2.0" in Cargo, it is the 1.2.x line. + if (parts.length == 3) return [Comparator('=', _atLeast(parts, pre))]; + return [ + Comparator('>=', _atLeast(parts, pre)), + Comparator('<', _tildeUpper(parts)), + ]; + default: + return [Comparator(op, _atLeast(parts, pre))]; + } +} + +/// Pick the version satisfying `requirement`, returned in its **published +/// spelling** so the store address and VCS tag stay faithful to the tag the +/// publisher pushed. Prereleases never satisfy a range. +String? resolve(Requirement requirement, List versions) { + switch (requirement) { + case ExactRequirement(:final tag): + for (final version in versions) { + if (version == tag) return version; + } + return null; + case RangeRequirement(): + String? best; + SemVer? bestParsed; + for (final version in versions) { + final parsed = parseVersion(version); + if (parsed == null || !parsed.isStable) continue; + if (!requirement.matches(version)) continue; + if (bestParsed == null || parsed.compareTo(bestParsed) > 0) { + best = version; + bestParsed = parsed; + } + } + return best; + } +} From c0b79e02775dda6fd5d79c7ce8ee0ecd6c3b1fa3 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:14 -0500 Subject: [PATCH 02/38] claude autosave 2026-08-07T03:38:14Z --- src/dart/lib/src/resolve.dart | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/dart/lib/src/resolve.dart diff --git a/src/dart/lib/src/resolve.dart b/src/dart/lib/src/resolve.dart new file mode 100644 index 0000000..f265d3e --- /dev/null +++ b/src/dart/lib/src/resolve.dart @@ -0,0 +1,118 @@ +/// Scheme-aware resolution against registry metadata — the Dart mirror of +/// `zed_lib::resolve` (Rust), verified against the same corpus. +library; + +import 'package:zed_interfaces/package_metadata.dart'; + +import 'version.dart'; + +/// Why a requirement did not resolve. The three cases need different fixes, so +/// they stay distinct rather than collapsing into null. +enum ResolveErrorKind { + /// The registry knows the package but it has no installable versions. + noVersions('no_versions'), + + /// The requirement cannot mean anything for this package's scheme. + invalidRequirement('invalid_requirement'), + + /// A well-formed requirement that nothing published satisfies. + unsatisfied('unsatisfied'); + + const ResolveErrorKind(this.wire); + + /// Stable string shared with the conformance corpus and the other + /// implementations. Renaming one breaks every consumer that matches on it. + final String wire; +} + +class ResolveException implements Exception { + ResolveException(this.kind, this.message); + + final ResolveErrorKind kind; + final String message; + + @override + String toString() => message; +} + +/// The scheme a package declared, defaulting to semver. +/// +/// `PackageMetadata.versionScheme` is nullable because the field carries a +/// serde default and the server omits it for the common case — absent means +/// semver, not "unknown". +VersionScheme schemeOf(PackageMetadata metadata) => + metadata.versionScheme ?? VersionScheme.semver; + +/// Resolve `requirement` against what the registry says a package published. +/// +/// Returns the version in its published spelling. Under [VersionScheme.opaque] +/// the requirement must be an exact tag: those packages have no ordering, so +/// `^1.0` is not "everything 1.x", it is a mistake that would otherwise resolve +/// through semver algebra by accident. +String resolveVersion(PackageMetadata metadata, String requirement) { + final id = '${metadata.org}/${metadata.name}'; + + if (metadata.versions.isEmpty) { + throw ResolveException( + ResolveErrorKind.noVersions, + '$id has no published versions', + ); + } + + final scheme = schemeOf(metadata); + final parsed = Requirement.parse(requirement); + + if (scheme == VersionScheme.opaque && parsed is RangeRequirement) { + throw ResolveException( + ResolveErrorKind.invalidRequirement, + '`$requirement` is not a valid requirement for $id: opaque-versioned ' + 'packages have no range algebra; require an exact tag', + ); + } + + // A range that *looks* like one but does not parse (`^1.x.y`) would degrade + // into an exact tag and never match. Catch it as the typo it is. + if (scheme != VersionScheme.opaque && + parsed is ExactRequirement && + looksLikeRange(requirement)) { + throw ResolveException( + ResolveErrorKind.invalidRequirement, + '`$requirement` is not a valid requirement for $id: looks like a version ' + 'range but is not a valid one', + ); + } + + final resolved = resolve(parsed, metadata.versions); + if (resolved == null) { + throw ResolveException( + ResolveErrorKind.unsatisfied, + '$id has no version matching `$requirement`; ' + 'published: ${metadata.versions.join(', ')}', + ); + } + return resolved; +} + +/// The newest installable version, ignoring prereleases. +/// +/// `PackageMetadata.latest` is what the registry computed when the package was +/// last published and can lag a yank, so this recomputes from the version list +/// the same response carried. +String? latestStable(PackageMetadata metadata) { + if (schemeOf(metadata) == VersionScheme.opaque) { + final latest = metadata.latest; + if (latest == null) return null; + return metadata.versions.contains(latest) ? latest : null; + } + String? best; + SemVer? bestParsed; + for (final version in metadata.versions) { + final parsed = parseVersion(version); + if (parsed == null || !parsed.isStable) continue; + if (bestParsed == null || parsed.compareTo(bestParsed) > 0) { + best = version; + bestParsed = parsed; + } + } + return best; +} From 9df9f37bad32772e0d4373bd908bdb54b5158637 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:22 -0500 Subject: [PATCH 03/38] claude autosave 2026-08-07T03:38:22Z --- src/dart/lib/zed_lib.dart | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/dart/lib/zed_lib.dart diff --git a/src/dart/lib/zed_lib.dart b/src/dart/lib/zed_lib.dart new file mode 100644 index 0000000..1a6a947 --- /dev/null +++ b/src/dart/lib/zed_lib.dart @@ -0,0 +1,23 @@ +/// Implementations of the zed-pkg contract, in Dart. +/// +/// The Dart slice of `zed-lib` exists so a Flutter or web client answers +/// "which version does `^1.2` install?" exactly the way `zed-cli` does. Both +/// run `conformance/cases/*.json`; a disagreement is a failing test rather than +/// a support ticket. +/// +/// Types come from `package:zed_interfaces`; this package adds only behavior. +library; + +export 'src/resolve.dart' + show ResolveErrorKind, ResolveException, latestStable, resolveVersion, schemeOf; +export 'src/version.dart' + show + Comparator, + ExactRequirement, + RangeRequirement, + Requirement, + SemVer, + looksLikeRange, + normalizeCalver, + parseVersion, + resolve; From 89822a7405f7eee0f654561435058be0f93cf5ca Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:26 -0500 Subject: [PATCH 04/38] claude autosave 2026-08-07T03:38:26Z --- src/dart/pubspec.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/dart/pubspec.yaml diff --git a/src/dart/pubspec.yaml b/src/dart/pubspec.yaml new file mode 100644 index 0000000..35add98 --- /dev/null +++ b/src/dart/pubspec.yaml @@ -0,0 +1,23 @@ +name: zed_lib +description: >- + Implementations of the zed-pkg interfaces in Dart — resolution and policy over + the shared contract types, verified against the cross-language corpus. +version: 0.1.0 +# Published as a zed-package ([targets.dart] in ../../.zpkg.toml) and mirrored +# to pub.dev from there. +publish_to: none +repository: https://github.com/zed-pkg/zed-lib + +environment: + sdk: ^3.0.0 + +dependencies: + # Shapes come from the generated interfaces slice; this package adds only + # behavior. A sibling checkout until zed-interfaces publishes to pub.dev, + # matching how the Rust slice depends on it. + zed_interfaces: + path: ../../../zed-interfaces/src/dart + +dev_dependencies: + lints: ^4.0.0 + test: ^1.25.0 From 13b85cb867989a2e127612ec08d93495849f8bdc Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:37 -0500 Subject: [PATCH 05/38] claude autosave 2026-08-07T03:38:37Z --- src/dart/test/conformance_test.dart | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/dart/test/conformance_test.dart diff --git a/src/dart/test/conformance_test.dart b/src/dart/test/conformance_test.dart new file mode 100644 index 0000000..e14d95d --- /dev/null +++ b/src/dart/test/conformance_test.dart @@ -0,0 +1,66 @@ +// Runs the shared conformance corpus against the Dart implementation. The Rust +// slice runs the same file; a case that passes in one language and fails in the +// other is the drift this repository exists to catch. + +import 'dart:convert'; +import 'dart:io'; + +import 'package:test/test.dart'; +import 'package:zed_interfaces/package_metadata.dart'; +import 'package:zed_lib/zed_lib.dart'; + +const _corpusPath = '../../conformance/cases/version-resolution.json'; + +PackageMetadata metadataFor(String scheme, List versions) => + PackageMetadata( + org: 'acme', + name: 'conformance', + vcs: Vcs.git, + repoUrl: 'https://github.com/acme/conformance', + latest: versions.isEmpty ? null : versions.last, + versions: versions, + versionScheme: switch (scheme) { + 'calver' => VersionScheme.calver, + 'opaque' => VersionScheme.opaque, + _ => VersionScheme.semver, + }, + ); + +void main() { + final raw = File(_corpusPath).readAsStringSync(); + final corpus = jsonDecode(raw) as Map; + final cases = (corpus['cases'] as List).cast>(); + + test('the corpus is not empty', () => expect(cases, isNotEmpty)); + + for (final testCase in cases) { + final name = testCase['name'] as String; + final metadata = metadataFor( + testCase['scheme'] as String, + (testCase['versions'] as List).cast(), + ); + final requirement = testCase['requirement'] as String; + final expected = testCase['expect'] as Map; + + test(name, () { + final wantVersion = expected['version'] as String?; + final wantError = expected['error'] as String?; + expect( + (wantVersion == null) != (wantError == null), + isTrue, + reason: 'a case declares exactly one of `version` or `error`', + ); + + if (wantVersion != null) { + expect(resolveVersion(metadata, requirement), wantVersion); + } else { + try { + final resolved = resolveVersion(metadata, requirement); + fail('expected $wantError, resolved $resolved'); + } on ResolveException catch (error) { + expect(error.kind.wire, wantError); + } + } + }); + } +} From 440fa9a99232de0bd7bd43cefccc247e50c55c40 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:40 -0500 Subject: [PATCH 06/38] claude autosave 2026-08-07T03:38:40Z --- src/dart/analysis_options.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/dart/analysis_options.yaml diff --git a/src/dart/analysis_options.yaml b/src/dart/analysis_options.yaml new file mode 100644 index 0000000..8c2a77b --- /dev/null +++ b/src/dart/analysis_options.yaml @@ -0,0 +1,19 @@ +include: package:lints/recommended.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + errors: + # This package is one of three implementations of the same behavior. + # Anything that can silently change behavior is an error, not a hint. + unused_import: error + unused_local_variable: error + dead_code: error + +linter: + rules: + - always_declare_return_types + - prefer_final_locals + - unnecessary_parenthesis From 9353ef4877e2daea9cf396767e2f7003968f620f Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:38:52 -0500 Subject: [PATCH 07/38] claude autosave 2026-08-07T03:38:52Z --- src/dart/lib/src/version.dart | 2 +- src/dart/pubspec.lock | 396 ++++++++++++++++++++++++++++++++++ 2 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 src/dart/pubspec.lock diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index 2b0bb67..ee9534e 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -148,7 +148,7 @@ const _pep440Labels = { /// `1.2.3+post.1` (semver has no "after the release" ordering). Conservative: /// only the common shapes, null otherwise. String? _normalizePep440(String raw) { - var input = (raw.startsWith('v') ? raw.substring(1) : raw).toLowerCase(); + final input = (raw.startsWith('v') ? raw.substring(1) : raw).toLowerCase(); final marker = input.indexOf(RegExp('[a-z]')); if (marker < 0) return null; var release = input.substring(0, marker); diff --git a/src/dart/pubspec.lock b/src/dart/pubspec.lock new file mode 100644 index 0000000..7f05074 --- /dev/null +++ b/src/dart/pubspec.lock @@ -0,0 +1,396 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "9a3386eea899815698dd55995277cf7cb8572ee52b399a6edfb7ae2b50e5fc19" + url: "https://pub.dev" + source: hosted + version: "105.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "62993bed6eadbe9596c5c20d5c167e7bc563c5fe266657a04ddeb93bdb84f4c9" + url: "https://pub.dev" + source: hosted + version: "14.1.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d" + url: "https://pub.dev" + source: hosted + version: "1.15.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" + url: "https://pub.dev" + source: hosted + version: "0.12.20" + meta: + dependency: transitive + description: + name: meta + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" + url: "https://pub.dev" + source: hosted + version: "1.19.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d + url: "https://pub.dev" + source: hosted + version: "3.0.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: "direct dev" + description: + name: test + sha256: "0d5ba5602ec3baa28c8ce365e1efc5575969c765f45c554a3e167dc7945b9c30" + url: "https://pub.dev" + source: hosted + version: "1.31.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "475610b2aa23c19687cce2961e44b0cc57cafe220f67c2b80201231b2a07fbe7" + url: "https://pub.dev" + source: hosted + version: "0.7.13" + test_core: + dependency: transitive + description: + name: test_core + sha256: a39c204a4fc7a7ccb04a2b985e359fda3cc37e45e0b8ac61c3fb1a05aa832132 + url: "https://pub.dev" + source: hosted + version: "0.6.19" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + url: "https://pub.dev" + source: hosted + version: "15.2.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" + zed_interfaces: + dependency: "direct main" + description: + path: "../../../zed-interfaces/src/dart" + relative: true + source: path + version: "0.1.0" +sdks: + dart: ">=3.11.0 <4.0.0" From 38ef8ca9c547f99c7b48a2f2988fcd8082767b1e Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:39:28 -0500 Subject: [PATCH 08/38] claude autosave 2026-08-07T03:39:28Z --- src/dart/lib/src/version.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index ee9534e..85cf100 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -286,9 +286,10 @@ bool looksLikeRange(String input) => if (input.isEmpty) return null; final parts = []; for (final segment in input.split('.')) { - // `1.*` and `1.x` mean "unbounded from here"; stop and let the caller - // widen, exactly as a missing segment would. - if (segment == '*' || segment == 'x' || segment == 'X') break; + // `1.*` means "unbounded from here"; stop and let the caller widen, + // exactly as a missing segment would. `x`/`X` are npm's spelling, not + // Cargo's — `1.x` is an opaque tag here, and `^1.x.y` is a typo. + if (segment == '*') break; final value = int.tryParse(segment); if (value == null) return null; parts.add(value); From 0862cdfc4bc6fab2b5909bc90d3c20a4baed8cf7 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:39:38 -0500 Subject: [PATCH 09/38] claude autosave 2026-08-07T03:39:38Z --- conformance/cases/version-resolution.json | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/conformance/cases/version-resolution.json b/conformance/cases/version-resolution.json index dbdee0e..aafc0cc 100644 --- a/conformance/cases/version-resolution.json +++ b/conformance/cases/version-resolution.json @@ -58,6 +58,41 @@ "requirement": "^1.x.y", "expect": { "error": "invalid_requirement" } }, + { + "name": "`*` is the wildcard in this dialect", + "scheme": "semver", + "versions": ["1.0.0", "1.9.0", "2.0.0"], + "requirement": "1.*", + "expect": { "version": "1.9.0" } + }, + { + "name": "`x` is npm's wildcard, not this dialect's — it is an opaque tag", + "scheme": "semver", + "versions": ["1.0.0", "1.9.0"], + "requirement": "1.x", + "expect": { "error": "unsatisfied" } + }, + { + "name": "a `v`-prefixed Go tag resolves through the same range", + "scheme": "semver", + "versions": ["v1.0.0", "v1.4.0"], + "requirement": "^1.2", + "expect": { "version": "v1.4.0" } + }, + { + "name": "Go's +incompatible does not change identity", + "scheme": "semver", + "versions": ["v2.0.0+incompatible"], + "requirement": "^2", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "a PEP 440 prerelease is still a prerelease", + "scheme": "semver", + "versions": ["1.2.3rc1", "1.2.2"], + "requirement": "^1.2", + "expect": { "version": "1.2.2" } + }, { "name": "npm-style whitespace ranges are accepted", "scheme": "semver", From e6904afa81144c7845c22551d679df5d94a54c27 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:40:56 -0500 Subject: [PATCH 10/38] claude autosave 2026-08-07T03:40:56Z --- Cargo.lock | 1 + src/dart/lib/src/version.dart | 31 +++++++++++++++++++++---------- src/rust/Cargo.toml | 1 + src/rust/examples/probe.rs | 11 +++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/rust/examples/probe.rs diff --git a/Cargo.lock b/Cargo.lock index b64b9fc..0898619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -367,6 +367,7 @@ dependencies = [ name = "zed-lib" version = "0.1.0" dependencies = [ + "semver", "serde", "serde_json", "thiserror", diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index 85cf100..41a7696 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -272,9 +272,14 @@ bool looksLikeRange(String input) => input.contains(',') || input.trim().split(RegExp(r'\s+')).length > 1; -/// Split a numeric-ish version into 1–3 parts plus an optional prerelease, -/// so `1.2` and `2026` can expand into full bounds. -({List parts, List pre})? _partial(String raw) { +/// Split a numeric-ish version into 1–3 parts plus an optional prerelease, so +/// `1.2` and `2026` can expand into full bounds. +/// +/// `*`, `x`, and `X` are all wildcards, and a wildcard must be the **last** +/// segment — `1.x.y` is an error, not `1.x`. That is the rule Cargo's `semver` +/// enforces ("unexpected character after wildcard"), and it is why `^1.x.y` is +/// an invalid requirement rather than a very wide one. +({List parts, List pre, bool wildcard})? _partial(String raw) { var input = raw.startsWith('v') ? raw.substring(1) : raw; input = input.split('+').first; List pre = const []; @@ -285,17 +290,23 @@ bool looksLikeRange(String input) => } if (input.isEmpty) return null; final parts = []; - for (final segment in input.split('.')) { - // `1.*` means "unbounded from here"; stop and let the caller widen, - // exactly as a missing segment would. `x`/`X` are npm's spelling, not - // Cargo's — `1.x` is an opaque tag here, and `^1.x.y` is a typo. - if (segment == '*') break; + var wildcard = false; + final segments = input.split('.'); + for (var i = 0; i < segments.length; i++) { + final segment = segments[i]; + if (segment == '*' || segment == 'x' || segment == 'X') { + if (i != segments.length - 1 || parts.length >= 3) return null; + wildcard = true; + break; + } final value = int.tryParse(segment); if (value == null) return null; parts.add(value); } - if (parts.isEmpty || parts.length > 3) return null; - return (parts: parts, pre: pre); + if (parts.length > 3) return null; + // A bare `*` constrains nothing; anything else needs at least one number. + if (parts.isEmpty && !wildcard) return null; + return (parts: parts, pre: pre, wildcard: wildcard); } SemVer _atLeast(List parts, List pre) => SemVer( diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index df6c3d6..11dd038 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -18,6 +18,7 @@ path = "lib.rs" # publishes 0.1.0 to the registry. zed-interfaces = { path = "../../../zed-interfaces/src/rust" } thiserror = "2.0.19" +semver = "1.0.28" [dev-dependencies] serde = { version = "1.0.229", features = ["derive"] } diff --git a/src/rust/examples/probe.rs b/src/rust/examples/probe.rs new file mode 100644 index 0000000..64afa82 --- /dev/null +++ b/src/rust/examples/probe.rs @@ -0,0 +1,11 @@ +fn main() { + for input in [ + "1.x", "1.X", "1.*", "^1.x", "^1.*", "^1.x.y", "1.x.y", "1.2.x", "*", "1.2.*", + "^1.2.*", "x", "1.2.3.x", ">=1.x", "1.x.3", + ] { + match semver::VersionReq::parse(input) { + Ok(r) => println!("{:<10} OK -> {r}", input), + Err(e) => println!("{:<10} ERR -> {e}", input), + } + } +} From a9003ee95e3c863cc594031cdc505830b56e47c3 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:41:14 -0500 Subject: [PATCH 11/38] claude autosave 2026-08-07T03:41:13Z --- src/dart/lib/src/version.dart | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index 41a7696..7fdd1e6 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -336,30 +336,44 @@ SemVer _tildeUpper(List parts) => switch (parts.length) { List? _parseComparators(String input) { final trimmed = input.trim(); if (trimmed.isEmpty) return null; - if (trimmed == '*') return const []; final comparators = []; + var sawToken = false; for (final token in trimmed.split(RegExp(r'\s*,\s*|\s+'))) { if (token.isEmpty) continue; final expanded = _expand(token); if (expanded == null) return null; + sawToken = true; comparators.addAll(expanded); } - return comparators.isEmpty ? null : comparators; + // `*` is a legitimate range that constrains nothing, so emptiness cannot + // double as the failure signal. + return sawToken ? comparators : null; } List? _expand(String token) { - if (token == '*') return const []; - final match = RegExp(r'^(\^|~|>=|<=|>|<|=)?\s*(.+)$').firstMatch(token); if (match == null) return null; - final op = match.group(1) ?? '^'; // Cargo: a bare version is a caret range. + final explicitOp = match.group(1); + final op = explicitOp ?? '^'; // Cargo: a bare version is a caret range. final rest = match.group(2)!.trim(); final partial = _partial(rest); if (partial == null) return null; final parts = partial.parts; final pre = partial.pre; + if (parts.isEmpty) return const []; // bare `*`/`x`: matches anything + + // An explicit wildcard binds tighter than an omitted segment: `1.2` is + // `^1.2` (< 2.0.0), but `1.2.*` is the 1.2 line (< 1.3.0). With an operator + // the wildcard is just the segments the author left off (`^1.*` == `^1`). + if (partial.wildcard && explicitOp == null) { + return [ + Comparator('>=', _atLeast(parts, pre)), + Comparator('<', _tildeUpper(parts)), + ]; + } + switch (op) { case '^': return [ @@ -372,7 +386,7 @@ List? _expand(String token) { Comparator('<', _tildeUpper(parts)), ]; case '=': - // `=1.2` is not "exactly 1.2.0" in Cargo, it is the 1.2.x line. + // `=1.2` is not "exactly 1.2.0" in Cargo, it is the 1.2 line. if (parts.length == 3) return [Comparator('=', _atLeast(parts, pre))]; return [ Comparator('>=', _atLeast(parts, pre)), From 5391654a8fb8c3597ec6ae2e82504284cf38eb20 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:41:35 -0500 Subject: [PATCH 12/38] claude autosave 2026-08-07T03:41:35Z --- conformance/cases/version-resolution.json | 29 +++++++++++++++++++---- src/rust/examples/probe.rs | 16 ++++++------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/conformance/cases/version-resolution.json b/conformance/cases/version-resolution.json index aafc0cc..086f46e 100644 --- a/conformance/cases/version-resolution.json +++ b/conformance/cases/version-resolution.json @@ -59,17 +59,38 @@ "expect": { "error": "invalid_requirement" } }, { - "name": "`*` is the wildcard in this dialect", + "name": "an explicit wildcard binds tighter than an omitted segment", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"], + "requirement": "1.2.*", + "expect": { "version": "1.2.9" } + }, + { + "name": "the same requirement with the segment omitted is a caret range", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"], + "requirement": "1.2", + "expect": { "version": "1.9.0" } + }, + { + "name": "`x` and `X` are wildcards too, not opaque tags", "scheme": "semver", "versions": ["1.0.0", "1.9.0", "2.0.0"], - "requirement": "1.*", + "requirement": "1.x", "expect": { "version": "1.9.0" } }, { - "name": "`x` is npm's wildcard, not this dialect's — it is an opaque tag", + "name": "a bare wildcard matches the newest stable version", + "scheme": "semver", + "versions": ["1.0.0", "2.0.0", "2.1.0-rc.1"], + "requirement": "*", + "expect": { "version": "2.0.0" } + }, + { + "name": "KNOWN GAP: a wildcard typo with no operator degrades to an opaque tag", "scheme": "semver", "versions": ["1.0.0", "1.9.0"], - "requirement": "1.x", + "requirement": "1.x.y", "expect": { "error": "unsatisfied" } }, { diff --git a/src/rust/examples/probe.rs b/src/rust/examples/probe.rs index 64afa82..1a543e2 100644 --- a/src/rust/examples/probe.rs +++ b/src/rust/examples/probe.rs @@ -1,11 +1,11 @@ +use zed_interfaces::version::{Requirement, resolve}; fn main() { - for input in [ - "1.x", "1.X", "1.*", "^1.x", "^1.*", "^1.x.y", "1.x.y", "1.2.x", "*", "1.2.*", - "^1.2.*", "x", "1.2.3.x", ">=1.x", "1.x.3", - ] { - match semver::VersionReq::parse(input) { - Ok(r) => println!("{:<10} OK -> {r}", input), - Err(e) => println!("{:<10} ERR -> {e}", input), - } + let versions: Vec = ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"] + .iter().map(|s| s.to_string()).collect(); + for input in ["1.*", "1.2.*", "1.2", "1.x", "1.x.y", "*", "^1.2", "~1.2"] { + let req = Requirement::parse(input); + let picked = resolve(&req, &versions); + let valid = Requirement::validate(input); + println!("{:<8} -> {:<10?} validate={:?}", input, picked, valid.is_ok()); } } From 30caf74250e488ab0debdc24b6c7ba875518b963 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:42:35 -0500 Subject: [PATCH 13/38] claude autosave 2026-08-07T03:42:35Z --- Cargo.lock | 1 - src/rust/Cargo.toml | 1 - src/rust/examples/probe.rs | 11 -- src/ts/version.ts | 382 +++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+), 13 deletions(-) delete mode 100644 src/rust/examples/probe.rs create mode 100644 src/ts/version.ts diff --git a/Cargo.lock b/Cargo.lock index 0898619..b64b9fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -367,7 +367,6 @@ dependencies = [ name = "zed-lib" version = "0.1.0" dependencies = [ - "semver", "serde", "serde_json", "thiserror", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 11dd038..df6c3d6 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -18,7 +18,6 @@ path = "lib.rs" # publishes 0.1.0 to the registry. zed-interfaces = { path = "../../../zed-interfaces/src/rust" } thiserror = "2.0.19" -semver = "1.0.28" [dev-dependencies] serde = { version = "1.0.229", features = ["derive"] } diff --git a/src/rust/examples/probe.rs b/src/rust/examples/probe.rs deleted file mode 100644 index 1a543e2..0000000 --- a/src/rust/examples/probe.rs +++ /dev/null @@ -1,11 +0,0 @@ -use zed_interfaces::version::{Requirement, resolve}; -fn main() { - let versions: Vec = ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"] - .iter().map(|s| s.to_string()).collect(); - for input in ["1.*", "1.2.*", "1.2", "1.x", "1.x.y", "*", "^1.2", "~1.2"] { - let req = Requirement::parse(input); - let picked = resolve(&req, &versions); - let valid = Requirement::validate(input); - println!("{:<8} -> {:<10?} validate={:?}", input, picked, valid.is_ok()); - } -} diff --git a/src/ts/version.ts b/src/ts/version.ts new file mode 100644 index 0000000..851f46d --- /dev/null +++ b/src/ts/version.ts @@ -0,0 +1,382 @@ +// Version parsing, comparison, and requirement matching — the TypeScript +// mirror of `zed_interfaces::version` (Rust). +// +// Deliberately dependency-free. The npm `semver` package looks like the +// obvious answer, but its dialect differs from Cargo's exactly where it hurts: +// a bare `1.0.0` is an *exact* constraint there and a caret range in Cargo, and +// `1.2` means the 1.2 line rather than `^1.2`. Three implementations of one +// contract cannot afford a translation layer whose edge cases nobody reads — +// so the algebra is written out, and the shared corpus proves it agrees. + +/** A parsed semantic version. Build metadata is dropped: semver precedence + * ignores it, so `2.0.0+incompatible` and `2.0.0` are one identity. */ +export interface SemVer { + readonly major: number; + readonly minor: number; + readonly patch: number; + /** Dot-separated prerelease identifiers; empty for a stable release. */ + readonly pre: readonly string[]; +} + +export const isStable = (version: SemVer): boolean => version.pre.length === 0; + +/** Semver §11: a prerelease is lower than the release it precedes; numeric + * identifiers order numerically and rank below alphanumeric ones; when one set + * is a prefix of the other, the longer set is higher. */ +function comparePre(a: readonly string[], b: readonly string[]): number { + if (a.length === 0 && b.length === 0) return 0; + if (a.length === 0) return 1; + if (b.length === 0) return -1; + for (let i = 0; i < a.length && i < b.length; i++) { + const left = a[i] as string; + const right = b[i] as string; + const leftNum = /^\d+$/.test(left) ? Number(left) : null; + const rightNum = /^\d+$/.test(right) ? Number(right) : null; + let ordering: number; + if (leftNum !== null && rightNum !== null) ordering = leftNum - rightNum; + else if (leftNum !== null) ordering = -1; + else if (rightNum !== null) ordering = 1; + else ordering = left < right ? -1 : left > right ? 1 : 0; + if (ordering !== 0) return ordering; + } + return a.length - b.length; +} + +export function compareVersions(a: SemVer, b: SemVer): number { + return ( + a.major - b.major || + a.minor - b.minor || + a.patch - b.patch || + comparePre(a.pre, b.pre) + ); +} + +const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/; + +function parseStrict(raw: string): SemVer | null { + const match = SEMVER_RE.exec(raw); + if (!match) return null; + const [, major, minor, patch, pre] = match as unknown as [string, string, string, string, string | undefined]; + // Leading zeros are illegal in semver numeric identifiers; calendar versions + // hit this constantly (`2026.06.01`) and are normalized separately. + for (const segment of [major, minor, patch]) { + if (segment.length > 1 && segment.startsWith("0")) return null; + } + return { + major: Number(major), + minor: Number(minor), + patch: Number(patch), + pre: pre ? pre.split(".") : [], + }; +} + +/** `2026.07.24` -> `2026.7.24`, `2026.07` -> `2026.7.0`, `2026` -> `2026.0.0`. + * Leading zeros stripped (semver forbids them), 1–3 numeric segments padded, + * an optional `-prerelease` suffix preserved. Null if not calendar-like. */ +export function normalizeCalver(raw: string): string | null { + let input = raw.startsWith("v") ? raw.slice(1) : raw; + let pre: string | null = null; + const dash = input.indexOf("-"); + if (dash > 0 && dash < input.length - 1) { + pre = input.slice(dash + 1); + input = input.slice(0, dash); + } + const parts: number[] = []; + for (const segment of input.split(".")) { + if (!/^\d+$/.test(segment)) return null; + parts.push(Number(segment)); + } + if (parts.length === 0 || parts.length > 3) return null; + while (parts.length < 3) parts.push(0); + const core = `${parts[0]}.${parts[1]}.${parts[2]}`; + return pre === null ? core : `${core}-${pre}`; +} + +/** Drop Go's `+incompatible` (and any build metadata) from a bare Go tag. */ +function normalizeGo(raw: string): string | null { + const input = raw.startsWith("v") ? raw.slice(1) : raw; + const core = input.split("+")[0] as string; + return parseStrict(core) === null ? null : core; +} + +const PEP440_LABELS: Record = { + a: { label: "alpha", prerelease: true }, + alpha: { label: "alpha", prerelease: true }, + b: { label: "beta", prerelease: true }, + beta: { label: "beta", prerelease: true }, + c: { label: "rc", prerelease: true }, + rc: { label: "rc", prerelease: true }, + pre: { label: "rc", prerelease: true }, + preview: { label: "rc", prerelease: true }, + dev: { label: "dev", prerelease: true }, + post: { label: "post", prerelease: false }, + rev: { label: "post", prerelease: false }, + r: { label: "post", prerelease: false }, +}; + +/** `1.2.3rc1` -> `1.2.3-rc.1`, `1.2a1` -> `1.2.0-alpha.1`, `1.2.3.post1` -> + * `1.2.3+post.1` (semver has no "after the release" ordering). Conservative: + * only the common shapes, null otherwise. */ +function normalizePep440(raw: string): string | null { + const input = (raw.startsWith("v") ? raw.slice(1) : raw).toLowerCase(); + const marker = input.search(/[a-z]/); + if (marker < 0) return null; + const release = input.slice(0, marker).replace(/\.+$/, ""); + const suffix = input.slice(marker); + const nums: number[] = []; + for (const segment of release.split(".")) { + if (segment === "") continue; + if (!/^\d+$/.test(segment)) return null; + nums.push(Number(segment)); + } + if (nums.length > 3) return null; + while (nums.length < 3) nums.push(0); + const core = `${nums[0]}.${nums[1]}.${nums[2]}`; + + const digit = suffix.search(/\d/); + const label = digit < 0 ? suffix : suffix.slice(0, digit); + const num = digit < 0 ? "0" : suffix.slice(digit); + if (!/^\d+$/.test(num)) return null; + const mapped = PEP440_LABELS[label]; + if (!mapped) return null; + return mapped.prerelease ? `${core}-${mapped.label}.${num}` : `${core}+${mapped.label}.${num}`; +} + +/** Parse a published version string, tolerating the foreign spellings zed + * federates: a bare `v` prefix, calendar versions, Go's `+incompatible`, and a + * subset of PEP 440. Null for a genuinely opaque tag. */ +export function parseVersion(raw: string): SemVer | null { + const direct = parseStrict(raw); + if (direct) return direct; + if (raw.startsWith("v")) { + const stripped = parseStrict(raw.slice(1)); + if (stripped) return stripped; + } + for (const normalize of [normalizeGo, normalizeCalver, normalizePep440]) { + const normalized = normalize(raw); + if (normalized !== null) { + const parsed = parseStrict(normalized.split("+")[0] as string); + if (parsed) return parsed; + } + } + return null; +} + +export type Op = "=" | ">" | ">=" | "<" | "<="; + +/** One `` bound. */ +export interface Comparator { + readonly op: Op; + readonly version: SemVer; +} + +function matchesComparator(comparator: Comparator, candidate: SemVer): boolean { + const ordering = compareVersions(candidate, comparator.version); + switch (comparator.op) { + case "=": + return ordering === 0; + case ">": + return ordering > 0; + case ">=": + return ordering >= 0; + case "<": + return ordering < 0; + case "<=": + return ordering <= 0; + } +} + +/** A requirement is either a range (semver algebra) or an exact tag. An opaque + * package's requirement is always the latter. */ +export type Requirement = + | { readonly kind: "range"; readonly comparators: readonly Comparator[] } + | { readonly kind: "exact"; readonly tag: string }; + +/** Does this string *look* like a range? Tells a typo (`^1.x.y`) from a + * legitimate opaque tag (`legacy-api`) — the difference between an invalid + * requirement and one that simply matches nothing. */ +export function looksLikeRange(input: string): boolean { + return ( + /^[\^~><=]/.test(input) || + input.includes("*") || + input.includes(",") || + input.trim().split(/\s+/).length > 1 + ); +} + +interface Partial { + readonly parts: readonly number[]; + readonly pre: readonly string[]; + readonly wildcard: boolean; +} + +/** Split a numeric-ish version into 1–3 parts plus an optional prerelease. + * + * `*`, `x`, and `X` are all wildcards, and a wildcard must be the **last** + * segment — `1.x.y` is an error, not `1.x`. That is the rule Cargo's `semver` + * enforces ("unexpected character after wildcard"), and it is why `^1.x.y` is + * an invalid requirement rather than a very wide one. */ +function partial(raw: string): Partial | null { + let input = raw.startsWith("v") ? raw.slice(1) : raw; + input = input.split("+")[0] as string; + let pre: string[] = []; + const dash = input.indexOf("-"); + if (dash > 0 && dash < input.length - 1) { + pre = input.slice(dash + 1).split("."); + input = input.slice(0, dash); + } + if (input === "") return null; + const parts: number[] = []; + let wildcard = false; + const segments = input.split("."); + for (let i = 0; i < segments.length; i++) { + const segment = segments[i] as string; + if (segment === "*" || segment === "x" || segment === "X") { + if (i !== segments.length - 1 || parts.length >= 3) return null; + wildcard = true; + break; + } + if (!/^\d+$/.test(segment)) return null; + parts.push(Number(segment)); + } + if (parts.length > 3) return null; + // A bare `*` constrains nothing; anything else needs at least one number. + if (parts.length === 0 && !wildcard) return null; + return { parts, pre, wildcard }; +} + +const atLeast = (parts: readonly number[], pre: readonly string[]): SemVer => ({ + major: parts[0] as number, + minor: parts.length > 1 ? (parts[1] as number) : 0, + patch: parts.length > 2 ? (parts[2] as number) : 0, + pre, +}); + +const at = (major: number, minor: number, patch: number): SemVer => ({ + major, + minor, + patch, + pre: [], +}); + +/** Cargo's caret: the upper bound is the next version that changes the + * left-most non-zero segment. `^0.2.3` is `<0.3.0`, `^0.0.3` is `<0.0.4`. */ +function caretUpper(parts: readonly number[]): SemVer { + const [major, minor, patch] = parts as [number, number?, number?]; + if (major !== 0) return at(major + 1, 0, 0); + if (minor === undefined) return at(1, 0, 0); + if (minor !== 0) return at(0, minor + 1, 0); + if (patch === undefined) return at(0, 1, 0); + if (patch !== 0) return at(0, 0, patch + 1); + return at(0, 0, 1); +} + +/** Cargo's tilde: only the last specified segment may grow. */ +function tildeUpper(parts: readonly number[]): SemVer { + const [major, minor] = parts as [number, number?]; + return minor === undefined ? at(major + 1, 0, 0) : at(major, minor + 1, 0); +} + +const OP_RE = /^(\^|~|>=|<=|>|<|=)?\s*(.+)$/; + +function expand(token: string): Comparator[] | null { + const match = OP_RE.exec(token); + if (!match) return null; + const explicitOp = match[1]; + const rest = (match[2] as string).trim(); + const split = partial(rest); + if (!split) return null; + const { parts, pre } = split; + + if (parts.length === 0) return []; // bare `*`/`x`: matches anything + + // An explicit wildcard binds tighter than an omitted segment: `1.2` is + // `^1.2` (< 2.0.0), but `1.2.*` is the 1.2 line (< 1.3.0). With an operator + // the wildcard is just the segments the author left off (`^1.*` == `^1`). + if (split.wildcard && explicitOp === undefined) { + return [ + { op: ">=", version: atLeast(parts, pre) }, + { op: "<", version: tildeUpper(parts) }, + ]; + } + + switch (explicitOp ?? "^") { // Cargo: a bare version is a caret range. + case "^": + return [ + { op: ">=", version: atLeast(parts, pre) }, + { op: "<", version: caretUpper(parts) }, + ]; + case "~": + return [ + { op: ">=", version: atLeast(parts, pre) }, + { op: "<", version: tildeUpper(parts) }, + ]; + case "=": + // `=1.2` is not "exactly 1.2.0" in Cargo, it is the 1.2 line. + if (parts.length === 3) return [{ op: "=", version: atLeast(parts, pre) }]; + return [ + { op: ">=", version: atLeast(parts, pre) }, + { op: "<", version: tildeUpper(parts) }, + ]; + default: + return [{ op: explicitOp as Op, version: atLeast(parts, pre) }]; + } +} + +function parseComparators(input: string): Comparator[] | null { + const trimmed = input.trim(); + if (trimmed === "") return null; + const comparators: Comparator[] = []; + let sawToken = false; + for (const token of trimmed.split(/\s*,\s*|\s+/)) { + if (token === "") continue; + const expanded = expand(token); + if (!expanded) return null; + sawToken = true; + comparators.push(...expanded); + } + // `*` is a legitimate range that constrains nothing, so emptiness cannot + // double as the failure signal. + return sawToken ? comparators : null; +} + +/** Parse in **Cargo's dialect**: a bare `1.2.3` is a caret range, and only + * `=1.2.3` pins one version. Anything that is not a legible range becomes an + * exact tag, which is how opaque versions are requested. */ +export function parseRequirement(input: string): Requirement { + const comparators = parseComparators(input); + return comparators === null + ? { kind: "exact", tag: input } + : { kind: "range", comparators }; +} + +export function requirementMatches(requirement: Requirement, version: string): boolean { + if (requirement.kind === "exact") return version === requirement.tag; + const parsed = parseVersion(version); + if (!parsed) return false; + return requirement.comparators.every((c) => matchesComparator(c, parsed)); +} + +/** Pick the version satisfying `requirement`, returned in its **published + * spelling** so the store address and VCS tag stay faithful to the tag the + * publisher pushed. Prereleases never satisfy a range. */ +export function resolve( + requirement: Requirement, + versions: readonly string[], +): string | null { + if (requirement.kind === "exact") { + return versions.find((version) => version === requirement.tag) ?? null; + } + let best: string | null = null; + let bestParsed: SemVer | null = null; + for (const version of versions) { + const parsed = parseVersion(version); + if (!parsed || !isStable(parsed)) continue; + if (!requirementMatches(requirement, version)) continue; + if (bestParsed === null || compareVersions(parsed, bestParsed) > 0) { + best = version; + bestParsed = parsed; + } + } + return best; +} From 1d366f3701330dcef89a9c085a5cf10be8da2720 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:42:54 -0500 Subject: [PATCH 14/38] claude autosave 2026-08-07T03:42:54Z --- src/ts/resolve.ts | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/ts/resolve.ts diff --git a/src/ts/resolve.ts b/src/ts/resolve.ts new file mode 100644 index 0000000..71158ad --- /dev/null +++ b/src/ts/resolve.ts @@ -0,0 +1,99 @@ +// Scheme-aware resolution against registry metadata — the TypeScript mirror of +// `zed_lib::resolve` (Rust), verified against the same corpus. + +import type { PackageMetadata, VersionScheme } from "@zed-pkg/zed-interfaces"; + +import { looksLikeRange, parseRequirement, parseVersion, resolve, compareVersions, isStable } from "./version.ts"; + +/** Stable strings shared with the conformance corpus and the other + * implementations. Renaming one breaks every consumer that matches on it. */ +export type ResolveErrorKind = "no_versions" | "invalid_requirement" | "unsatisfied"; + +/** Why a requirement did not resolve. The three cases need different fixes, so + * they stay distinct rather than collapsing into null. */ +export class ResolveError extends Error { + constructor( + readonly kind: ResolveErrorKind, + message: string, + ) { + super(message); + this.name = "ResolveError"; + } +} + +/** The scheme a package declared, defaulting to semver. + * + * `version_scheme` is optional on the wire because the field carries a serde + * default and the server omits it for the common case — absent means semver, + * not "unknown". */ +export function schemeOf(metadata: PackageMetadata): VersionScheme { + return metadata.version_scheme ?? "semver"; +} + +/** Resolve `requirement` against what the registry says a package published. + * + * Returns the version in its published spelling. Under the `opaque` scheme the + * requirement must be an exact tag: those packages have no ordering, so `^1.0` + * is not "everything 1.x", it is a mistake that would otherwise resolve + * through semver algebra by accident. */ +export function resolveVersion(metadata: PackageMetadata, requirement: string): string { + const id = `${metadata.org}/${metadata.name}`; + + if (metadata.versions.length === 0) { + throw new ResolveError("no_versions", `${id} has no published versions`); + } + + const scheme = schemeOf(metadata); + const parsed = parseRequirement(requirement); + + if (scheme === "opaque" && parsed.kind === "range") { + throw new ResolveError( + "invalid_requirement", + `\`${requirement}\` is not a valid requirement for ${id}: opaque-versioned ` + + `packages have no range algebra; require an exact tag`, + ); + } + + // A range that *looks* like one but does not parse (`^1.x.y`) would degrade + // into an exact tag and never match. Catch it as the typo it is. + if (scheme !== "opaque" && parsed.kind === "exact" && looksLikeRange(requirement)) { + throw new ResolveError( + "invalid_requirement", + `\`${requirement}\` is not a valid requirement for ${id}: looks like a version ` + + `range but is not a valid one`, + ); + } + + const resolved = resolve(parsed, metadata.versions); + if (resolved === null) { + throw new ResolveError( + "unsatisfied", + `${id} has no version matching \`${requirement}\`; published: ${metadata.versions.join(", ")}`, + ); + } + return resolved; +} + +/** The newest installable version, ignoring prereleases. + * + * `latest` is what the registry computed when the package was last published + * and can lag a yank, so this recomputes from the version list the same + * response carried. */ +export function latestStable(metadata: PackageMetadata): string | null { + if (schemeOf(metadata) === "opaque") { + const latest = metadata.latest; + if (!latest) return null; + return metadata.versions.includes(latest) ? latest : null; + } + let best: string | null = null; + let bestParsed: ReturnType = null; + for (const version of metadata.versions) { + const parsed = parseVersion(version); + if (!parsed || !isStable(parsed)) continue; + if (bestParsed === null || compareVersions(parsed, bestParsed) > 0) { + best = version; + bestParsed = parsed; + } + } + return best; +} From 03a9b89a28872f12086cc70e1aed76f171bc15d5 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:01 -0500 Subject: [PATCH 15/38] claude autosave 2026-08-07T03:43:01Z --- src/ts/index.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/ts/index.ts diff --git a/src/ts/index.ts b/src/ts/index.ts new file mode 100644 index 0000000..a982c0b --- /dev/null +++ b/src/ts/index.ts @@ -0,0 +1,22 @@ +// Implementations of the zed-pkg contract, in TypeScript. +// +// The TS slice of zed-lib exists so a browser client answers "which version +// does `^1.2` install?" exactly the way zed-cli does. Both run +// conformance/cases/*.json; a disagreement is a failing test rather than a +// support ticket. +// +// Types come from @zed-pkg/zed-interfaces; this package adds only behavior. + +export { ResolveError, latestStable, resolveVersion, schemeOf } from "./resolve.ts"; +export type { ResolveErrorKind } from "./resolve.ts"; +export { + compareVersions, + isStable, + looksLikeRange, + normalizeCalver, + parseRequirement, + parseVersion, + requirementMatches, + resolve, +} from "./version.ts"; +export type { Comparator, Op, Requirement, SemVer } from "./version.ts"; From bdb33ce701a4d0cff54ede9d788f0a94ec0f11cf Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:04 -0500 Subject: [PATCH 16/38] claude autosave 2026-08-07T03:43:04Z --- src/ts/package.json | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/ts/package.json diff --git a/src/ts/package.json b/src/ts/package.json new file mode 100644 index 0000000..21ca588 --- /dev/null +++ b/src/ts/package.json @@ -0,0 +1,32 @@ +{ + "name": "@zed-pkg/zed-lib", + "version": "0.1.0", + "description": "Implementations of the zed-pkg interfaces in TypeScript — resolution and policy over the shared contract types, verified against the cross-language corpus.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/zed-pkg/zed-lib.git", + "directory": "src/ts" + }, + "type": "module", + "types": "./index.ts", + "exports": { + ".": "./index.ts", + "./*": "./*.ts" + }, + "files": [ + "*.ts", + "README.md" + ], + "sideEffects": false, + "dependencies": { + "@zed-pkg/zed-interfaces": "file:../../../zed-interfaces/src/ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "test": "node --test conformance.test.ts" + }, + "devDependencies": { + "typescript": "^5.6.0" + } +} From f96a2ae50d6043542dd9b0ffe9576b7af6f7854e Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:16 -0500 Subject: [PATCH 17/38] claude autosave 2026-08-07T03:43:16Z --- src/ts/conformance.test.ts | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/ts/conformance.test.ts diff --git a/src/ts/conformance.test.ts b/src/ts/conformance.test.ts new file mode 100644 index 0000000..5ad66a7 --- /dev/null +++ b/src/ts/conformance.test.ts @@ -0,0 +1,68 @@ +// Runs the shared conformance corpus against the TypeScript implementation. +// The Rust and Dart slices run the same file; a case that passes in one +// language and fails in another is the drift this repository exists to catch. +// +// node --test conformance.test.ts +// +// No build step: Node strips the types on the way in. + +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { test } from "node:test"; + +import type { PackageMetadata, VersionScheme } from "@zed-pkg/zed-interfaces"; + +import { ResolveError, resolveVersion } from "./index.ts"; + +interface Case { + readonly name: string; + readonly scheme: string; + readonly versions: readonly string[]; + readonly requirement: string; + readonly expect: { readonly version?: string; readonly error?: string }; +} + +const corpusPath = path.join( + import.meta.dirname, + "../../conformance/cases/version-resolution.json", +); +const corpus = JSON.parse(fs.readFileSync(corpusPath, "utf8")) as { cases: Case[] }; + +const metadataFor = (scheme: string, versions: readonly string[]): PackageMetadata => ({ + org: "acme", + name: "conformance", + vcs: "git", + repo_url: "https://github.com/acme/conformance", + latest: versions.length ? (versions[versions.length - 1] as string) : null, + versions, + version_scheme: (scheme === "calver" || scheme === "opaque" ? scheme : "semver") as VersionScheme, +}); + +test("the corpus is not empty", () => { + assert.ok(corpus.cases.length > 0); +}); + +for (const testCase of corpus.cases) { + test(testCase.name, () => { + const metadata = metadataFor(testCase.scheme, testCase.versions); + const { version: want, error: wantError } = testCase.expect; + assert.ok( + (want === undefined) !== (wantError === undefined), + "a case declares exactly one of `version` or `error`", + ); + + if (want !== undefined) { + assert.equal(resolveVersion(metadata, testCase.requirement), want); + return; + } + assert.throws( + () => resolveVersion(metadata, testCase.requirement), + (error: unknown) => { + assert.ok(error instanceof ResolveError); + assert.equal(error.kind, wantError); + return true; + }, + ); + }); +} From aaee6ccceb31454d1a5be00d61196da25eaf1eec Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:18 -0500 Subject: [PATCH 18/38] claude autosave 2026-08-07T03:43:18Z --- src/ts/tsconfig.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/ts/tsconfig.json diff --git a/src/ts/tsconfig.json b/src/ts/tsconfig.json new file mode 100644 index 0000000..e181977 --- /dev/null +++ b/src/ts/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "strict": true, + "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, + "types": ["node"], + "skipLibCheck": true, + "noEmit": true + }, + "include": ["*.ts"] +} From 1731a80893b8808d6bf511a782d67ca4b893ab1e Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:33 -0500 Subject: [PATCH 19/38] claude autosave 2026-08-07T03:43:33Z --- src/ts/package-lock.json | 45 ++++++++++++++++++++++++++++++++++++++++ src/ts/resolve.ts | 11 ++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/ts/package-lock.json diff --git a/src/ts/package-lock.json b/src/ts/package-lock.json new file mode 100644 index 0000000..3fe6059 --- /dev/null +++ b/src/ts/package-lock.json @@ -0,0 +1,45 @@ +{ + "name": "@zed-pkg/zed-lib", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@zed-pkg/zed-lib", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@zed-pkg/zed-interfaces": "file:../../../zed-interfaces/src/ts" + }, + "devDependencies": { + "typescript": "^5.6.0" + } + }, + "../../../zed-interfaces/src/ts": { + "name": "@zed-pkg/zed-interfaces", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "typescript": "^5.6.0" + } + }, + "node_modules/@zed-pkg/zed-interfaces": { + "resolved": "../../../zed-interfaces/src/ts", + "link": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/src/ts/resolve.ts b/src/ts/resolve.ts index 71158ad..165aa57 100644 --- a/src/ts/resolve.ts +++ b/src/ts/resolve.ts @@ -12,12 +12,15 @@ export type ResolveErrorKind = "no_versions" | "invalid_requirement" | "unsatisf /** Why a requirement did not resolve. The three cases need different fixes, so * they stay distinct rather than collapsing into null. */ export class ResolveError extends Error { - constructor( - readonly kind: ResolveErrorKind, - message: string, - ) { + // Declared as a field rather than a constructor parameter property: those + // are not erasable, and this package is consumed straight from source by + // Node's type-stripping and by bundlers. + readonly kind: ResolveErrorKind; + + constructor(kind: ResolveErrorKind, message: string) { super(message); this.name = "ResolveError"; + this.kind = kind; } } From a8c8b7f34b8852ad6aa25d7bf11a69681db131e2 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:43:57 -0500 Subject: [PATCH 20/38] claude autosave 2026-08-07T03:43:57Z --- .zpkg.toml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/.zpkg.toml b/.zpkg.toml index 6b7070f..67515d5 100644 --- a/.zpkg.toml +++ b/.zpkg.toml @@ -57,11 +57,30 @@ dir = "conformance" name = "zed-lib-conformance" adapter = "none" -# Dart and TypeScript implementations land under src/dart and src/ts, mirroring -# the slices in zed-interfaces. They are not scaffolded until there is real -# behavior to put in them — an empty package is a promise, not a package. +# Front-end implementations of the same behavior. Not thin bindings — each is a +# native implementation held to `conformance/cases/*.json`, so a browser or +# Flutter client resolves a requirement exactly the way zed-cli does. +[targets.dart] +dir = "src/dart" +adapter = "dart" + +[targets.dart.native] +registry = "pub.dev" +package = "zed_lib" +tag_format = "dart/v{version}" + +[targets.typescript] +dir = "src/ts" +name = "zed-lib-typescript" +adapter = "node" + +[targets.typescript.native] +registry = "npm" +package = "@zed-pkg/zed-lib" +tag_format = "ts/v{version}" [scripts] test = "cargo test --all-targets --locked" lint = "cargo clippy --all-targets --locked -- -D warnings" format = "cargo fmt --all -- --check" +conformance = "cargo test --locked --test conformance" From 8218afd78ff34058c6125b703182a9c7b9b9bf3c Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:44:12 -0500 Subject: [PATCH 21/38] claude autosave 2026-08-07T03:44:12Z --- src/rust/tests/own_manifest.rs | 59 ++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/rust/tests/own_manifest.rs diff --git a/src/rust/tests/own_manifest.rs b/src/rust/tests/own_manifest.rs new file mode 100644 index 0000000..f8fb19b --- /dev/null +++ b/src/rust/tests/own_manifest.rs @@ -0,0 +1,59 @@ +//! This repository's own `.zpkg.toml` must satisfy the rules `zed-interfaces` +//! defines. zed-lib is a polyglot package with three implementation slices and +//! a corpus target; nothing else in CI parses that manifest, so a mistake in it +//! would only surface at publish time. + +use std::path::Path; + +use zed_interfaces::manifest::Manifest; + +fn own_manifest() -> Manifest { + let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../.zpkg.toml"); + let raw = std::fs::read_to_string(&path) + .unwrap_or_else(|error| panic!("read {}: {error}", path.display())); + Manifest::parse(&raw).expect("the repository manifest parses and validates") +} + +#[test] +fn the_repository_manifest_is_valid() { + let manifest = own_manifest(); + assert_eq!(manifest.package.name, "zed-lib"); + assert!(manifest.is_polyglot()); +} + +#[test] +fn every_implementation_slice_is_its_own_target_with_an_isolated_root() { + let manifest = own_manifest(); + for (target, dir, adapter) in [ + ("rust", "src/rust", "rust"), + ("dart", "src/dart", "dart"), + ("typescript", "src/ts", "node"), + ] { + let section = manifest + .targets + .get(target) + .unwrap_or_else(|| panic!("missing `[targets.{target}]`")); + assert_eq!(section.dir, dir, "target `{target}` moved"); + assert_eq!(section.adapter.as_deref(), Some(adapter)); + assert!( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .join(dir) + .is_dir(), + "target `{target}` points at `{dir}`, which does not exist" + ); + } +} + +#[test] +fn the_corpus_ships_as_its_own_target() { + let manifest = own_manifest(); + let corpus = manifest + .targets + .get("conformance") + .expect("the corpus is consumable on its own"); + assert_eq!(corpus.dir, "conformance"); + // An implementation in a language zed-lib does not ship yet still needs + // something to be correct against, so the corpus must not be Rust-only. + assert_eq!(corpus.adapter.as_deref(), Some("none")); +} From c4a6407a4e8d9b4a06fe776e6081b21e57073ce2 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:44:26 -0500 Subject: [PATCH 22/38] claude autosave 2026-08-07T03:44:26Z --- src/dart/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/dart/README.md diff --git a/src/dart/README.md b/src/dart/README.md new file mode 100644 index 0000000..476574c --- /dev/null +++ b/src/dart/README.md @@ -0,0 +1,41 @@ +# zed_lib (Dart) + +Implementations of the [zed-pkg](https://github.com/zed-pkg) contract in Dart, +so a Flutter or web client answers "which version does `^1.2` install?" exactly +the way `zed-cli` does. + +```dart +import 'package:zed_interfaces/package_metadata.dart'; +import 'package:zed_lib/zed_lib.dart'; + +final metadata = PackageMetadata.fromJson(json); +try { + final version = resolveVersion(metadata, '^1.2'); // '1.4.0', as published +} on ResolveException catch (error) { + switch (error.kind) { + case ResolveErrorKind.noVersions: // nothing installable + case ResolveErrorKind.invalidRequirement: // the requirement is the bug + case ResolveErrorKind.unsatisfied: // good requirement, no match + } +} +``` + +Types come from `package:zed_interfaces`; this package adds only behavior. + +## Not a binding, and not a dependency wrapper + +This is a native Dart implementation of the same algebra, held to +[`conformance/cases/*.json`](../../conformance) alongside the Rust and +TypeScript slices. It is deliberately dependency-free: `pub_semver`'s dialect +differs from Cargo's exactly where it matters — a bare `1.0.0` is an *exact* +constraint there and a caret range here — and three implementations of one +contract cannot afford a translation layer whose edge cases nobody reads. + +```sh +dart pub get +dart analyze +dart test # runs the shared corpus +``` + +The package resolves `zed_interfaces` through a sibling checkout of +`zed-interfaces`, so clone both into the same parent directory. From b11cfbe19b8d7d2525db99bc82cd1c964504f5c5 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:44:32 -0500 Subject: [PATCH 23/38] claude autosave 2026-08-07T03:44:32Z --- src/ts/README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/ts/README.md diff --git a/src/ts/README.md b/src/ts/README.md new file mode 100644 index 0000000..30b2a66 --- /dev/null +++ b/src/ts/README.md @@ -0,0 +1,39 @@ +# @zed-pkg/zed-lib + +Implementations of the [zed-pkg](https://github.com/zed-pkg) contract in +TypeScript, so a browser client answers "which version does `^1.2` install?" +exactly the way `zed-cli` does. + +```ts +import type { PackageMetadata } from "@zed-pkg/zed-interfaces"; +import { ResolveError, resolveVersion } from "@zed-pkg/zed-lib"; + +try { + const version = resolveVersion(metadata, "^1.2"); // "1.4.0", as published +} catch (error) { + if (error instanceof ResolveError) { + error.kind; // "no_versions" | "invalid_requirement" | "unsatisfied" + } +} +``` + +Types come from `@zed-pkg/zed-interfaces`; this package adds only behavior. + +## Not a binding, and not a dependency wrapper + +This is a native TypeScript implementation of the same algebra, held to +[`conformance/cases/*.json`](../../conformance) alongside the Rust and Dart +slices. It is deliberately dependency-free: npm's `semver` implements a +different dialect from Cargo's — a bare `1.0.0` is exact there, a caret range +here, and `1.2` means the 1.2 line rather than `^1.2` — and three +implementations of one contract cannot afford a translation layer whose edge +cases nobody reads. + +Shipped as TypeScript source. Everything is erasable syntax, so Node runs the +tests with no build step: + +```sh +npm install +npm test # node --test conformance.test.ts, the shared corpus +npm run typecheck +``` From da9d5da1c59db27e1bc69cad51f1f8230ad88a9b Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:44:45 -0500 Subject: [PATCH 24/38] claude autosave 2026-08-07T03:44:45Z --- .github/workflows/ci.yml | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b663590..4b48486 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,3 +56,74 @@ jobs: - name: Conformance corpus working-directory: zed-lib run: cargo test --locked --test conformance + + # Each implementation slice runs the same corpus. These jobs are what turn + # "three implementations of one contract" from a claim into a check. + dart: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + path: zed-lib + persist-credentials: false + show-progress: false + + - name: Check out zed-interfaces + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: zed-pkg/zed-interfaces + path: zed-interfaces + persist-credentials: false + show-progress: false + + - name: Install Dart SDK + uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c # v1.7.1 + + - name: Resolve dependencies + working-directory: zed-lib/src/dart + run: dart pub get + + - name: Analyze + working-directory: zed-lib/src/dart + run: dart analyze --fatal-infos + + - name: Conformance corpus + working-directory: zed-lib/src/dart + run: dart test + + typescript: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + path: zed-lib + persist-credentials: false + show-progress: false + + - name: Check out zed-interfaces + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: zed-pkg/zed-interfaces + path: zed-interfaces + persist-credentials: false + show-progress: false + + - name: Install dependencies + working-directory: zed-lib/src/ts + run: | + npm install + npm install --no-save typescript@5 @types/node + + - name: Typecheck + working-directory: zed-lib/src/ts + run: npx tsc --noEmit + + # Node strips the types, so the corpus runs against the shipped source + # rather than a build artifact. + - name: Conformance corpus + working-directory: zed-lib/src/ts + run: node --test conformance.test.ts From e2e5e02961fb7b149ce0e2002511ad90a41482b6 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:45:07 -0500 Subject: [PATCH 25/38] claude autosave 2026-08-07T03:45:07Z --- README.md | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d2546b2..b1ce228 100644 --- a/README.md +++ b/README.md @@ -43,21 +43,37 @@ let newest = latest_stable(&metadata); // ignores prereleases | `invalid_requirement` | the requirement cannot mean anything here (`^1.x.y`, or a range against an opaque package) | | `unsatisfied` | a good requirement nothing published satisfies | -## Layout +## Three implementations, one corpus ``` zed-lib/ src/rust/ the crate (Cargo.toml lives here) - conformance/cases/ language-neutral corpus every implementation must pass + src/dart/ native Dart implementation (package:zed_lib) + src/ts/ native TypeScript implementation (@zed-pkg/zed-lib) + conformance/cases/ language-neutral corpus all three must pass Cargo.toml virtual workspace, members = ["src/rust"] .zpkg.toml one package, one slice per language + the corpus ``` -Rust is the first slice. Dart and TypeScript implementations will sit beside it -under `src/`, mirroring the slice layout of `zed-interfaces` and verified -against the same `conformance/` corpus — so the CLI and a web UI cannot -disagree about what `^1.2` resolves to. They are not scaffolded yet: an empty -package is a promise, not a package. +The Dart and TypeScript slices are **not bindings**. Each is a native +implementation of the same algebra, and each runs +[`conformance/cases/*.json`](conformance) — so "the CLI resolved 1.4.0 but the +web UI offered 2.0.0" is a failing test in one of them rather than a support +ticket. + +All three are dependency-free on purpose. `pub_semver` and npm's `semver` each +implement a *different dialect* from Cargo's, and they disagree exactly where +it hurts: + +| requirement | Cargo (and zed) | npm `semver` | `pub_semver` | +| ----------- | --------------- | ------------ | ------------ | +| `1.0.0` | `>=1.0.0 <2.0.0` | exactly `1.0.0` | exactly `1.0.0` | +| `1.2` | `>=1.2.0 <2.0.0` | `>=1.2.0 <1.3.0` | — | +| `1.2.*` | `>=1.2.0 <1.3.0` | same | — | + +Three implementations of one contract cannot afford a translation layer whose +edge cases nobody reads, so the algebra is written out in each language and the +corpus proves they agree. ## Migrating behavior out of zed-interfaces From f91f0755655bc9af23364d13dade0bcd9d37f1f8 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:46:37 -0500 Subject: [PATCH 26/38] claude autosave 2026-08-07T03:46:37Z --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b1ce228..84140ea 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,16 @@ Sibling checkouts, like the rest of the org: ```sh git clone https://github.com/zed-pkg/zed-interfaces git clone https://github.com/zed-pkg/zed-lib -cd zed-lib && cargo test +cd zed-lib + +cargo test # Rust slice + corpus +(cd src/dart && dart pub get && dart test) # Dart slice + corpus +(cd src/ts && npm install && npm test) # TypeScript slice + corpus ``` -The crate depends on `../zed-interfaces/src/rust` by path until -`zed-interfaces` publishes `0.1.0` to the registry, at which point this becomes -a plain version requirement. +Every slice depends on its `zed-interfaces` counterpart by path until +`zed-interfaces` publishes `0.1.0`, at which point each becomes a plain version +requirement. ## License From b827305a487a24300494ee9ec5b4de55989d16ce Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 22:46:46 -0500 Subject: [PATCH 27/38] claude autosave 2026-08-07T03:46:46Z --- .gitignore | 4 + agents.md | 2 + src/dart/pubspec.lock | 396 --------------------------------------- src/ts/package-lock.json | 45 ----- 4 files changed, 6 insertions(+), 441 deletions(-) delete mode 100644 src/dart/pubspec.lock delete mode 100644 src/ts/package-lock.json diff --git a/.gitignore b/.gitignore index 1653517..ee90305 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ temp node_modules/ .dart_tool/ .DS_Store + +# Slice tooling state +src/dart/pubspec.lock +src/ts/package-lock.json diff --git a/agents.md b/agents.md index 786391f..04fc520 100644 --- a/agents.md +++ b/agents.md @@ -16,6 +16,8 @@ This repository implements the contract defined by `zed-pkg/zed-interfaces`. Int - Moving behavior out of `zed-interfaces` is a breaking change for that crate. Land each move as its own change with its consumers updated in contract-first order, not as a batch. - Cross-language behavior is specified by `conformance/cases/*.json` before it is implemented. Add the case, watch it fail, then write the code; a case written afterwards tests the code's opinion rather than the contract. - Every implementation slice runs the same corpus. A case that only one language can satisfy is a bug in the case. +- The slices are native implementations, not bindings, and they take no semver dependency. `pub_semver` and npm's `semver` implement a different dialect from Cargo's — a bare `1.0.0` is exact there and a caret range here — so a wrapper would smuggle in disagreements the corpus was built to prevent. When behavior is ambiguous, the Rust `semver` crate is the reference: probe it, then pin the answer as a case. +- A new corpus case must be verified against Rust *first*. Rust is the slice consumers already run through `zed-cli`, so a case Rust fails is a case that mis-states the contract. - Errors carry a stable `kind()` string shared with the corpus. Renaming one is a breaking change for every implementation and every consumer that matches on it. - Resolution returns versions in their **published spelling**. Normalizing is for comparison only — the store address and the VCS tag must stay faithful to what the publisher tagged. - Keep `Cargo.lock` committed; do not allow CI to update it implicitly. diff --git a/src/dart/pubspec.lock b/src/dart/pubspec.lock deleted file mode 100644 index 7f05074..0000000 --- a/src/dart/pubspec.lock +++ /dev/null @@ -1,396 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: "9a3386eea899815698dd55995277cf7cb8572ee52b399a6edfb7ae2b50e5fc19" - url: "https://pub.dev" - source: hosted - version: "105.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "62993bed6eadbe9596c5c20d5c167e7bc563c5fe266657a04ddeb93bdb84f4c9" - url: "https://pub.dev" - source: hosted - version: "14.1.0" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" - source: hosted - version: "2.13.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d" - url: "https://pub.dev" - source: hosted - version: "1.15.1" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - lints: - dependency: "direct dev" - description: - name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" - url: "https://pub.dev" - source: hosted - version: "0.12.20" - meta: - dependency: transitive - description: - name: meta - sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" - url: "https://pub.dev" - source: hosted - version: "1.19.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - package_config: - dependency: transitive - description: - name: package_config - sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d - url: "https://pub.dev" - source: hosted - version: "3.0.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" - source_span: - dependency: transitive - description: - name: source_span - sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" - source: hosted - version: "1.10.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test: - dependency: "direct dev" - description: - name: test - sha256: "0d5ba5602ec3baa28c8ce365e1efc5575969c765f45c554a3e167dc7945b9c30" - url: "https://pub.dev" - source: hosted - version: "1.31.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "475610b2aa23c19687cce2961e44b0cc57cafe220f67c2b80201231b2a07fbe7" - url: "https://pub.dev" - source: hosted - version: "0.7.13" - test_core: - dependency: transitive - description: - name: test_core - sha256: a39c204a4fc7a7ccb04a2b985e359fda3cc37e45e0b8ac61c3fb1a05aa832132 - url: "https://pub.dev" - source: hosted - version: "0.6.19" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" - url: "https://pub.dev" - source: hosted - version: "15.2.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" - zed_interfaces: - dependency: "direct main" - description: - path: "../../../zed-interfaces/src/dart" - relative: true - source: path - version: "0.1.0" -sdks: - dart: ">=3.11.0 <4.0.0" diff --git a/src/ts/package-lock.json b/src/ts/package-lock.json deleted file mode 100644 index 3fe6059..0000000 --- a/src/ts/package-lock.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@zed-pkg/zed-lib", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@zed-pkg/zed-lib", - "version": "0.1.0", - "license": "MIT", - "dependencies": { - "@zed-pkg/zed-interfaces": "file:../../../zed-interfaces/src/ts" - }, - "devDependencies": { - "typescript": "^5.6.0" - } - }, - "../../../zed-interfaces/src/ts": { - "name": "@zed-pkg/zed-interfaces", - "version": "0.1.0", - "license": "MIT", - "devDependencies": { - "typescript": "^5.6.0" - } - }, - "node_modules/@zed-pkg/zed-interfaces": { - "resolved": "../../../zed-interfaces/src/ts", - "link": true - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - } - } -} From b9c050b83503319be2e613e11231ccad13819910 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:20:34 -0500 Subject: [PATCH 28/38] claude autosave 2026-08-07T04:20:34Z --- src/dart/lib/src/resolve.dart | 2 +- src/dart/lib/src/version.dart | 34 +++++++++++++++++----------------- src/dart/lib/zed_lib.dart | 9 +++++++-- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/dart/lib/src/resolve.dart b/src/dart/lib/src/resolve.dart index f265d3e..6c6b60b 100644 --- a/src/dart/lib/src/resolve.dart +++ b/src/dart/lib/src/resolve.dart @@ -82,7 +82,7 @@ String resolveVersion(PackageMetadata metadata, String requirement) { ); } - final resolved = resolve(parsed, metadata.versions); + final resolved = resolveRequirement(parsed, metadata.versions); if (resolved == null) { throw ResolveException( ResolveErrorKind.unsatisfied, diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index 7fdd1e6..cddef40 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -201,8 +201,8 @@ SemVer? parseVersion(String raw) { } /// One `` bound. -class Comparator { - const Comparator(this.op, this.version); +class VersionBound { + const VersionBound(this.op, this.version); final String op; final SemVer version; @@ -253,7 +253,7 @@ class ExactRequirement extends Requirement { class RangeRequirement extends Requirement { const RangeRequirement(this.comparators); - final List comparators; + final List comparators; @override bool matches(String version) { @@ -333,11 +333,11 @@ SemVer _tildeUpper(List parts) => switch (parts.length) { _ => SemVer(parts[0], parts[1] + 1, 0), }; -List? _parseComparators(String input) { +List? _parseComparators(String input) { final trimmed = input.trim(); if (trimmed.isEmpty) return null; - final comparators = []; + final comparators = []; var sawToken = false; for (final token in trimmed.split(RegExp(r'\s*,\s*|\s+'))) { if (token.isEmpty) continue; @@ -351,7 +351,7 @@ List? _parseComparators(String input) { return sawToken ? comparators : null; } -List? _expand(String token) { +List? _expand(String token) { final match = RegExp(r'^(\^|~|>=|<=|>|<|=)?\s*(.+)$').firstMatch(token); if (match == null) return null; final explicitOp = match.group(1); @@ -369,38 +369,38 @@ List? _expand(String token) { // the wildcard is just the segments the author left off (`^1.*` == `^1`). if (partial.wildcard && explicitOp == null) { return [ - Comparator('>=', _atLeast(parts, pre)), - Comparator('<', _tildeUpper(parts)), + VersionBound('>=', _atLeast(parts, pre)), + VersionBound('<', _tildeUpper(parts)), ]; } switch (op) { case '^': return [ - Comparator('>=', _atLeast(parts, pre)), - Comparator('<', _caretUpper(parts)), + VersionBound('>=', _atLeast(parts, pre)), + VersionBound('<', _caretUpper(parts)), ]; case '~': return [ - Comparator('>=', _atLeast(parts, pre)), - Comparator('<', _tildeUpper(parts)), + VersionBound('>=', _atLeast(parts, pre)), + VersionBound('<', _tildeUpper(parts)), ]; case '=': // `=1.2` is not "exactly 1.2.0" in Cargo, it is the 1.2 line. - if (parts.length == 3) return [Comparator('=', _atLeast(parts, pre))]; + if (parts.length == 3) return [VersionBound('=', _atLeast(parts, pre))]; return [ - Comparator('>=', _atLeast(parts, pre)), - Comparator('<', _tildeUpper(parts)), + VersionBound('>=', _atLeast(parts, pre)), + VersionBound('<', _tildeUpper(parts)), ]; default: - return [Comparator(op, _atLeast(parts, pre))]; + return [VersionBound(op, _atLeast(parts, pre))]; } } /// Pick the version satisfying `requirement`, returned in its **published /// spelling** so the store address and VCS tag stay faithful to the tag the /// publisher pushed. Prereleases never satisfy a range. -String? resolve(Requirement requirement, List versions) { +String? resolveRequirement(Requirement requirement, List versions) { switch (requirement) { case ExactRequirement(:final tag): for (final version in versions) { diff --git a/src/dart/lib/zed_lib.dart b/src/dart/lib/zed_lib.dart index 1a6a947..d94590a 100644 --- a/src/dart/lib/zed_lib.dart +++ b/src/dart/lib/zed_lib.dart @@ -10,14 +10,19 @@ library; export 'src/resolve.dart' show ResolveErrorKind, ResolveException, latestStable, resolveVersion, schemeOf; +// `VersionBound`, not `Comparator`: dart:core exports `Comparator`, and an +// explicit import *wins* over the implicit dart:core one — so the old name did +// not raise an ambiguity error, it silently shadowed the real type and broke +// unrelated consumer code. `resolveRequirement`, not `resolve`: a top-level +// `resolve` next to `resolveVersion` reads as a typo of it. export 'src/version.dart' show - Comparator, ExactRequirement, RangeRequirement, Requirement, SemVer, + VersionBound, looksLikeRange, normalizeCalver, parseVersion, - resolve; + resolveRequirement; From c126799f6ccdb2f3e993e93e0533ff1d6acff280 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:20:46 -0500 Subject: [PATCH 29/38] claude autosave 2026-08-07T04:20:46Z --- src/dart/test/public_api_test.dart | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/dart/test/public_api_test.dart diff --git a/src/dart/test/public_api_test.dart b/src/dart/test/public_api_test.dart new file mode 100644 index 0000000..af7cefd --- /dev/null +++ b/src/dart/test/public_api_test.dart @@ -0,0 +1,40 @@ +// Guards the shape of the exported API, not its behavior. +// +// This package is imported into Flutter apps, where dart:core is implicit and +// an explicit import wins over it. A type exported from here with a dart:core +// name does not produce an ambiguity error — it silently shadows the real one, +// and the consumer gets a baffling error in code that never touched zed-lib. +// That shipped once (a `Comparator` class), so it gets a test. + +import 'package:test/test.dart'; +import 'package:zed_lib/zed_lib.dart'; + +void main() { + test('importing zed_lib does not shadow dart:core types', () { + // Every one of these would fail to compile if the package exported a type + // with the same name; the test passing *is* the assertion. + final Comparator byValue = (a, b) => a.compareTo(b); + final sorted = [3, 1, 2]..sort(byValue); + expect(sorted, [1, 2, 3]); + + const duration = Duration(seconds: 1); + expect(duration.inMilliseconds, 1000); + + final match = RegExp(r'\d+').firstMatch('v12'); + expect(match?.group(0), '12'); + + final Set names = {'a'}; + final List numbers = [1]; + final Map byName = {'a': 1}; + expect([names.length, numbers.length, byName.length], [1, 1, 1]); + }); + + test('the public surface is the documented one', () { + // Named so a rename has to be deliberate: these are what consumers import. + expect(parseVersion('1.2.3')?.minor, 2); + expect(normalizeCalver('2026.07'), '2026.7.0'); + expect(looksLikeRange('^1.2'), isTrue); + expect(const VersionBound('>=', SemVer(1, 0, 0)).matches(const SemVer(1, 1, 0)), isTrue); + expect(resolveRequirement(Requirement.parse('^1'), ['1.4.0']), '1.4.0'); + }); +} From dd10452cfdb7ef2819fa4364c44443ffb1fea1bf Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:20:57 -0500 Subject: [PATCH 30/38] claude autosave 2026-08-07T04:20:57Z --- src/dart/test/public_api_test.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dart/test/public_api_test.dart b/src/dart/test/public_api_test.dart index af7cefd..e0e0811 100644 --- a/src/dart/test/public_api_test.dart +++ b/src/dart/test/public_api_test.dart @@ -13,8 +13,10 @@ void main() { test('importing zed_lib does not shadow dart:core types', () { // Every one of these would fail to compile if the package exported a type // with the same name; the test passing *is* the assertion. - final Comparator byValue = (a, b) => a.compareTo(b); - final sorted = [3, 1, 2]..sort(byValue); + int byValue(int a, int b) => a.compareTo(b); + // The type annotation is the point: it must resolve to dart:core's. + final Comparator comparator = byValue; + final sorted = [3, 1, 2]..sort(comparator); expect(sorted, [1, 2, 3]); const duration = Duration(seconds: 1); From 60b482964f6ca6fb63dfa125eea0a98590ffdf45 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:26:18 -0500 Subject: [PATCH 31/38] claude autosave 2026-08-07T04:26:18Z --- src/rust/examples/generate_fuzz_corpus.rs | 151 ++++++++++++++++++++++ src/ts/index.ts | 4 +- src/ts/resolve.ts | 4 +- src/ts/version.ts | 22 ++-- 4 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 src/rust/examples/generate_fuzz_corpus.rs diff --git a/src/rust/examples/generate_fuzz_corpus.rs b/src/rust/examples/generate_fuzz_corpus.rs new file mode 100644 index 0000000..db65d39 --- /dev/null +++ b/src/rust/examples/generate_fuzz_corpus.rs @@ -0,0 +1,151 @@ +//! Generates a differential-test corpus: pseudo-random (scheme, versions, +//! requirement) triples, answered by the **Rust** implementation and written as +//! ordinary corpus cases that Dart and TypeScript then have to reproduce. +//! +//! Rust is the reference on purpose. It is the slice consumers already run +//! through `zed-cli`, and it delegates the hard part to the `semver` crate that +//! Cargo itself uses — so "the hand-written Dart and TypeScript algebra agrees +//! with Cargo" is the property under test. The 20-odd hand-written cases pin +//! the decisions a human reasoned about; this pins the thousand combinations +//! nobody would think to write down. +//! +//! Deterministic by construction (a fixed-seed LCG, no clock, no entropy), so +//! regenerating produces byte-identical output and CI can diff it. +//! +//! Run with: `cargo run --locked --example generate_fuzz_corpus` + +use std::fs; +use std::path::Path; + +use zed_interfaces::registry::PackageMetadata; +use zed_interfaces::vcs::Vcs; +use zed_interfaces::version::VersionScheme; +use zed_lib::{latest_stable, resolve_version}; + +/// Deterministic LCG (Numerical Recipes constants). A real RNG would make the +/// corpus unreproducible, which would turn a CI diff into noise. +struct Lcg(u64); + +impl Lcg { + fn next(&mut self) -> u64 { + self.0 = self.0.wrapping_mul(1_664_525).wrapping_add(1_013_904_223); + self.0 >> 16 + } + + fn pick<'a, T>(&mut self, options: &'a [T]) -> &'a T { + &options[(self.next() as usize) % options.len()] + } + + fn range(&mut self, low: usize, high: usize) -> usize { + low + (self.next() as usize) % (high - low + 1) + } +} + +const VERSION_POOL: &[&str] = &[ + "0.0.1", "0.1.0", "0.1.9", "0.2.0", "1.0.0", "1.0.1", "1.2.0", "1.2.3", "1.2.9", "1.3.0", + "1.9.9", "2.0.0", "2.1.0", "10.0.0", "1.0.0-rc.1", "2.0.0-alpha.1", "1.2.3-beta.2", + "v1.0.0", "v2.0.0+incompatible", "2026.01.01", "2026.06.01", "2026.07.24", "2026.10.01", + "1.2.3rc1", "1.2.3.post1", "legacy-api", "release-candidate-1", "nightly", +]; + +const REQUIREMENT_POOL: &[&str] = &[ + "^1", "^1.2", "^1.2.3", "^0.1", "^0.0.1", "^2", "^2026", "~1", "~1.2", "~1.2.3", + ">=1.2", ">=1.2 <2", ">1.0.0", "<2.0.0", "<=1.2.3", "=1.0.0", "=1.2", "*", "1", "1.2", + "1.2.3", "1.*", "1.2.*", "1.x", "2026.07.24", ">=2026.7", "legacy-api", "nightly", + "^1.x.y", "not-a-version", ">= 1.0.0, < 2.0.0", +]; + +const SCHEMES: &[(&str, VersionScheme)] = &[ + ("semver", VersionScheme::Semver), + ("calver", VersionScheme::Calver), + ("opaque", VersionScheme::Opaque), +]; + +fn metadata(scheme: VersionScheme, versions: Vec) -> PackageMetadata { + PackageMetadata { + org: "acme".to_string(), + name: "conformance".to_string(), + vcs: Vcs::Git, + repo_url: "https://github.com/acme/conformance".to_string(), + description: None, + latest: versions.last().cloned(), + versions, + version_scheme: scheme, + tags: Vec::new(), + } +} + +fn json_array(values: &[String]) -> String { + let items: Vec = values + .iter() + .map(|v| serde_json::to_string(v).expect("string")) + .collect(); + format!("[{}]", items.join(", ")) +} + +fn main() { + let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../conformance/cases"); + fs::create_dir_all(&dir).expect("cases dir"); + + let mut rng = Lcg(0x5EED_1234); + let mut resolution = Vec::new(); + let mut latest = Vec::new(); + + for index in 0..400 { + let (scheme_name, scheme) = rng.pick(SCHEMES); + let count = rng.range(0, 6); + let mut versions: Vec = (0..count) + .map(|_| (*rng.pick(VERSION_POOL)).to_string()) + .collect(); + versions.sort(); + versions.dedup(); + let requirement = *rng.pick(REQUIREMENT_POOL); + let meta = metadata(*scheme, versions.clone()); + + let expect = match resolve_version(&meta, requirement) { + Ok(version) => format!("{{ \"version\": {} }}", serde_json::to_string(version).unwrap()), + Err(error) => format!("{{ \"error\": \"{}\" }}", error.kind()), + }; + resolution.push(format!( + " {{\n \"name\": \"fuzz/{index}\",\n \"scheme\": \"{scheme_name}\",\n \"versions\": {},\n \"requirement\": {},\n \"expect\": {expect}\n }}", + json_array(&versions), + serde_json::to_string(requirement).unwrap(), + )); + + // Same shape, different operation: `latest_stable` has no requirement + // and its own rules about prereleases and a stale `latest` field. + if index % 2 == 0 { + let expect = match latest_stable(&meta) { + Some(version) => { + format!("{{ \"version\": {} }}", serde_json::to_string(version).unwrap()) + } + None => "{ \"version\": null }".to_string(), + }; + latest.push(format!( + " {{\n \"name\": \"fuzz/{index}\",\n \"scheme\": \"{scheme_name}\",\n \"versions\": {},\n \"latest\": {},\n \"expect\": {expect}\n }}", + json_array(&versions), + meta.latest + .as_ref() + .map(|v| serde_json::to_string(v).unwrap()) + .unwrap_or_else(|| "null".to_string()), + )); + } + } + + let resolution_doc = format!( + "{{\n \"schema\": \"zed-lib/conformance/version-resolution/v1\",\n \"description\": \"GENERATED by `cargo run --example generate_fuzz_corpus` — do not edit by hand. Pseudo-random cases answered by the Rust implementation, which every other slice must reproduce. Deterministic: regenerating rewrites this file byte for byte.\",\n \"cases\": [\n{}\n ]\n}}\n", + resolution.join(",\n") + ); + let latest_doc = format!( + "{{\n \"schema\": \"zed-lib/conformance/latest-stable/v1\",\n \"description\": \"GENERATED by `cargo run --example generate_fuzz_corpus` — do not edit by hand. Pseudo-random `latest_stable` cases answered by the Rust implementation.\",\n \"cases\": [\n{}\n ]\n}}\n", + latest.join(",\n") + ); + + fs::write(dir.join("fuzz-version-resolution.json"), resolution_doc).expect("write"); + fs::write(dir.join("fuzz-latest-stable.json"), latest_doc).expect("write"); + println!( + "wrote {} resolution cases and {} latest-stable cases", + resolution.len(), + latest.len() + ); +} diff --git a/src/ts/index.ts b/src/ts/index.ts index a982c0b..b7dd794 100644 --- a/src/ts/index.ts +++ b/src/ts/index.ts @@ -17,6 +17,6 @@ export { parseRequirement, parseVersion, requirementMatches, - resolve, + resolveRequirement, } from "./version.ts"; -export type { Comparator, Op, Requirement, SemVer } from "./version.ts"; +export type { Op, Requirement, SemVer, VersionBound } from "./version.ts"; diff --git a/src/ts/resolve.ts b/src/ts/resolve.ts index 165aa57..58f3f15 100644 --- a/src/ts/resolve.ts +++ b/src/ts/resolve.ts @@ -3,7 +3,7 @@ import type { PackageMetadata, VersionScheme } from "@zed-pkg/zed-interfaces"; -import { looksLikeRange, parseRequirement, parseVersion, resolve, compareVersions, isStable } from "./version.ts"; +import { compareVersions, isStable, looksLikeRange, parseRequirement, parseVersion, resolveRequirement } from "./version.ts"; /** Stable strings shared with the conformance corpus and the other * implementations. Renaming one breaks every consumer that matches on it. */ @@ -67,7 +67,7 @@ export function resolveVersion(metadata: PackageMetadata, requirement: string): ); } - const resolved = resolve(parsed, metadata.versions); + const resolved = resolveRequirement(parsed, metadata.versions); if (resolved === null) { throw new ResolveError( "unsatisfied", diff --git a/src/ts/version.ts b/src/ts/version.ts index 851f46d..e2cfc76 100644 --- a/src/ts/version.ts +++ b/src/ts/version.ts @@ -165,14 +165,14 @@ export function parseVersion(raw: string): SemVer | null { export type Op = "=" | ">" | ">=" | "<" | "<="; /** One `` bound. */ -export interface Comparator { +export interface VersionBound { readonly op: Op; readonly version: SemVer; } -function matchesComparator(comparator: Comparator, candidate: SemVer): boolean { - const ordering = compareVersions(candidate, comparator.version); - switch (comparator.op) { +function matchesBound(bound: VersionBound, candidate: SemVer): boolean { + const ordering = compareVersions(candidate, bound.version); + switch (bound.op) { case "=": return ordering === 0; case ">": @@ -189,7 +189,7 @@ function matchesComparator(comparator: Comparator, candidate: SemVer): boolean { /** A requirement is either a range (semver algebra) or an exact tag. An opaque * package's requirement is always the latter. */ export type Requirement = - | { readonly kind: "range"; readonly comparators: readonly Comparator[] } + | { readonly kind: "range"; readonly comparators: readonly VersionBound[] } | { readonly kind: "exact"; readonly tag: string }; /** Does this string *look* like a range? Tells a typo (`^1.x.y`) from a @@ -279,7 +279,7 @@ function tildeUpper(parts: readonly number[]): SemVer { const OP_RE = /^(\^|~|>=|<=|>|<|=)?\s*(.+)$/; -function expand(token: string): Comparator[] | null { +function expand(token: string): VersionBound[] | null { const match = OP_RE.exec(token); if (!match) return null; const explicitOp = match[1]; @@ -323,10 +323,10 @@ function expand(token: string): Comparator[] | null { } } -function parseComparators(input: string): Comparator[] | null { +function parseBounds(input: string): VersionBound[] | null { const trimmed = input.trim(); if (trimmed === "") return null; - const comparators: Comparator[] = []; + const comparators: VersionBound[] = []; let sawToken = false; for (const token of trimmed.split(/\s*,\s*|\s+/)) { if (token === "") continue; @@ -344,7 +344,7 @@ function parseComparators(input: string): Comparator[] | null { * `=1.2.3` pins one version. Anything that is not a legible range becomes an * exact tag, which is how opaque versions are requested. */ export function parseRequirement(input: string): Requirement { - const comparators = parseComparators(input); + const comparators = parseBounds(input); return comparators === null ? { kind: "exact", tag: input } : { kind: "range", comparators }; @@ -354,13 +354,13 @@ export function requirementMatches(requirement: Requirement, version: string): b if (requirement.kind === "exact") return version === requirement.tag; const parsed = parseVersion(version); if (!parsed) return false; - return requirement.comparators.every((c) => matchesComparator(c, parsed)); + return requirement.comparators.every((bound) => matchesBound(bound, parsed)); } /** Pick the version satisfying `requirement`, returned in its **published * spelling** so the store address and VCS tag stay faithful to the tag the * publisher pushed. Prereleases never satisfy a range. */ -export function resolve( +export function resolveRequirement( requirement: Requirement, versions: readonly string[], ): string | null { From 134df5ff3b06aad8224daf667c9a3cd1d2ddc2e4 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:26:38 -0500 Subject: [PATCH 32/38] claude autosave 2026-08-07T04:26:38Z --- conformance/cases/latest-stable.json | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 conformance/cases/latest-stable.json diff --git a/conformance/cases/latest-stable.json b/conformance/cases/latest-stable.json new file mode 100644 index 0000000..20fdefd --- /dev/null +++ b/conformance/cases/latest-stable.json @@ -0,0 +1,76 @@ +{ + "schema": "zed-lib/conformance/latest-stable/v1", + "description": "Cases for `latest_stable`: the newest installable version, which is not the same question as `latest` on the wire. `latest` is what the registry computed when the package was last published and can lag a yank, so an implementation that just forwards it will offer a version the same response says is gone.", + "cases": [ + { + "name": "prereleases are never the latest stable version", + "scheme": "semver", + "versions": ["1.0.0", "2.0.0", "2.1.0-rc.1"], + "latest": "2.1.0-rc.1", + "expect": { "version": "2.0.0" } + }, + { + "name": "the newest version wins regardless of list order", + "scheme": "semver", + "versions": ["2.0.0", "10.0.0", "1.0.0"], + "latest": "1.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "the published spelling is preserved", + "scheme": "semver", + "versions": ["v1.0.0", "v2.0.0"], + "latest": null, + "expect": { "version": "v2.0.0" } + }, + { + "name": "calendar versions order by their normalized form", + "scheme": "calver", + "versions": ["2026.09.01", "2026.10.01", "2026.01.01"], + "latest": null, + "expect": { "version": "2026.10.01" } + }, + { + "name": "an opaque package has no ordering, so the registry's latest stands", + "scheme": "opaque", + "versions": ["legacy-api", "nightly"], + "latest": "legacy-api", + "expect": { "version": "legacy-api" } + }, + { + "name": "an opaque latest that is no longer published is not offered", + "scheme": "opaque", + "versions": ["legacy-api"], + "latest": "withdrawn", + "expect": { "version": null } + }, + { + "name": "an opaque package with no latest recorded has no answer", + "scheme": "opaque", + "versions": ["legacy-api"], + "latest": null, + "expect": { "version": null } + }, + { + "name": "nothing published, nothing to offer", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "only prereleases published means no stable version exists", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "2.0.0-alpha.1"], + "latest": "2.0.0-alpha.1", + "expect": { "version": null } + }, + { + "name": "an unparseable tag under a semver scheme is skipped, not crashed on", + "scheme": "semver", + "versions": ["1.0.0", "nightly"], + "latest": "nightly", + "expect": { "version": "1.0.0" } + } + ] +} From 31da75137e727bc74a2a7c367c57f6c7fb8a8cbe Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:27:04 -0500 Subject: [PATCH 33/38] claude autosave 2026-08-07T04:27:04Z --- src/rust/tests/conformance.rs | 170 +++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 55 deletions(-) diff --git a/src/rust/tests/conformance.rs b/src/rust/tests/conformance.rs index a4f4c22..6d0af8c 100644 --- a/src/rust/tests/conformance.rs +++ b/src/rust/tests/conformance.rs @@ -1,20 +1,27 @@ -//! Runs the shared conformance corpus against the Rust implementation. +//! Runs every corpus file in `conformance/cases/` against the Rust +//! implementation. The Dart and TypeScript slices load the same directory, so a +//! case added here is a case all three must answer identically. //! -//! The corpus is language-neutral on purpose: the Dart and TypeScript slices -//! of zed-lib will run the same file, so "the CLI resolved 1.4.0 but the web UI -//! showed 2.0.0" becomes a failing test in one of them rather than a support -//! ticket. +//! Rust is also the *oracle* for the generated files +//! (`fuzz-*.json`, written by `cargo run --example generate_fuzz_corpus`), so +//! its job here is narrower but not pointless: it catches the day a change to +//! this crate silently rewrites what the other two are being held to. -use std::path::Path; +use std::fs; +use std::path::{Path, PathBuf}; use serde::Deserialize; use zed_interfaces::registry::PackageMetadata; use zed_interfaces::vcs::Vcs; use zed_interfaces::version::VersionScheme; -use zed_lib::resolve_version; +use zed_lib::{latest_stable, resolve_version}; + +const RESOLUTION_SCHEMA: &str = "zed-lib/conformance/version-resolution/v1"; +const LATEST_SCHEMA: &str = "zed-lib/conformance/latest-stable/v1"; #[derive(Debug, Deserialize)] struct Corpus { + schema: String, cases: Vec, } @@ -23,7 +30,13 @@ struct Case { name: String, scheme: String, versions: Vec, - requirement: String, + /// Present on resolution cases. + #[serde(default)] + requirement: Option, + /// Present on latest-stable cases: what the registry recorded, which the + /// implementation may not simply forward. + #[serde(default)] + latest: Option, expect: Expect, } @@ -35,63 +48,110 @@ struct Expect { error: Option, } -fn corpus() -> Corpus { - let path = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("../../conformance/cases/version-resolution.json"); - let raw = std::fs::read_to_string(&path) - .unwrap_or_else(|error| panic!("read {}: {error}", path.display())); - serde_json::from_str(&raw).expect("the corpus is valid JSON in the expected shape") +fn cases_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("../../conformance/cases") } -#[test] -fn the_shared_corpus_passes() { - let corpus = corpus(); - assert!(!corpus.cases.is_empty(), "the corpus must not be empty"); +fn corpus_files() -> Vec { + let mut files: Vec = fs::read_dir(cases_dir()) + .expect("conformance/cases is readable") + .filter_map(|entry| entry.ok().map(|e| e.path())) + .filter(|path| path.extension().is_some_and(|ext| ext == "json")) + .collect(); + files.sort(); + assert!(!files.is_empty(), "the corpus directory must not be empty"); + files +} - for case in &corpus.cases { - let metadata = PackageMetadata { - org: "acme".to_string(), - name: "conformance".to_string(), - vcs: Vcs::Git, - repo_url: "https://github.com/acme/conformance".to_string(), - description: None, - latest: case.versions.last().cloned(), - versions: case.versions.clone(), - version_scheme: VersionScheme::from_str_lenient(&case.scheme), - tags: Vec::new(), - }; +fn metadata(case: &Case) -> PackageMetadata { + PackageMetadata { + org: "acme".to_string(), + name: "conformance".to_string(), + vcs: Vcs::Git, + repo_url: "https://github.com/acme/conformance".to_string(), + description: None, + latest: case.latest.clone().or_else(|| case.versions.last().cloned()), + versions: case.versions.clone(), + version_scheme: VersionScheme::from_str_lenient(&case.scheme), + tags: Vec::new(), + } +} - match (&case.expect.version, &case.expect.error) { - (Some(want), None) => { - let got = resolve_version(&metadata, &case.requirement).unwrap_or_else(|error| { - panic!("{}: expected {want}, got error {error}", case.name) - }); - assert_eq!(got, want, "{}", case.name); - } - (None, Some(want)) => { - let error = - resolve_version(&metadata, &case.requirement).unwrap_err_or_panic(&case.name); - assert_eq!(error.kind(), want, "{}", case.name); - } - _ => panic!( - "{}: a case declares exactly one of `version` or `error`", - case.name - ), +fn check_resolution(case: &Case, file: &str) { + let meta = metadata(case); + let requirement = case + .requirement + .as_deref() + .unwrap_or_else(|| panic!("{file}:{}: resolution cases need a `requirement`", case.name)); + match (&case.expect.version, &case.expect.error) { + (Some(want), None) => { + let got = resolve_version(&meta, requirement) + .unwrap_or_else(|error| panic!("{file}:{}: expected {want}, got {error}", case.name)); + assert_eq!(got, want, "{file}:{}", case.name); } + (None, Some(want)) => match resolve_version(&meta, requirement) { + Ok(version) => panic!("{file}:{}: expected {want}, resolved {version}", case.name), + Err(error) => assert_eq!(error.kind(), want, "{file}:{}", case.name), + }, + _ => panic!("{file}:{}: declare exactly one of `version` or `error`", case.name), } } -/// `Result::unwrap_err` needs `T: Debug`, which `&str` satisfies — but the -/// panic message would not say which case failed. -trait UnwrapErrOrPanic { - fn unwrap_err_or_panic(self, case: &str) -> E; +fn check_latest(case: &Case, file: &str) { + assert!( + case.expect.error.is_none(), + "{file}:{}: latest-stable cases cannot fail, they return null", + case.name + ); + let meta = metadata(case); + assert_eq!( + latest_stable(&meta), + case.expect.version.as_deref(), + "{file}:{}", + case.name + ); } -impl UnwrapErrOrPanic for Result { - fn unwrap_err_or_panic(self, case: &str) -> E { - match self { - Ok(value) => panic!("{case}: expected an error, resolved {value:?}"), - Err(error) => error, +#[test] +fn every_corpus_file_passes() { + let mut total = 0; + for path in corpus_files() { + let file = path.file_name().unwrap().to_string_lossy().to_string(); + let raw = fs::read_to_string(&path).expect("corpus file is readable"); + let corpus: Corpus = serde_json::from_str(&raw) + .unwrap_or_else(|error| panic!("{file} is not a valid corpus: {error}")); + assert!(!corpus.cases.is_empty(), "{file} has no cases"); + + for case in &corpus.cases { + match corpus.schema.as_str() { + RESOLUTION_SCHEMA => check_resolution(case, &file), + LATEST_SCHEMA => check_latest(case, &file), + other => panic!("{file}: unknown corpus schema `{other}`"), + } + total += 1; } } + // A loader bug that silently matched nothing would otherwise look like a + // clean run in every language at once. + assert!(total > 100, "expected the generated corpus too, ran only {total}"); + println!("ran {total} cases"); +} + +#[test] +fn the_generated_corpus_is_present_and_deterministic() { + let names: Vec = corpus_files() + .iter() + .map(|path| path.file_name().unwrap().to_string_lossy().to_string()) + .collect(); + for expected in [ + "version-resolution.json", + "latest-stable.json", + "fuzz-version-resolution.json", + "fuzz-latest-stable.json", + ] { + assert!( + names.iter().any(|name| name == expected), + "missing corpus file {expected}; run `cargo run --example generate_fuzz_corpus`" + ); + } } From 3b9bf6702a06cbe7a4ecbfe4631a92ecfae19307 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:27:30 -0500 Subject: [PATCH 34/38] claude autosave 2026-08-07T04:27:30Z --- conformance/cases/fuzz-latest-stable.json | 1406 +++++++++ .../cases/fuzz-version-resolution.json | 2806 +++++++++++++++++ src/rust/tests/conformance.rs | 14 +- 3 files changed, 4224 insertions(+), 2 deletions(-) create mode 100644 conformance/cases/fuzz-latest-stable.json create mode 100644 conformance/cases/fuzz-version-resolution.json diff --git a/conformance/cases/fuzz-latest-stable.json b/conformance/cases/fuzz-latest-stable.json new file mode 100644 index 0000000..e197c8b --- /dev/null +++ b/conformance/cases/fuzz-latest-stable.json @@ -0,0 +1,1406 @@ +{ + "schema": "zed-lib/conformance/latest-stable/v1", + "description": "GENERATED by `cargo run --example generate_fuzz_corpus` — do not edit by hand. Pseudo-random `latest_stable` cases answered by the Rust implementation.", + "cases": [ + { + "name": "fuzz/0", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/2", + "scheme": "semver", + "versions": ["1.2.9", "nightly", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/4", + "scheme": "semver", + "versions": ["0.1.0", "1.0.0", "10.0.0", "2.0.0"], + "latest": "2.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/6", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/8", + "scheme": "semver", + "versions": ["0.1.0", "1.2.3-beta.2", "10.0.0", "2.1.0", "2026.07.24", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/10", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.0", "1.2.9", "legacy-api", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/12", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/14", + "scheme": "calver", + "versions": ["0.1.0", "1.0.1", "nightly"], + "latest": "nightly", + "expect": { "version": "1.0.1" } + }, + { + "name": "fuzz/16", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/18", + "scheme": "opaque", + "versions": ["1.0.0", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/20", + "scheme": "opaque", + "versions": ["1.2.3rc1"], + "latest": "1.2.3rc1", + "expect": { "version": "1.2.3rc1" } + }, + { + "name": "fuzz/22", + "scheme": "opaque", + "versions": ["0.0.1"], + "latest": "0.0.1", + "expect": { "version": "0.0.1" } + }, + { + "name": "fuzz/24", + "scheme": "calver", + "versions": ["2.0.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/26", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.2.3-beta.2", "1.2.3rc1", "2.0.0-alpha.1"], + "latest": "2.0.0-alpha.1", + "expect": { "version": null } + }, + { + "name": "fuzz/28", + "scheme": "opaque", + "versions": ["1.3.0", "1.9.9"], + "latest": "1.9.9", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/30", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/32", + "scheme": "opaque", + "versions": ["0.1.0", "1.9.9", "2.0.0-alpha.1", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/34", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "2.0.0"], + "latest": "2.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/36", + "scheme": "calver", + "versions": ["0.1.0", "0.2.0", "1.2.9", "2026.06.01"], + "latest": "2026.06.01", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/38", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "1.3.0", "2.0.0", "2026.01.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/40", + "scheme": "calver", + "versions": ["nightly", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/42", + "scheme": "semver", + "versions": ["0.0.1", "0.1.9", "1.9.9", "2.0.0-alpha.1", "2026.06.01", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/44", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3-beta.2", "1.2.9", "nightly"], + "latest": "nightly", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/46", + "scheme": "opaque", + "versions": ["0.2.0", "1.2.3-beta.2", "1.9.9", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/48", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "1.9.9", "2.1.0", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/50", + "scheme": "opaque", + "versions": ["1.2.3rc1", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/52", + "scheme": "semver", + "versions": ["0.2.0", "1.0.0", "10.0.0", "2.0.0-alpha.1", "2026.07.24", "legacy-api"], + "latest": "legacy-api", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/54", + "scheme": "semver", + "versions": ["1.0.0", "10.0.0", "2.0.0", "2026.01.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/56", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.0", "1.2.3", "1.9.9", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/58", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3rc1", "10.0.0", "2.0.0-alpha.1"], + "latest": "2.0.0-alpha.1", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/60", + "scheme": "calver", + "versions": ["1.2.3", "1.2.3.post1", "1.9.9", "release-candidate-1", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/62", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.2.3.post1"], + "latest": "1.2.3.post1", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/64", + "scheme": "semver", + "versions": ["1.2.0"], + "latest": "1.2.0", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/66", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0"], + "latest": "1.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/68", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/70", + "scheme": "calver", + "versions": ["1.2.3", "1.3.0", "2.0.0"], + "latest": "2.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/72", + "scheme": "opaque", + "versions": ["10.0.0", "2026.01.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/74", + "scheme": "opaque", + "versions": ["0.0.1", "0.1.9", "2.1.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/76", + "scheme": "semver", + "versions": ["1.2.3rc1", "2026.06.01"], + "latest": "2026.06.01", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/78", + "scheme": "semver", + "versions": ["1.2.9", "2026.06.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/80", + "scheme": "calver", + "versions": ["0.2.0", "2.0.0-alpha.1", "legacy-api", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/82", + "scheme": "opaque", + "versions": ["0.2.0", "1.2.3-beta.2", "1.2.3rc1", "2026.06.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/84", + "scheme": "calver", + "versions": ["1.2.3"], + "latest": "1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/86", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/88", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/90", + "scheme": "calver", + "versions": ["1.0.1", "1.2.3-beta.2", "1.9.9", "nightly"], + "latest": "nightly", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/92", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/94", + "scheme": "calver", + "versions": ["1.0.0", "2.0.0"], + "latest": "2.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/96", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/98", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "2026.06.01", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/100", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/102", + "scheme": "calver", + "versions": ["1.2.0", "1.2.3-beta.2", "1.9.9", "2026.06.01", "legacy-api"], + "latest": "legacy-api", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/104", + "scheme": "opaque", + "versions": ["1.0.0", "2.1.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/106", + "scheme": "calver", + "versions": ["1.0.0", "1.0.0-rc.1", "1.3.0", "nightly", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/108", + "scheme": "opaque", + "versions": ["0.1.0", "1.9.9", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/110", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.3.post1", "1.2.9", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/112", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/114", + "scheme": "semver", + "versions": ["1.2.3rc1"], + "latest": "1.2.3rc1", + "expect": { "version": null } + }, + { + "name": "fuzz/116", + "scheme": "semver", + "versions": ["0.1.0", "1.2.3.post1", "1.2.3rc1", "2.1.0", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/118", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/120", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "1.0.0-rc.1", "nightly", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/122", + "scheme": "opaque", + "versions": ["1.2.3-beta.2", "10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/124", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/126", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/128", + "scheme": "semver", + "versions": ["0.0.1", "0.1.0", "10.0.0", "2.0.0-alpha.1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/130", + "scheme": "semver", + "versions": ["2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/132", + "scheme": "calver", + "versions": ["1.2.0", "1.2.3.post1", "1.2.9", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/134", + "scheme": "semver", + "versions": ["1.0.0", "2026.01.01", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/136", + "scheme": "semver", + "versions": ["0.0.1", "1.0.1", "1.2.3-beta.2", "2026.06.01", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/138", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0", "2026.01.01", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/140", + "scheme": "semver", + "versions": ["0.1.9", "2026.10.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/142", + "scheme": "semver", + "versions": ["0.2.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/144", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/146", + "scheme": "opaque", + "versions": ["1.0.0-rc.1", "1.2.3.post1", "1.3.0", "1.9.9"], + "latest": "1.9.9", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/148", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/150", + "scheme": "calver", + "versions": ["0.2.0", "2026.01.01", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/152", + "scheme": "calver", + "versions": ["release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": null } + }, + { + "name": "fuzz/154", + "scheme": "opaque", + "versions": ["v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/156", + "scheme": "calver", + "versions": ["0.2.0", "1.0.0-rc.1", "1.0.1", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/158", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/160", + "scheme": "semver", + "versions": ["0.1.9", "1.9.9", "2026.06.01", "nightly"], + "latest": "nightly", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/162", + "scheme": "semver", + "versions": ["0.1.0", "1.2.9", "2.0.0-alpha.1", "release-candidate-1", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/164", + "scheme": "calver", + "versions": ["0.2.0", "1.2.3", "2026.07.24", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/166", + "scheme": "opaque", + "versions": ["0.1.0", "1.2.3-beta.2"], + "latest": "1.2.3-beta.2", + "expect": { "version": "1.2.3-beta.2" } + }, + { + "name": "fuzz/168", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/170", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.9"], + "latest": "1.2.9", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/172", + "scheme": "calver", + "versions": ["1.0.0", "1.2.3-beta.2", "1.3.0"], + "latest": "1.3.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/174", + "scheme": "opaque", + "versions": ["1.2.3rc1", "10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/176", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3-beta.2", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/178", + "scheme": "calver", + "versions": ["0.2.0", "1.2.0", "1.3.0", "2.0.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/180", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/182", + "scheme": "calver", + "versions": ["0.2.0", "1.2.3-beta.2", "1.2.3.post1", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/184", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/186", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "2.0.0-alpha.1"], + "latest": "2.0.0-alpha.1", + "expect": { "version": "0.2.0" } + }, + { + "name": "fuzz/188", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/190", + "scheme": "calver", + "versions": ["1.2.3", "10.0.0", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/192", + "scheme": "semver", + "versions": ["1.2.3.post1"], + "latest": "1.2.3.post1", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/194", + "scheme": "opaque", + "versions": ["1.2.0", "2.0.0", "release-candidate-1", "v1.0.0", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/196", + "scheme": "calver", + "versions": ["0.1.0", "nightly"], + "latest": "nightly", + "expect": { "version": "0.1.0" } + }, + { + "name": "fuzz/198", + "scheme": "calver", + "versions": ["2.0.0-alpha.1", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": null } + }, + { + "name": "fuzz/200", + "scheme": "opaque", + "versions": ["0.1.9", "1.2.3.post1", "2.0.0", "2026.10.01", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/202", + "scheme": "opaque", + "versions": ["0.1.9", "1.0.0", "1.2.3-beta.2", "2.0.0", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/204", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3rc1", "2.0.0", "2.1.0"], + "latest": "2.1.0", + "expect": { "version": "2.1.0" } + }, + { + "name": "fuzz/206", + "scheme": "semver", + "versions": ["0.0.1", "1.2.0", "1.2.9", "1.3.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/208", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.3rc1"], + "latest": "1.2.3rc1", + "expect": { "version": null } + }, + { + "name": "fuzz/210", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3", "1.2.3rc1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/212", + "scheme": "semver", + "versions": ["1.2.3.post1", "10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/214", + "scheme": "opaque", + "versions": ["2.1.0", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/216", + "scheme": "opaque", + "versions": ["1.0.1"], + "latest": "1.0.1", + "expect": { "version": "1.0.1" } + }, + { + "name": "fuzz/218", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3.post1", "2.0.0-alpha.1", "2.1.0", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/220", + "scheme": "calver", + "versions": ["0.1.0", "1.2.3", "1.2.3-beta.2", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/222", + "scheme": "opaque", + "versions": ["1.0.0"], + "latest": "1.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/224", + "scheme": "calver", + "versions": ["1.2.0", "1.3.0", "legacy-api", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/226", + "scheme": "semver", + "versions": ["0.0.1", "1.0.0", "1.0.0-rc.1", "1.2.3-beta.2", "1.2.3rc1", "1.3.0"], + "latest": "1.3.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/228", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "2.1.0", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/230", + "scheme": "opaque", + "versions": ["0.1.9", "1.2.0", "1.3.0", "10.0.0", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/232", + "scheme": "semver", + "versions": ["0.1.0", "2026.10.01", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/234", + "scheme": "calver", + "versions": ["1.2.3.post1", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/236", + "scheme": "opaque", + "versions": ["10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/238", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "1.2.3rc1", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/240", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3", "1.9.9", "2.0.0-alpha.1", "2.1.0", "legacy-api"], + "latest": "legacy-api", + "expect": { "version": "legacy-api" } + }, + { + "name": "fuzz/242", + "scheme": "calver", + "versions": ["0.1.0", "2.0.0", "2.1.0"], + "latest": "2.1.0", + "expect": { "version": "2.1.0" } + }, + { + "name": "fuzz/244", + "scheme": "semver", + "versions": ["2.1.0", "2026.01.01", "nightly", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/246", + "scheme": "calver", + "versions": ["nightly"], + "latest": "nightly", + "expect": { "version": null } + }, + { + "name": "fuzz/248", + "scheme": "calver", + "versions": ["0.2.0", "1.0.0-rc.1", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/250", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/252", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/254", + "scheme": "opaque", + "versions": ["nightly"], + "latest": "nightly", + "expect": { "version": "nightly" } + }, + { + "name": "fuzz/256", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/258", + "scheme": "opaque", + "versions": ["0.1.9", "1.0.0", "1.2.9", "2.1.0", "2026.10.01", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/260", + "scheme": "semver", + "versions": ["0.0.1", "1.9.9", "2.0.0", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/262", + "scheme": "semver", + "versions": ["0.0.1", "0.1.9", "1.0.1", "1.2.3.post1", "nightly", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/264", + "scheme": "calver", + "versions": ["1.2.3", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/266", + "scheme": "semver", + "versions": ["0.0.1", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/268", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/270", + "scheme": "calver", + "versions": ["1.3.0", "1.9.9", "2.0.0-alpha.1", "2026.07.24", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/272", + "scheme": "semver", + "versions": ["0.1.9", "1.0.1", "1.3.0", "2026.06.01", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/274", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/276", + "scheme": "calver", + "versions": ["0.0.1", "1.2.0", "2026.07.24", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/278", + "scheme": "semver", + "versions": ["1.3.0"], + "latest": "1.3.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/280", + "scheme": "opaque", + "versions": ["1.2.9", "1.3.0", "2.1.0", "2026.06.01", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/282", + "scheme": "opaque", + "versions": ["2.0.0", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/284", + "scheme": "calver", + "versions": ["0.1.9", "10.0.0", "2026.07.24", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/286", + "scheme": "calver", + "versions": ["1.0.0-rc.1"], + "latest": "1.0.0-rc.1", + "expect": { "version": null } + }, + { + "name": "fuzz/288", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/290", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "2.0.0", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/292", + "scheme": "calver", + "versions": ["1.3.0", "legacy-api"], + "latest": "legacy-api", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/294", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/296", + "scheme": "opaque", + "versions": ["0.1.0", "0.1.9", "1.0.0-rc.1", "10.0.0", "2.0.0"], + "latest": "2.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/298", + "scheme": "opaque", + "versions": ["1.2.9", "1.3.0"], + "latest": "1.3.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/300", + "scheme": "semver", + "versions": ["0.0.1", "1.9.9", "2.0.0", "2.0.0-alpha.1", "2026.01.01", "2026.06.01"], + "latest": "2026.06.01", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/302", + "scheme": "semver", + "versions": ["0.2.0", "1.0.0", "1.0.1", "1.2.3.post1", "2.0.0-alpha.1", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/304", + "scheme": "opaque", + "versions": ["1.2.0", "1.2.3", "1.9.9", "2.0.0", "2.0.0-alpha.1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/306", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/308", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/310", + "scheme": "opaque", + "versions": ["1.0.0-rc.1", "1.2.0", "1.2.3.post1", "1.2.3rc1", "10.0.0", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/312", + "scheme": "opaque", + "versions": ["1.0.0"], + "latest": "1.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/314", + "scheme": "calver", + "versions": ["1.2.0", "10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/316", + "scheme": "calver", + "versions": ["1.0.0"], + "latest": "1.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/318", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/320", + "scheme": "semver", + "versions": ["0.0.1", "1.2.9", "2.1.0", "release-candidate-1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2.1.0" } + }, + { + "name": "fuzz/322", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/324", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/326", + "scheme": "opaque", + "versions": ["1.9.9"], + "latest": "1.9.9", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/328", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "1.9.9", "2.0.0", "release-candidate-1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/330", + "scheme": "calver", + "versions": ["0.1.0", "0.2.0", "1.0.1", "1.2.3.post1", "10.0.0"], + "latest": "10.0.0", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/332", + "scheme": "semver", + "versions": ["1.3.0", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/334", + "scheme": "opaque", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/336", + "scheme": "opaque", + "versions": ["1.2.0", "1.2.3", "1.2.3-beta.2", "2.1.0", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "release-candidate-1" } + }, + { + "name": "fuzz/338", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/340", + "scheme": "calver", + "versions": ["1.3.0"], + "latest": "1.3.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/342", + "scheme": "opaque", + "versions": ["0.1.9", "10.0.0", "2026.06.01", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/344", + "scheme": "opaque", + "versions": ["1.2.3-beta.2"], + "latest": "1.2.3-beta.2", + "expect": { "version": "1.2.3-beta.2" } + }, + { + "name": "fuzz/346", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0", "1.9.9", "2.1.0", "2026.01.01", "nightly"], + "latest": "nightly", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/348", + "scheme": "calver", + "versions": ["0.0.1", "1.9.9", "2026.01.01", "2026.07.24"], + "latest": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/350", + "scheme": "semver", + "versions": ["0.1.9", "1.0.0", "1.9.9", "2.0.0-alpha.1", "nightly"], + "latest": "nightly", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/352", + "scheme": "semver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/354", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3", "1.2.9", "1.9.9", "2026.06.01"], + "latest": "2026.06.01", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/356", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3.post1", "2.0.0-alpha.1", "2026.07.24", "release-candidate-1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/358", + "scheme": "calver", + "versions": ["0.1.9", "1.0.0", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/360", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "10.0.0", "nightly", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "10.0.0" } + }, + { + "name": "fuzz/362", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "2.0.0-alpha.1", "2.1.0", "2026.06.01"], + "latest": "2026.06.01", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/364", + "scheme": "calver", + "versions": ["2026.01.01", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/366", + "scheme": "semver", + "versions": ["1.2.9"], + "latest": "1.2.9", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/368", + "scheme": "opaque", + "versions": ["0.0.1", "0.1.9", "1.9.9", "v1.0.0", "v2.0.0+incompatible"], + "latest": "v2.0.0+incompatible", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/370", + "scheme": "semver", + "versions": ["0.0.1", "1.0.0", "1.0.1", "1.2.0", "1.2.3", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/372", + "scheme": "calver", + "versions": ["1.0.0-rc.1", "1.9.9", "2.0.0", "2.0.0-alpha.1"], + "latest": "2.0.0-alpha.1", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/374", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0-rc.1", "1.2.3-beta.2", "1.9.9", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/376", + "scheme": "semver", + "versions": ["1.2.0", "1.2.3-beta.2", "1.2.9", "legacy-api"], + "latest": "legacy-api", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/378", + "scheme": "calver", + "versions": [], + "latest": null, + "expect": { "version": null } + }, + { + "name": "fuzz/380", + "scheme": "semver", + "versions": ["0.0.1", "0.1.0", "1.3.0", "2026.06.01", "2026.07.24", "nightly"], + "latest": "nightly", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/382", + "scheme": "calver", + "versions": ["1.0.0", "1.2.3.post1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/384", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "release-candidate-1"], + "latest": "release-candidate-1", + "expect": { "version": null } + }, + { + "name": "fuzz/386", + "scheme": "opaque", + "versions": ["0.1.9", "2026.10.01"], + "latest": "2026.10.01", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/388", + "scheme": "opaque", + "versions": ["1.2.3"], + "latest": "1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/390", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3-beta.2"], + "latest": "1.2.3-beta.2", + "expect": { "version": "0.0.1" } + }, + { + "name": "fuzz/392", + "scheme": "calver", + "versions": ["1.2.3", "1.2.3-beta.2", "1.2.3rc1", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/394", + "scheme": "opaque", + "versions": ["1.2.3", "2026.01.01"], + "latest": "2026.01.01", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/396", + "scheme": "semver", + "versions": ["1.2.3", "1.3.0", "10.0.0", "2026.01.01", "2026.10.01", "v1.0.0"], + "latest": "v1.0.0", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/398", + "scheme": "semver", + "versions": ["1.9.9", "2.1.0"], + "latest": "2.1.0", + "expect": { "version": "2.1.0" } + } + ] +} diff --git a/conformance/cases/fuzz-version-resolution.json b/conformance/cases/fuzz-version-resolution.json new file mode 100644 index 0000000..d6977c7 --- /dev/null +++ b/conformance/cases/fuzz-version-resolution.json @@ -0,0 +1,2806 @@ +{ + "schema": "zed-lib/conformance/version-resolution/v1", + "description": "GENERATED by `cargo run --example generate_fuzz_corpus` — do not edit by hand. Pseudo-random cases answered by the Rust implementation, which every other slice must reproduce. Deterministic: regenerating rewrites this file byte for byte.", + "cases": [ + { + "name": "fuzz/0", + "scheme": "semver", + "versions": [], + "requirement": "^0.0.1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/1", + "scheme": "opaque", + "versions": ["0.1.9", "1.2.3-beta.2", "1.2.9", "2.0.0", "2.0.0-alpha.1", "2026.01.01"], + "requirement": "~1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/2", + "scheme": "semver", + "versions": ["1.2.9", "nightly", "v1.0.0"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/3", + "scheme": "opaque", + "versions": ["0.1.9"], + "requirement": ">=1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/4", + "scheme": "semver", + "versions": ["0.1.0", "1.0.0", "10.0.0", "2.0.0"], + "requirement": "1", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/5", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "1.0.0-rc.1", "2.1.0", "2026.10.01", "v2.0.0+incompatible"], + "requirement": ">1.0.0", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/6", + "scheme": "semver", + "versions": [], + "requirement": "1.x", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/7", + "scheme": "opaque", + "versions": ["0.2.0", "1.3.0", "1.9.9", "2026.06.01", "nightly", "v2.0.0+incompatible"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/8", + "scheme": "semver", + "versions": ["0.1.0", "1.2.3-beta.2", "10.0.0", "2.1.0", "2026.07.24", "2026.10.01"], + "requirement": "1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/9", + "scheme": "semver", + "versions": ["0.1.9", "0.2.0", "1.2.3rc1", "2026.07.24"], + "requirement": "1.x", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/10", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.0", "1.2.9", "legacy-api", "release-candidate-1"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/11", + "scheme": "calver", + "versions": ["1.0.1", "1.9.9", "2.0.0", "2026.06.01"], + "requirement": "<2.0.0", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/12", + "scheme": "calver", + "versions": [], + "requirement": "^1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/13", + "scheme": "semver", + "versions": ["0.1.9", "0.2.0", "1.0.0-rc.1", "2026.01.01", "release-candidate-1"], + "requirement": "*", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/14", + "scheme": "calver", + "versions": ["0.1.0", "1.0.1", "nightly"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/15", + "scheme": "semver", + "versions": ["1.3.0", "2.0.0-alpha.1", "2.1.0", "v2.0.0+incompatible"], + "requirement": "1.*", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/16", + "scheme": "calver", + "versions": [], + "requirement": "*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/17", + "scheme": "semver", + "versions": ["1.2.3.post1", "1.2.9", "1.9.9", "10.0.0", "2.1.0", "2026.07.24"], + "requirement": "^1.2", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/18", + "scheme": "opaque", + "versions": ["1.0.0", "2026.07.24"], + "requirement": "^0.0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/19", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "1.2.3.post1", "1.2.3rc1", "2026.07.24", "release-candidate-1"], + "requirement": "1.2.3", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/20", + "scheme": "opaque", + "versions": ["1.2.3rc1"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/21", + "scheme": "semver", + "versions": ["1.9.9", "2.1.0", "nightly", "v2.0.0+incompatible"], + "requirement": "1.x", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/22", + "scheme": "opaque", + "versions": ["0.0.1"], + "requirement": "^2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/23", + "scheme": "semver", + "versions": ["1.2.3", "1.2.9", "1.3.0"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/24", + "scheme": "calver", + "versions": ["2.0.0", "v1.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/25", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3-beta.2", "1.2.3rc1"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/26", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.2.3-beta.2", "1.2.3rc1", "2.0.0-alpha.1"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/27", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.0-rc.1", "1.0.1", "2.0.0-alpha.1", "nightly"], + "requirement": "~1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/28", + "scheme": "opaque", + "versions": ["1.3.0", "1.9.9"], + "requirement": "1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/29", + "scheme": "opaque", + "versions": ["1.2.9", "10.0.0", "2026.07.24"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/30", + "scheme": "calver", + "versions": [], + "requirement": "^2026", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/31", + "scheme": "opaque", + "versions": ["1.2.3.post1", "1.3.0", "2.1.0", "2026.10.01"], + "requirement": "^0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/32", + "scheme": "opaque", + "versions": ["0.1.0", "1.9.9", "2.0.0-alpha.1", "2026.07.24"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/33", + "scheme": "calver", + "versions": ["1.0.0-rc.1", "1.2.3rc1", "1.9.9", "v1.0.0"], + "requirement": "^0.0.1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/34", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "2.0.0"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/35", + "scheme": "calver", + "versions": ["0.1.0", "1.2.3rc1", "2026.06.01"], + "requirement": "1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/36", + "scheme": "calver", + "versions": ["0.1.0", "0.2.0", "1.2.9", "2026.06.01"], + "requirement": "<=1.2.3", + "expect": { "version": "0.2.0" } + }, + { + "name": "fuzz/37", + "scheme": "calver", + "versions": ["2.1.0"], + "requirement": "=1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/38", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "1.3.0", "2.0.0", "2026.01.01", "release-candidate-1"], + "requirement": "<=1.2.3", + "expect": { "version": "0.2.0" } + }, + { + "name": "fuzz/39", + "scheme": "calver", + "versions": ["1.2.3rc1", "10.0.0", "2.1.0", "2026.06.01"], + "requirement": "1.x", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/40", + "scheme": "calver", + "versions": ["nightly", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/41", + "scheme": "calver", + "versions": ["1.0.1", "2.0.0", "2026.06.01", "legacy-api", "v1.0.0"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/42", + "scheme": "semver", + "versions": ["0.0.1", "0.1.9", "1.9.9", "2.0.0-alpha.1", "2026.06.01", "2026.10.01"], + "requirement": "1.2.3", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/43", + "scheme": "opaque", + "versions": ["0.0.1", "1.0.0-rc.1", "1.3.0"], + "requirement": "~1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/44", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3-beta.2", "1.2.9", "nightly"], + "requirement": "1.2.3", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/45", + "scheme": "opaque", + "versions": ["1.2.0", "2026.01.01"], + "requirement": ">=2026.7", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/46", + "scheme": "opaque", + "versions": ["0.2.0", "1.2.3-beta.2", "1.9.9", "v2.0.0+incompatible"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/47", + "scheme": "semver", + "versions": ["0.1.0", "1.9.9"], + "requirement": "^0.1", + "expect": { "version": "0.1.0" } + }, + { + "name": "fuzz/48", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "1.9.9", "2.1.0", "v2.0.0+incompatible"], + "requirement": "~1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/49", + "scheme": "opaque", + "versions": ["0.0.1"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/50", + "scheme": "opaque", + "versions": ["1.2.3rc1", "release-candidate-1"], + "requirement": "1.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/51", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "2.0.0"], + "requirement": "^1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/52", + "scheme": "semver", + "versions": ["0.2.0", "1.0.0", "10.0.0", "2.0.0-alpha.1", "2026.07.24", "legacy-api"], + "requirement": "*", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/53", + "scheme": "calver", + "versions": ["0.2.0", "1.3.0", "2026.07.24"], + "requirement": "1.*", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/54", + "scheme": "semver", + "versions": ["1.0.0", "10.0.0", "2.0.0", "2026.01.01", "release-candidate-1"], + "requirement": "~1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/55", + "scheme": "opaque", + "versions": ["0.1.9", "1.9.9"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/56", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.0", "1.2.3", "1.9.9", "release-candidate-1"], + "requirement": "^1.x.y", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/57", + "scheme": "opaque", + "versions": ["1.3.0", "2026.06.01", "2026.10.01", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/58", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3rc1", "10.0.0", "2.0.0-alpha.1"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/59", + "scheme": "opaque", + "versions": ["1.9.9", "v2.0.0+incompatible"], + "requirement": "1.x", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/60", + "scheme": "calver", + "versions": ["1.2.3", "1.2.3.post1", "1.9.9", "release-candidate-1", "v2.0.0+incompatible"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/61", + "scheme": "opaque", + "versions": ["1.9.9"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/62", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.2.3.post1"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/63", + "scheme": "opaque", + "versions": ["1.2.3"], + "requirement": "1.x", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/64", + "scheme": "semver", + "versions": ["1.2.0"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/65", + "scheme": "opaque", + "versions": ["1.2.3rc1"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/66", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0"], + "requirement": "1.x", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/67", + "scheme": "opaque", + "versions": ["2026.01.01", "2026.10.01"], + "requirement": ">=2026.7", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/68", + "scheme": "calver", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/69", + "scheme": "calver", + "versions": ["2026.07.24"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/70", + "scheme": "calver", + "versions": ["1.2.3", "1.3.0", "2.0.0"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/71", + "scheme": "semver", + "versions": ["1.2.3rc1", "nightly"], + "requirement": "<=1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/72", + "scheme": "opaque", + "versions": ["10.0.0", "2026.01.01", "release-candidate-1"], + "requirement": "~1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/73", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3.post1", "1.9.9", "10.0.0", "2.0.0", "v1.0.0"], + "requirement": "=1.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/74", + "scheme": "opaque", + "versions": ["0.0.1", "0.1.9", "2.1.0", "v1.0.0"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/75", + "scheme": "calver", + "versions": ["10.0.0"], + "requirement": "1.x", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/76", + "scheme": "semver", + "versions": ["1.2.3rc1", "2026.06.01"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/77", + "scheme": "calver", + "versions": ["1.0.1", "1.2.3-beta.2", "legacy-api"], + "requirement": ">=1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/78", + "scheme": "semver", + "versions": ["1.2.9", "2026.06.01", "release-candidate-1"], + "requirement": ">1.0.0", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/79", + "scheme": "semver", + "versions": ["1.2.3.post1"], + "requirement": "1.*", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/80", + "scheme": "calver", + "versions": ["0.2.0", "2.0.0-alpha.1", "legacy-api", "v1.0.0"], + "requirement": "1.*", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/81", + "scheme": "opaque", + "versions": [], + "requirement": "^1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/82", + "scheme": "opaque", + "versions": ["0.2.0", "1.2.3-beta.2", "1.2.3rc1", "2026.06.01", "release-candidate-1"], + "requirement": "<2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/83", + "scheme": "calver", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/84", + "scheme": "calver", + "versions": ["1.2.3"], + "requirement": "~1.2", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/85", + "scheme": "opaque", + "versions": [], + "requirement": ">=1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/86", + "scheme": "calver", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/87", + "scheme": "semver", + "versions": ["0.0.1", "2.1.0"], + "requirement": "^1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/88", + "scheme": "opaque", + "versions": [], + "requirement": "1.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/89", + "scheme": "opaque", + "versions": ["1.2.3.post1", "2026.01.01", "2026.06.01", "2026.07.24", "legacy-api", "nightly"], + "requirement": "=1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/90", + "scheme": "calver", + "versions": ["1.0.1", "1.2.3-beta.2", "1.9.9", "nightly"], + "requirement": "~1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/91", + "scheme": "semver", + "versions": ["0.1.9", "1.2.0", "2.1.0"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/92", + "scheme": "calver", + "versions": [], + "requirement": "~1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/93", + "scheme": "calver", + "versions": [], + "requirement": "^0.0.1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/94", + "scheme": "calver", + "versions": ["1.0.0", "2.0.0"], + "requirement": "^2", + "expect": { "version": "2.0.0" } + }, + { + "name": "fuzz/95", + "scheme": "calver", + "versions": ["1.2.0"], + "requirement": "<=1.2.3", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/96", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "2026.07.24"], + "requirement": "~1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/97", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.0-rc.1", "2.1.0"], + "requirement": "<2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/98", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "2026.06.01", "v2.0.0+incompatible"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/99", + "scheme": "calver", + "versions": ["1.2.3rc1", "2026.01.01"], + "requirement": "*", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/100", + "scheme": "calver", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/101", + "scheme": "semver", + "versions": ["2.0.0-alpha.1", "2026.06.01", "2026.10.01", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/102", + "scheme": "calver", + "versions": ["1.2.0", "1.2.3-beta.2", "1.9.9", "2026.06.01", "legacy-api"], + "requirement": "^1.2", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/103", + "scheme": "calver", + "versions": ["1.9.9", "2.0.0-alpha.1", "2.1.0"], + "requirement": "1.2.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/104", + "scheme": "opaque", + "versions": ["1.0.0", "2.1.0", "v1.0.0"], + "requirement": "1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/105", + "scheme": "semver", + "versions": ["0.1.0", "1.2.3", "1.2.3-beta.2", "1.2.3.post1"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/106", + "scheme": "calver", + "versions": ["1.0.0", "1.0.0-rc.1", "1.3.0", "nightly", "v2.0.0+incompatible"], + "requirement": "1.2.3", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/107", + "scheme": "calver", + "versions": ["2026.06.01", "legacy-api", "v1.0.0"], + "requirement": "=1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/108", + "scheme": "opaque", + "versions": ["0.1.0", "1.9.9", "v1.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/109", + "scheme": "semver", + "versions": [], + "requirement": "2026.07.24", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/110", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.3.post1", "1.2.9", "2026.01.01"], + "requirement": "^0.0.1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/111", + "scheme": "semver", + "versions": ["1.9.9", "release-candidate-1", "v1.0.0"], + "requirement": "^2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/112", + "scheme": "calver", + "versions": [], + "requirement": "^1.x.y", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/113", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.0.1", "2026.06.01"], + "requirement": "1", + "expect": { "version": "1.0.1" } + }, + { + "name": "fuzz/114", + "scheme": "semver", + "versions": ["1.2.3rc1"], + "requirement": "~1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/115", + "scheme": "calver", + "versions": ["10.0.0", "v1.0.0"], + "requirement": "^2026", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/116", + "scheme": "semver", + "versions": ["0.1.0", "1.2.3.post1", "1.2.3rc1", "2.1.0", "2026.01.01"], + "requirement": "^1.2", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/117", + "scheme": "opaque", + "versions": [], + "requirement": "^1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/118", + "scheme": "semver", + "versions": [], + "requirement": ">=2026.7", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/119", + "scheme": "opaque", + "versions": ["0.0.1", "0.2.0", "1.2.3.post1", "legacy-api", "v1.0.0"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/120", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "1.0.0-rc.1", "nightly", "v1.0.0"], + "requirement": "*", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/121", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3.post1", "1.9.9", "2026.01.01", "v1.0.0"], + "requirement": "^1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/122", + "scheme": "opaque", + "versions": ["1.2.3-beta.2", "10.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/123", + "scheme": "opaque", + "versions": ["2.1.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/124", + "scheme": "semver", + "versions": [], + "requirement": "1.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/125", + "scheme": "semver", + "versions": [], + "requirement": "^1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/126", + "scheme": "opaque", + "versions": [], + "requirement": ">1.0.0", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/127", + "scheme": "opaque", + "versions": ["2026.01.01", "v1.0.0"], + "requirement": "^1.x.y", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/128", + "scheme": "semver", + "versions": ["0.0.1", "0.1.0", "10.0.0", "2.0.0-alpha.1", "v1.0.0"], + "requirement": "~1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/129", + "scheme": "calver", + "versions": [], + "requirement": "<=1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/130", + "scheme": "semver", + "versions": ["2026.01.01"], + "requirement": "^1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/131", + "scheme": "semver", + "versions": ["1.2.3", "1.2.3rc1", "1.3.0", "2.0.0-alpha.1", "legacy-api"], + "requirement": "1.x", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/132", + "scheme": "calver", + "versions": ["1.2.0", "1.2.3.post1", "1.2.9", "v2.0.0+incompatible"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/133", + "scheme": "semver", + "versions": ["1.2.3.post1", "10.0.0", "2.0.0", "legacy-api"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/134", + "scheme": "semver", + "versions": ["1.0.0", "2026.01.01", "2026.07.24"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/135", + "scheme": "semver", + "versions": ["1.9.9", "10.0.0", "2026.07.24", "v1.0.0"], + "requirement": "^2026", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/136", + "scheme": "semver", + "versions": ["0.0.1", "1.0.1", "1.2.3-beta.2", "2026.06.01", "2026.07.24"], + "requirement": "1", + "expect": { "version": "1.0.1" } + }, + { + "name": "fuzz/137", + "scheme": "opaque", + "versions": ["1.3.0", "2026.01.01", "2026.06.01", "v1.0.0"], + "requirement": "~1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/138", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0", "2026.01.01", "2026.10.01"], + "requirement": ">=1.2", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/139", + "scheme": "semver", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/140", + "scheme": "semver", + "versions": ["0.1.9", "2026.10.01", "release-candidate-1"], + "requirement": ">=2026.7", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/141", + "scheme": "opaque", + "versions": ["0.0.1"], + "requirement": "^2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/142", + "scheme": "semver", + "versions": ["0.2.0", "v1.0.0"], + "requirement": "<2.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/143", + "scheme": "semver", + "versions": ["2026.07.24"], + "requirement": ">=1.2", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/144", + "scheme": "semver", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/145", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3rc1", "1.9.9", "2026.07.24", "nightly", "v1.0.0"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/146", + "scheme": "opaque", + "versions": ["1.0.0-rc.1", "1.2.3.post1", "1.3.0", "1.9.9"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/147", + "scheme": "calver", + "versions": ["1.2.0", "10.0.0", "legacy-api", "v2.0.0+incompatible"], + "requirement": "~1", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/148", + "scheme": "calver", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/149", + "scheme": "semver", + "versions": ["0.1.9", "1.2.9", "2.0.0-alpha.1"], + "requirement": ">1.0.0", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/150", + "scheme": "calver", + "versions": ["0.2.0", "2026.01.01", "2026.07.24"], + "requirement": "~1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/151", + "scheme": "opaque", + "versions": ["1.2.3", "1.2.3-beta.2", "1.3.0", "10.0.0", "2026.06.01", "2026.10.01"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/152", + "scheme": "calver", + "versions": ["release-candidate-1"], + "requirement": "1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/153", + "scheme": "calver", + "versions": ["0.1.0", "1.0.1", "2.0.0-alpha.1", "2026.01.01", "2026.06.01", "2026.10.01"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/154", + "scheme": "opaque", + "versions": ["v2.0.0+incompatible"], + "requirement": "^1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/155", + "scheme": "semver", + "versions": ["1.2.9", "10.0.0"], + "requirement": "=1.2", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/156", + "scheme": "calver", + "versions": ["0.2.0", "1.0.0-rc.1", "1.0.1", "2026.07.24"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/157", + "scheme": "opaque", + "versions": ["0.2.0", "2.0.0", "2026.10.01", "legacy-api", "release-candidate-1"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/158", + "scheme": "opaque", + "versions": [], + "requirement": ">=1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/159", + "scheme": "semver", + "versions": ["0.1.9", "1.2.0", "1.2.3rc1", "2026.07.24"], + "requirement": "~1.2", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/160", + "scheme": "semver", + "versions": ["0.1.9", "1.9.9", "2026.06.01", "nightly"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/161", + "scheme": "opaque", + "versions": [], + "requirement": "^1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/162", + "scheme": "semver", + "versions": ["0.1.0", "1.2.9", "2.0.0-alpha.1", "release-candidate-1", "v2.0.0+incompatible"], + "requirement": "=1.2", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/163", + "scheme": "calver", + "versions": ["0.2.0", "2026.06.01"], + "requirement": "~1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/164", + "scheme": "calver", + "versions": ["0.2.0", "1.2.3", "2026.07.24", "2026.10.01"], + "requirement": "^0.1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/165", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "1.2.9", "1.3.0", "10.0.0", "2.1.0", "v2.0.0+incompatible"], + "requirement": "~1.2.3", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/166", + "scheme": "opaque", + "versions": ["0.1.0", "1.2.3-beta.2"], + "requirement": "~1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/167", + "scheme": "semver", + "versions": ["0.0.1", "2026.06.01", "2026.10.01", "release-candidate-1"], + "requirement": "1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/168", + "scheme": "opaque", + "versions": [], + "requirement": "1.2.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/169", + "scheme": "opaque", + "versions": ["1.0.0", "1.2.3-beta.2", "2.0.0-alpha.1", "2.1.0", "v2.0.0+incompatible"], + "requirement": "1.x", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/170", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.9"], + "requirement": "<=1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/171", + "scheme": "calver", + "versions": ["0.1.0"], + "requirement": ">=1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/172", + "scheme": "calver", + "versions": ["1.0.0", "1.2.3-beta.2", "1.3.0"], + "requirement": "1.2.3", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/173", + "scheme": "semver", + "versions": ["1.2.9", "2026.06.01"], + "requirement": "1.2.*", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/174", + "scheme": "opaque", + "versions": ["1.2.3rc1", "10.0.0"], + "requirement": "1.x", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/175", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "10.0.0", "2.1.0", "nightly"], + "requirement": "nightly", + "expect": { "version": "nightly" } + }, + { + "name": "fuzz/176", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3-beta.2", "v2.0.0+incompatible"], + "requirement": ">1.0.0", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/177", + "scheme": "opaque", + "versions": ["v1.0.0"], + "requirement": "~1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/178", + "scheme": "calver", + "versions": ["0.2.0", "1.2.0", "1.3.0", "2.0.0", "v1.0.0"], + "requirement": "^1", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/179", + "scheme": "calver", + "versions": ["0.0.1", "1.2.3", "2026.10.01", "nightly", "v1.0.0"], + "requirement": ">1.0.0", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/180", + "scheme": "calver", + "versions": [], + "requirement": "1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/181", + "scheme": "opaque", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/182", + "scheme": "calver", + "versions": ["0.2.0", "1.2.3-beta.2", "1.2.3.post1", "2026.07.24"], + "requirement": "~1.2", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/183", + "scheme": "semver", + "versions": ["1.2.3-beta.2"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/184", + "scheme": "opaque", + "versions": [], + "requirement": "1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/185", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "1.2.3rc1", "2.0.0-alpha.1", "2026.01.01", "legacy-api"], + "requirement": "1.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/186", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "2.0.0-alpha.1"], + "requirement": "^1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/187", + "scheme": "opaque", + "versions": [], + "requirement": "^1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/188", + "scheme": "calver", + "versions": [], + "requirement": "<=1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/189", + "scheme": "semver", + "versions": ["0.0.1", "0.2.0"], + "requirement": "1.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/190", + "scheme": "calver", + "versions": ["1.2.3", "10.0.0", "2026.07.24"], + "requirement": "1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/191", + "scheme": "calver", + "versions": ["2.0.0-alpha.1"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/192", + "scheme": "semver", + "versions": ["1.2.3.post1"], + "requirement": ">=1.2 <2", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/193", + "scheme": "semver", + "versions": ["2026.01.01"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/194", + "scheme": "opaque", + "versions": ["1.2.0", "2.0.0", "release-candidate-1", "v1.0.0", "v2.0.0+incompatible"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/195", + "scheme": "calver", + "versions": ["0.0.1", "0.2.0", "1.0.1", "10.0.0"], + "requirement": "1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/196", + "scheme": "calver", + "versions": ["0.1.0", "nightly"], + "requirement": "~1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/197", + "scheme": "calver", + "versions": [], + "requirement": "2026.07.24", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/198", + "scheme": "calver", + "versions": ["2.0.0-alpha.1", "release-candidate-1"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/199", + "scheme": "semver", + "versions": ["0.2.0", "1.0.0", "2.0.0-alpha.1"], + "requirement": "<2.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/200", + "scheme": "opaque", + "versions": ["0.1.9", "1.2.3.post1", "2.0.0", "2026.10.01", "v2.0.0+incompatible"], + "requirement": "=1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/201", + "scheme": "calver", + "versions": ["10.0.0", "2.1.0"], + "requirement": "^1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/202", + "scheme": "opaque", + "versions": ["0.1.9", "1.0.0", "1.2.3-beta.2", "2.0.0", "2026.01.01"], + "requirement": "=1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/203", + "scheme": "semver", + "versions": ["1.9.9", "10.0.0"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/204", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3rc1", "2.0.0", "2.1.0"], + "requirement": "<2.0.0", + "expect": { "version": "0.2.0" } + }, + { + "name": "fuzz/205", + "scheme": "opaque", + "versions": ["1.0.0", "1.0.1", "legacy-api"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/206", + "scheme": "semver", + "versions": ["0.0.1", "1.2.0", "1.2.9", "1.3.0", "v1.0.0"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/207", + "scheme": "calver", + "versions": ["1.2.3.post1", "1.2.9"], + "requirement": "1.2.3", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/208", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.3rc1"], + "requirement": ">=1.2 <2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/209", + "scheme": "opaque", + "versions": ["1.3.0"], + "requirement": ">=1.2 <2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/210", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3", "1.2.3rc1", "v1.0.0"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/211", + "scheme": "calver", + "versions": ["v2.0.0+incompatible"], + "requirement": "^1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/212", + "scheme": "semver", + "versions": ["1.2.3.post1", "10.0.0"], + "requirement": "^1", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/213", + "scheme": "calver", + "versions": ["1.0.0-rc.1", "1.0.1", "1.2.3", "release-candidate-1", "v2.0.0+incompatible"], + "requirement": "<2.0.0", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/214", + "scheme": "opaque", + "versions": ["2.1.0", "2026.07.24"], + "requirement": "1.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/215", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3-beta.2", "2026.01.01", "2026.07.24"], + "requirement": ">=1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/216", + "scheme": "opaque", + "versions": ["1.0.1"], + "requirement": "1.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/217", + "scheme": "semver", + "versions": ["2026.10.01"], + "requirement": "<2.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/218", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3.post1", "2.0.0-alpha.1", "2.1.0", "2026.07.24"], + "requirement": ">=1.2", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/219", + "scheme": "calver", + "versions": ["1.2.0", "2026.07.24"], + "requirement": "~1", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/220", + "scheme": "calver", + "versions": ["0.1.0", "1.2.3", "1.2.3-beta.2", "2026.01.01"], + "requirement": ">1.0.0", + "expect": { "version": "2026.01.01" } + }, + { + "name": "fuzz/221", + "scheme": "calver", + "versions": ["1.2.3", "2.0.0", "nightly"], + "requirement": "1.*", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/222", + "scheme": "opaque", + "versions": ["1.0.0"], + "requirement": ">=1.2 <2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/223", + "scheme": "calver", + "versions": ["1.2.0"], + "requirement": "1.2.*", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/224", + "scheme": "calver", + "versions": ["1.2.0", "1.3.0", "legacy-api", "v1.0.0"], + "requirement": "^2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/225", + "scheme": "opaque", + "versions": ["1.0.0", "1.0.1", "1.2.3.post1", "2026.01.01", "2026.06.01", "2026.07.24"], + "requirement": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/226", + "scheme": "semver", + "versions": ["0.0.1", "1.0.0", "1.0.0-rc.1", "1.2.3-beta.2", "1.2.3rc1", "1.3.0"], + "requirement": "<2.0.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/227", + "scheme": "semver", + "versions": ["1.0.0", "nightly"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/228", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "2.1.0", "2026.10.01"], + "requirement": "1.2.*", + "expect": { "version": "1.2.0" } + }, + { + "name": "fuzz/229", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "1.2.3-beta.2", "1.2.9"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/230", + "scheme": "opaque", + "versions": ["0.1.9", "1.2.0", "1.3.0", "10.0.0", "release-candidate-1"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/231", + "scheme": "opaque", + "versions": ["0.0.1"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/232", + "scheme": "semver", + "versions": ["0.1.0", "2026.10.01", "release-candidate-1"], + "requirement": "1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/233", + "scheme": "opaque", + "versions": ["0.2.0", "1.2.0", "1.2.9", "10.0.0", "legacy-api"], + "requirement": "~1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/234", + "scheme": "calver", + "versions": ["1.2.3.post1", "v2.0.0+incompatible"], + "requirement": "~1.2.3", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/235", + "scheme": "semver", + "versions": ["1.2.3-beta.2", "1.2.3.post1", "1.9.9", "10.0.0"], + "requirement": "^1.2", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/236", + "scheme": "opaque", + "versions": ["10.0.0"], + "requirement": "=1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/237", + "scheme": "calver", + "versions": ["1.2.3", "1.2.3.post1", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/238", + "scheme": "opaque", + "versions": ["0.1.0", "1.0.1", "1.2.3rc1", "2026.01.01"], + "requirement": "1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/239", + "scheme": "calver", + "versions": [], + "requirement": "<2.0.0", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/240", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3", "1.9.9", "2.0.0-alpha.1", "2.1.0", "legacy-api"], + "requirement": "<2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/241", + "scheme": "opaque", + "versions": ["1.2.9", "10.0.0"], + "requirement": "1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/242", + "scheme": "calver", + "versions": ["0.1.0", "2.0.0", "2.1.0"], + "requirement": "1.2.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/243", + "scheme": "opaque", + "versions": [], + "requirement": "^2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/244", + "scheme": "semver", + "versions": ["2.1.0", "2026.01.01", "nightly", "v1.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/245", + "scheme": "semver", + "versions": ["0.0.1", "0.2.0", "2.1.0"], + "requirement": "~1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/246", + "scheme": "calver", + "versions": ["nightly"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/247", + "scheme": "semver", + "versions": ["1.2.0", "1.9.9", "v2.0.0+incompatible"], + "requirement": "^1.x.y", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/248", + "scheme": "calver", + "versions": ["0.2.0", "1.0.0-rc.1", "2026.01.01"], + "requirement": "1.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/249", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3rc1", "1.9.9", "2026.06.01"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/250", + "scheme": "semver", + "versions": [], + "requirement": "1.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/251", + "scheme": "opaque", + "versions": [], + "requirement": "*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/252", + "scheme": "calver", + "versions": [], + "requirement": "^1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/253", + "scheme": "calver", + "versions": ["legacy-api", "v1.0.0"], + "requirement": "1", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/254", + "scheme": "opaque", + "versions": ["nightly"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/255", + "scheme": "opaque", + "versions": ["1.0.0-rc.1", "1.2.9", "1.9.9", "2.0.0", "nightly"], + "requirement": "^0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/256", + "scheme": "opaque", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/257", + "scheme": "semver", + "versions": ["1.0.0", "1.2.3.post1", "2026.06.01", "legacy-api", "release-candidate-1"], + "requirement": "~1.2.3", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/258", + "scheme": "opaque", + "versions": ["0.1.9", "1.0.0", "1.2.9", "2.1.0", "2026.10.01", "v2.0.0+incompatible"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/259", + "scheme": "semver", + "versions": ["1.2.3rc1", "10.0.0", "2026.01.01"], + "requirement": "1.2.*", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/260", + "scheme": "semver", + "versions": ["0.0.1", "1.9.9", "2.0.0", "2026.07.24"], + "requirement": "^0.0.1", + "expect": { "version": "0.0.1" } + }, + { + "name": "fuzz/261", + "scheme": "calver", + "versions": ["0.1.0", "1.2.0", "1.2.3", "10.0.0", "2026.10.01"], + "requirement": "^1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/262", + "scheme": "semver", + "versions": ["0.0.1", "0.1.9", "1.0.1", "1.2.3.post1", "nightly", "v1.0.0"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/263", + "scheme": "semver", + "versions": [], + "requirement": "^0.0.1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/264", + "scheme": "calver", + "versions": ["1.2.3", "release-candidate-1"], + "requirement": "^1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/265", + "scheme": "semver", + "versions": ["v2.0.0+incompatible"], + "requirement": "<2.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/266", + "scheme": "semver", + "versions": ["0.0.1", "2026.10.01"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/267", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3", "1.2.3rc1", "legacy-api", "release-candidate-1"], + "requirement": ">=2026.7", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/268", + "scheme": "opaque", + "versions": [], + "requirement": "=1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/269", + "scheme": "semver", + "versions": ["2026.01.01", "2026.06.01", "legacy-api", "v1.0.0"], + "requirement": "1", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/270", + "scheme": "calver", + "versions": ["1.3.0", "1.9.9", "2.0.0-alpha.1", "2026.07.24", "release-candidate-1"], + "requirement": "=1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/271", + "scheme": "opaque", + "versions": ["2026.06.01"], + "requirement": "^1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/272", + "scheme": "semver", + "versions": ["0.1.9", "1.0.1", "1.3.0", "2026.06.01", "v2.0.0+incompatible"], + "requirement": "1.2", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/273", + "scheme": "semver", + "versions": ["1.0.1", "1.3.0", "2026.01.01", "2026.06.01"], + "requirement": "^2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/274", + "scheme": "opaque", + "versions": [], + "requirement": "^2026", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/275", + "scheme": "semver", + "versions": ["release-candidate-1"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/276", + "scheme": "calver", + "versions": ["0.0.1", "1.2.0", "2026.07.24", "release-candidate-1"], + "requirement": "2026.07.24", + "expect": { "version": "2026.07.24" } + }, + { + "name": "fuzz/277", + "scheme": "calver", + "versions": ["1.2.3", "2.1.0", "2026.06.01"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/278", + "scheme": "semver", + "versions": ["1.3.0"], + "requirement": "^2026", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/279", + "scheme": "semver", + "versions": ["1.9.9", "2026.06.01"], + "requirement": "~1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/280", + "scheme": "opaque", + "versions": ["1.2.9", "1.3.0", "2.1.0", "2026.06.01", "2026.10.01"], + "requirement": "*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/281", + "scheme": "semver", + "versions": ["2026.10.01"], + "requirement": "^1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/282", + "scheme": "opaque", + "versions": ["2.0.0", "release-candidate-1"], + "requirement": "1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/283", + "scheme": "opaque", + "versions": ["1.9.9", "2.1.0"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/284", + "scheme": "calver", + "versions": ["0.1.9", "10.0.0", "2026.07.24", "2026.10.01"], + "requirement": ">=1.2", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/285", + "scheme": "opaque", + "versions": ["1.0.0", "1.2.3.post1", "1.9.9", "10.0.0", "2026.01.01", "v2.0.0+incompatible"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/286", + "scheme": "calver", + "versions": ["1.0.0-rc.1"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/287", + "scheme": "opaque", + "versions": ["1.2.3.post1", "1.2.9", "1.9.9", "2.1.0"], + "requirement": "^1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/288", + "scheme": "calver", + "versions": [], + "requirement": "^0.1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/289", + "scheme": "semver", + "versions": ["0.2.0", "release-candidate-1", "v1.0.0"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/290", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "2.0.0", "2026.01.01"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/291", + "scheme": "opaque", + "versions": ["0.1.0", "0.1.9", "v1.0.0", "v2.0.0+incompatible"], + "requirement": "=1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/292", + "scheme": "calver", + "versions": ["1.3.0", "legacy-api"], + "requirement": "^1", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/293", + "scheme": "opaque", + "versions": ["1.0.0", "1.2.0"], + "requirement": "^0.0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/294", + "scheme": "semver", + "versions": [], + "requirement": "1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/295", + "scheme": "opaque", + "versions": ["2.0.0", "2.1.0", "2026.01.01", "2026.07.24"], + "requirement": ">=2026.7", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/296", + "scheme": "opaque", + "versions": ["0.1.0", "0.1.9", "1.0.0-rc.1", "10.0.0", "2.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/297", + "scheme": "opaque", + "versions": ["1.2.3.post1", "2.0.0", "2.1.0", "release-candidate-1"], + "requirement": "1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/298", + "scheme": "opaque", + "versions": ["1.2.9", "1.3.0"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/299", + "scheme": "opaque", + "versions": ["0.1.0"], + "requirement": "=1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/300", + "scheme": "semver", + "versions": ["0.0.1", "1.9.9", "2.0.0", "2.0.0-alpha.1", "2026.01.01", "2026.06.01"], + "requirement": "1.x", + "expect": { "version": "1.9.9" } + }, + { + "name": "fuzz/301", + "scheme": "calver", + "versions": ["0.2.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/302", + "scheme": "semver", + "versions": ["0.2.0", "1.0.0", "1.0.1", "1.2.3.post1", "2.0.0-alpha.1", "2026.01.01"], + "requirement": ">=1.2 <2", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/303", + "scheme": "calver", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/304", + "scheme": "opaque", + "versions": ["1.2.0", "1.2.3", "1.9.9", "2.0.0", "2.0.0-alpha.1", "v1.0.0"], + "requirement": "^1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/305", + "scheme": "calver", + "versions": ["0.1.0", "1.2.3rc1", "2.0.0-alpha.1", "2026.10.01"], + "requirement": "1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/306", + "scheme": "opaque", + "versions": [], + "requirement": "^0.0.1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/307", + "scheme": "calver", + "versions": ["0.1.0", "0.1.9", "1.2.3.post1", "1.2.9", "release-candidate-1"], + "requirement": ">1.0.0", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/308", + "scheme": "calver", + "versions": [], + "requirement": "1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/309", + "scheme": "opaque", + "versions": [], + "requirement": "<=1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/310", + "scheme": "opaque", + "versions": ["1.0.0-rc.1", "1.2.0", "1.2.3.post1", "1.2.3rc1", "10.0.0", "v2.0.0+incompatible"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/311", + "scheme": "semver", + "versions": ["0.2.0", "1.9.9", "2026.07.24"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/312", + "scheme": "opaque", + "versions": ["1.0.0"], + "requirement": "1.2.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/313", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3.post1", "2026.06.01"], + "requirement": "*", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/314", + "scheme": "calver", + "versions": ["1.2.0", "10.0.0"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/315", + "scheme": "semver", + "versions": ["0.2.0", "1.2.0", "1.2.3", "2.1.0", "2026.06.01"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/316", + "scheme": "calver", + "versions": ["1.0.0"], + "requirement": ">1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/317", + "scheme": "semver", + "versions": ["0.0.1", "1.0.1", "1.3.0", "2.1.0", "2026.10.01", "v2.0.0+incompatible"], + "requirement": "~1", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/318", + "scheme": "opaque", + "versions": [], + "requirement": "^1.2.3", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/319", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.3-beta.2", "1.2.9", "2.0.0-alpha.1"], + "requirement": "~1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/320", + "scheme": "semver", + "versions": ["0.0.1", "1.2.9", "2.1.0", "release-candidate-1", "v1.0.0"], + "requirement": "1.*", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/321", + "scheme": "semver", + "versions": ["1.9.9", "10.0.0", "2.0.0-alpha.1", "nightly"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/322", + "scheme": "calver", + "versions": [], + "requirement": "2026.07.24", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/323", + "scheme": "semver", + "versions": ["v1.0.0"], + "requirement": "^1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/324", + "scheme": "semver", + "versions": [], + "requirement": "not-a-version", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/325", + "scheme": "semver", + "versions": ["0.1.9", "1.0.1", "2.0.0-alpha.1", "2026.07.24"], + "requirement": ">=1.2 <2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/326", + "scheme": "opaque", + "versions": ["1.9.9"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/327", + "scheme": "calver", + "versions": ["1.0.0", "1.2.9", "2026.07.24"], + "requirement": ">=1.2 <2", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/328", + "scheme": "semver", + "versions": ["1.0.0", "1.2.0", "1.9.9", "2.0.0", "release-candidate-1", "v1.0.0"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/329", + "scheme": "calver", + "versions": ["1.9.9"], + "requirement": "2026.07.24", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/330", + "scheme": "calver", + "versions": ["0.1.0", "0.2.0", "1.0.1", "1.2.3.post1", "10.0.0"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/331", + "scheme": "opaque", + "versions": [], + "requirement": "^2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/332", + "scheme": "semver", + "versions": ["1.3.0", "v2.0.0+incompatible"], + "requirement": "*", + "expect": { "version": "v2.0.0+incompatible" } + }, + { + "name": "fuzz/333", + "scheme": "semver", + "versions": ["10.0.0"], + "requirement": "^2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/334", + "scheme": "opaque", + "versions": [], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/335", + "scheme": "semver", + "versions": ["1.0.0", "1.2.3.post1", "2.0.0", "2026.06.01", "2026.10.01", "legacy-api"], + "requirement": "*", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/336", + "scheme": "opaque", + "versions": ["1.2.0", "1.2.3", "1.2.3-beta.2", "2.1.0", "release-candidate-1"], + "requirement": "^1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/337", + "scheme": "opaque", + "versions": ["2.0.0"], + "requirement": "<2.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/338", + "scheme": "semver", + "versions": [], + "requirement": "legacy-api", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/339", + "scheme": "opaque", + "versions": ["1.0.1", "1.2.0", "1.2.3rc1", "2026.07.24", "2026.10.01"], + "requirement": "1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/340", + "scheme": "calver", + "versions": ["1.3.0"], + "requirement": "1.2.3", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/341", + "scheme": "opaque", + "versions": ["2.1.0"], + "requirement": "1.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/342", + "scheme": "opaque", + "versions": ["0.1.9", "10.0.0", "2026.06.01", "2026.07.24"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/343", + "scheme": "semver", + "versions": ["1.2.3rc1", "legacy-api"], + "requirement": "^1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/344", + "scheme": "opaque", + "versions": ["1.2.3-beta.2"], + "requirement": "1.2.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/345", + "scheme": "semver", + "versions": ["0.1.0", "1.0.0-rc.1", "1.2.3.post1", "1.3.0", "2.0.0", "2026.01.01"], + "requirement": "^1.2.3", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/346", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0", "1.9.9", "2.1.0", "2026.01.01", "nightly"], + "requirement": "^0.1", + "expect": { "version": "0.1.0" } + }, + { + "name": "fuzz/347", + "scheme": "opaque", + "versions": ["2026.01.01", "nightly"], + "requirement": "^1.x.y", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/348", + "scheme": "calver", + "versions": ["0.0.1", "1.9.9", "2026.01.01", "2026.07.24"], + "requirement": "~1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/349", + "scheme": "calver", + "versions": ["0.1.0", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "version": "0.1.0" } + }, + { + "name": "fuzz/350", + "scheme": "semver", + "versions": ["0.1.9", "1.0.0", "1.9.9", "2.0.0-alpha.1", "nightly"], + "requirement": "^0.1", + "expect": { "version": "0.1.9" } + }, + { + "name": "fuzz/351", + "scheme": "opaque", + "versions": ["10.0.0", "v2.0.0+incompatible"], + "requirement": "<=1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/352", + "scheme": "semver", + "versions": [], + "requirement": "^1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/353", + "scheme": "opaque", + "versions": ["1.2.3", "1.2.9", "1.3.0", "10.0.0", "legacy-api"], + "requirement": "1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/354", + "scheme": "semver", + "versions": ["0.2.0", "1.2.3", "1.2.9", "1.9.9", "2026.06.01"], + "requirement": ">1.0.0", + "expect": { "version": "2026.06.01" } + }, + { + "name": "fuzz/355", + "scheme": "calver", + "versions": ["1.2.3-beta.2"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/356", + "scheme": "semver", + "versions": ["0.1.9", "1.2.3.post1", "2.0.0-alpha.1", "2026.07.24", "release-candidate-1", "v1.0.0"], + "requirement": "^0.1", + "expect": { "version": "0.1.9" } + }, + { + "name": "fuzz/357", + "scheme": "opaque", + "versions": ["2.0.0-alpha.1", "2026.01.01", "v2.0.0+incompatible"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/358", + "scheme": "calver", + "versions": ["0.1.9", "1.0.0", "v1.0.0"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "v1.0.0" } + }, + { + "name": "fuzz/359", + "scheme": "opaque", + "versions": ["1.2.0", "2026.01.01", "2026.07.24", "legacy-api", "release-candidate-1"], + "requirement": "^1.2.3", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/360", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "10.0.0", "nightly", "v2.0.0+incompatible"], + "requirement": "1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/361", + "scheme": "opaque", + "versions": ["0.1.9", "2026.10.01", "nightly"], + "requirement": "^1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/362", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "2.0.0-alpha.1", "2.1.0", "2026.06.01"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/363", + "scheme": "calver", + "versions": ["0.2.0", "1.2.3-beta.2", "2026.01.01", "2026.06.01"], + "requirement": "=1.0.0", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/364", + "scheme": "calver", + "versions": ["2026.01.01", "2026.10.01"], + "requirement": ">1.0.0", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/365", + "scheme": "opaque", + "versions": ["1.2.3rc1", "2.1.0", "2026.07.24", "release-candidate-1"], + "requirement": "1.2.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/366", + "scheme": "semver", + "versions": ["1.2.9"], + "requirement": "^1.2.3", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/367", + "scheme": "semver", + "versions": ["1.0.0", "1.2.3-beta.2"], + "requirement": "=1.0.0", + "expect": { "version": "1.0.0" } + }, + { + "name": "fuzz/368", + "scheme": "opaque", + "versions": ["0.0.1", "0.1.9", "1.9.9", "v1.0.0", "v2.0.0+incompatible"], + "requirement": "^1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/369", + "scheme": "semver", + "versions": ["1.0.1"], + "requirement": "~1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/370", + "scheme": "semver", + "versions": ["0.0.1", "1.0.0", "1.0.1", "1.2.0", "1.2.3", "release-candidate-1"], + "requirement": "^1.2.3", + "expect": { "version": "1.2.3" } + }, + { + "name": "fuzz/371", + "scheme": "calver", + "versions": ["1.0.1", "2.0.0", "2.0.0-alpha.1", "2026.07.24"], + "requirement": "~1.2", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/372", + "scheme": "calver", + "versions": ["1.0.0-rc.1", "1.9.9", "2.0.0", "2.0.0-alpha.1"], + "requirement": "not-a-version", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/373", + "scheme": "calver", + "versions": ["0.0.1", "0.1.0", "2.0.0-alpha.1", "2.1.0", "2026.10.01", "release-candidate-1"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/374", + "scheme": "calver", + "versions": ["0.1.0", "1.0.0-rc.1", "1.2.3-beta.2", "1.9.9", "2026.10.01"], + "requirement": "*", + "expect": { "version": "2026.10.01" } + }, + { + "name": "fuzz/375", + "scheme": "semver", + "versions": ["0.2.0", "1.0.1", "1.2.3-beta.2", "1.2.9", "2.0.0-alpha.1", "v1.0.0"], + "requirement": ">1.0.0", + "expect": { "version": "1.2.9" } + }, + { + "name": "fuzz/376", + "scheme": "semver", + "versions": ["1.2.0", "1.2.3-beta.2", "1.2.9", "legacy-api"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/377", + "scheme": "semver", + "versions": ["legacy-api", "nightly", "v1.0.0"], + "requirement": ">=2026.7", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/378", + "scheme": "calver", + "versions": [], + "requirement": "1", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/379", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3.post1", "2026.06.01"], + "requirement": ">=1.2 <2", + "expect": { "version": "1.2.3.post1" } + }, + { + "name": "fuzz/380", + "scheme": "semver", + "versions": ["0.0.1", "0.1.0", "1.3.0", "2026.06.01", "2026.07.24", "nightly"], + "requirement": "1.2", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/381", + "scheme": "calver", + "versions": [], + "requirement": "1.*", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/382", + "scheme": "calver", + "versions": ["1.0.0", "1.2.3.post1", "v1.0.0"], + "requirement": "legacy-api", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/383", + "scheme": "opaque", + "versions": ["0.1.9", "0.2.0", "1.2.3", "1.2.3.post1", "1.9.9"], + "requirement": "^0.0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/384", + "scheme": "semver", + "versions": ["1.0.0-rc.1", "release-candidate-1"], + "requirement": "1.2.3", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/385", + "scheme": "semver", + "versions": ["1.0.0", "1.3.0", "2.0.0", "2026.06.01", "v1.0.0"], + "requirement": "1.x", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/386", + "scheme": "opaque", + "versions": ["0.1.9", "2026.10.01"], + "requirement": ">1.0.0", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/387", + "scheme": "semver", + "versions": ["1.3.0", "nightly"], + "requirement": "~1", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/388", + "scheme": "opaque", + "versions": ["1.2.3"], + "requirement": ">=1.2", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/389", + "scheme": "calver", + "versions": ["0.2.0", "1.0.0-rc.1", "1.2.9", "2.0.0", "legacy-api"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/390", + "scheme": "semver", + "versions": ["0.0.1", "1.2.3-beta.2"], + "requirement": "1.x", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/391", + "scheme": "opaque", + "versions": ["0.0.1", "1.2.3-beta.2", "1.2.3.post1", "1.9.9"], + "requirement": "^0.0.1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/392", + "scheme": "calver", + "versions": ["1.2.3", "1.2.3-beta.2", "1.2.3rc1", "v1.0.0"], + "requirement": "^0.0.1", + "expect": { "error": "unsatisfied" } + }, + { + "name": "fuzz/393", + "scheme": "calver", + "versions": ["1.2.3-beta.2", "1.2.3.post1", "1.3.0", "2026.06.01", "release-candidate-1", "v2.0.0+incompatible"], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/394", + "scheme": "opaque", + "versions": ["1.2.3", "2026.01.01"], + "requirement": "~1", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/395", + "scheme": "opaque", + "versions": [], + "requirement": "1.2", + "expect": { "error": "no_versions" } + }, + { + "name": "fuzz/396", + "scheme": "semver", + "versions": ["1.2.3", "1.3.0", "10.0.0", "2026.01.01", "2026.10.01", "v1.0.0"], + "requirement": "1", + "expect": { "version": "1.3.0" } + }, + { + "name": "fuzz/397", + "scheme": "opaque", + "versions": ["0.0.1", "1.0.0", "1.0.0-rc.1", "1.9.9", "2.0.0", "2026.01.01"], + "requirement": "1.2.*", + "expect": { "error": "invalid_requirement" } + }, + { + "name": "fuzz/398", + "scheme": "semver", + "versions": ["1.9.9", "2.1.0"], + "requirement": ">1.0.0", + "expect": { "version": "2.1.0" } + }, + { + "name": "fuzz/399", + "scheme": "calver", + "versions": ["0.2.0", "1.2.9", "10.0.0", "2026.01.01"], + "requirement": "nightly", + "expect": { "error": "unsatisfied" } + } + ] +} diff --git a/src/rust/tests/conformance.rs b/src/rust/tests/conformance.rs index 6d0af8c..0d0c3cb 100644 --- a/src/rust/tests/conformance.rs +++ b/src/rust/tests/conformance.rs @@ -63,14 +63,24 @@ fn corpus_files() -> Vec { files } -fn metadata(case: &Case) -> PackageMetadata { +/// `latest` is *data* for a latest-stable case — including when it is null, +/// which is what "the registry recorded nothing" looks like. Falling back to +/// the newest version there would quietly answer a different question than the +/// case asked. Resolution cases never read the field, so they get the +/// convenient fallback. +fn metadata(case: &Case, latest_is_data: bool) -> PackageMetadata { + let latest = if latest_is_data { + case.latest.clone() + } else { + case.latest.clone().or_else(|| case.versions.last().cloned()) + }; PackageMetadata { org: "acme".to_string(), name: "conformance".to_string(), vcs: Vcs::Git, repo_url: "https://github.com/acme/conformance".to_string(), description: None, - latest: case.latest.clone().or_else(|| case.versions.last().cloned()), + latest, versions: case.versions.clone(), version_scheme: VersionScheme::from_str_lenient(&case.scheme), tags: Vec::new(), From 796da52cc3975ce83d789f716364beb90c2378f6 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:27:54 -0500 Subject: [PATCH 35/38] claude autosave 2026-08-07T04:27:54Z --- src/dart/test/conformance_test.dart | 146 +++++++++++++++++++--------- src/rust/tests/conformance.rs | 4 +- 2 files changed, 102 insertions(+), 48 deletions(-) diff --git a/src/dart/test/conformance_test.dart b/src/dart/test/conformance_test.dart index e14d95d..8abeb5b 100644 --- a/src/dart/test/conformance_test.dart +++ b/src/dart/test/conformance_test.dart @@ -1,6 +1,11 @@ -// Runs the shared conformance corpus against the Dart implementation. The Rust -// slice runs the same file; a case that passes in one language and fails in the -// other is the drift this repository exists to catch. +// Runs every corpus file in ../../conformance/cases against the Dart +// implementation. The Rust and TypeScript slices load the same directory. +// +// Most of these cases were answered by Rust and written out by +// `cargo run --example generate_fuzz_corpus`: Rust delegates the hard part to +// the same `semver` crate Cargo uses, so what is really under test here is +// whether this hand-written algebra agrees with Cargo across combinations +// nobody would think to write down by hand. import 'dart:convert'; import 'dart:io'; @@ -9,58 +14,107 @@ import 'package:test/test.dart'; import 'package:zed_interfaces/package_metadata.dart'; import 'package:zed_lib/zed_lib.dart'; -const _corpusPath = '../../conformance/cases/version-resolution.json'; +const _casesDir = '../../conformance/cases'; +const _resolutionSchema = 'zed-lib/conformance/version-resolution/v1'; +const _latestSchema = 'zed-lib/conformance/latest-stable/v1'; -PackageMetadata metadataFor(String scheme, List versions) => - PackageMetadata( - org: 'acme', - name: 'conformance', - vcs: Vcs.git, - repoUrl: 'https://github.com/acme/conformance', - latest: versions.isEmpty ? null : versions.last, - versions: versions, - versionScheme: switch (scheme) { - 'calver' => VersionScheme.calver, - 'opaque' => VersionScheme.opaque, - _ => VersionScheme.semver, - }, - ); +/// `latest` is data for a latest-stable case — including when it is null, which +/// is what "the registry recorded nothing" looks like. Resolution cases never +/// read it, so they get a convenient fallback instead. +PackageMetadata metadataFor( + String scheme, + List versions, { + required String? latest, + required bool latestIsData, +}) => PackageMetadata( + org: 'acme', + name: 'conformance', + vcs: Vcs.git, + repoUrl: 'https://github.com/acme/conformance', + latest: latestIsData ? latest : (latest ?? (versions.isEmpty ? null : versions.last)), + versions: versions, + versionScheme: switch (scheme) { + 'calver' => VersionScheme.calver, + 'opaque' => VersionScheme.opaque, + _ => VersionScheme.semver, + }, +); void main() { - final raw = File(_corpusPath).readAsStringSync(); - final corpus = jsonDecode(raw) as Map; - final cases = (corpus['cases'] as List).cast>(); + final files = Directory(_casesDir) + .listSync() + .whereType() + .where((file) => file.path.endsWith('.json')) + .toList() + ..sort((a, b) => a.path.compareTo(b.path)); - test('the corpus is not empty', () => expect(cases, isNotEmpty)); + test('the corpus directory is not empty', () => expect(files, isNotEmpty)); - for (final testCase in cases) { - final name = testCase['name'] as String; - final metadata = metadataFor( - testCase['scheme'] as String, - (testCase['versions'] as List).cast(), - ); - final requirement = testCase['requirement'] as String; - final expected = testCase['expect'] as Map; + var total = 0; - test(name, () { - final wantVersion = expected['version'] as String?; - final wantError = expected['error'] as String?; - expect( - (wantVersion == null) != (wantError == null), - isTrue, - reason: 'a case declares exactly one of `version` or `error`', - ); + for (final file in files) { + final name = file.uri.pathSegments.last; + final corpus = jsonDecode(file.readAsStringSync()) as Map; + final schema = corpus['schema'] as String; + final cases = (corpus['cases'] as List).cast>(); - if (wantVersion != null) { - expect(resolveVersion(metadata, requirement), wantVersion); - } else { - try { - final resolved = resolveVersion(metadata, requirement); - fail('expected $wantError, resolved $resolved'); - } on ResolveException catch (error) { - expect(error.kind.wire, wantError); + group(name, () { + for (final testCase in cases) { + final caseName = testCase['name'] as String; + final versions = (testCase['versions'] as List).cast(); + final expected = testCase['expect'] as Map; + final wantVersion = expected['version'] as String?; + total++; + + switch (schema) { + case _resolutionSchema: + test(caseName, () { + final metadata = metadataFor( + testCase['scheme'] as String, + versions, + latest: testCase['latest'] as String?, + latestIsData: false, + ); + final requirement = testCase['requirement'] as String; + final wantError = expected['error'] as String?; + expect( + (wantVersion == null) != (wantError == null), + isTrue, + reason: 'declare exactly one of `version` or `error`', + ); + if (wantVersion != null) { + expect(resolveVersion(metadata, requirement), wantVersion); + } else { + try { + final resolved = resolveVersion(metadata, requirement); + fail('expected $wantError, resolved $resolved'); + } on ResolveException catch (error) { + expect(error.kind.wire, wantError); + } + } + }); + + case _latestSchema: + test(caseName, () { + final metadata = metadataFor( + testCase['scheme'] as String, + versions, + latest: testCase['latest'] as String?, + latestIsData: true, + ); + expect(expected['error'], isNull, reason: 'latest-stable cases return null, not errors'); + expect(latestStable(metadata), wantVersion); + }); + + default: + test('$name has a known schema', () => fail('unknown corpus schema `$schema`')); } } }); } + + // A loader bug that silently matched nothing would look like a clean run. + test('the generated corpus was loaded too', () { + expect(total, greaterThan(100), reason: 'ran only $total cases'); + }); } diff --git a/src/rust/tests/conformance.rs b/src/rust/tests/conformance.rs index 0d0c3cb..30b24f5 100644 --- a/src/rust/tests/conformance.rs +++ b/src/rust/tests/conformance.rs @@ -88,7 +88,7 @@ fn metadata(case: &Case, latest_is_data: bool) -> PackageMetadata { } fn check_resolution(case: &Case, file: &str) { - let meta = metadata(case); + let meta = metadata(case, false); let requirement = case .requirement .as_deref() @@ -113,7 +113,7 @@ fn check_latest(case: &Case, file: &str) { "{file}:{}: latest-stable cases cannot fail, they return null", case.name ); - let meta = metadata(case); + let meta = metadata(case, true); assert_eq!( latest_stable(&meta), case.expect.version.as_deref(), From e91bcf519bf007921579bcaa5430309aa6b930ad Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:29:08 -0500 Subject: [PATCH 36/38] claude autosave 2026-08-07T04:29:08Z --- src/dart/bin_diverge.dart | 37 +++++++++++++++++++++++++++++++++++ src/dart/lib/src/version.dart | 8 ++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/dart/bin_diverge.dart diff --git a/src/dart/bin_diverge.dart b/src/dart/bin_diverge.dart new file mode 100644 index 0000000..4a6f3bf --- /dev/null +++ b/src/dart/bin_diverge.dart @@ -0,0 +1,37 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:zed_interfaces/package_metadata.dart'; +import 'package:zed_lib/zed_lib.dart'; + +void main() { + for (final name in ['fuzz-version-resolution', 'fuzz-latest-stable']) { + final doc = jsonDecode(File('../../conformance/cases/$name.json').readAsStringSync()) as Map; + final isLatest = name.contains('latest'); + for (final c in (doc['cases'] as List).cast>()) { + final versions = (c['versions'] as List).cast(); + final scheme = switch (c['scheme'] as String) { + 'calver' => VersionScheme.calver, + 'opaque' => VersionScheme.opaque, + _ => VersionScheme.semver, + }; + final meta = PackageMetadata( + org: 'a', name: 'b', vcs: Vcs.git, repoUrl: 'u', + latest: isLatest ? c['latest'] as String? : (c['latest'] as String? ?? (versions.isEmpty ? null : versions.last)), + versions: versions, versionScheme: scheme); + final expect = c['expect'] as Map; + String got; + if (isLatest) { + got = 'version=${latestStable(meta)}'; + } else { + try { got = 'version=${resolveVersion(meta, c['requirement'] as String)}'; } + on ResolveException catch (e) { got = 'error=${e.kind.wire}'; } + } + final want = expect.containsKey('error') && expect['error'] != null + ? 'error=${expect['error']}' : 'version=${expect['version']}'; + if (got != want) { + print('${c['name']} scheme=${c['scheme']} req=${c['requirement']} versions=$versions'); + print(' rust=$want dart=$got'); + } + } + } +} diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index cddef40..300e1bf 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -337,6 +337,14 @@ List? _parseComparators(String input) { final trimmed = input.trim(); if (trimmed.isEmpty) return null; + // `>= 1.0.0, < 2.0.0` is legal — Cargo allows space between an operator and + // its version. Glue them back together before splitting, or the operator + // becomes its own token and the whole requirement reads as an opaque tag. + final glued = trimmed.replaceAllMapped( + RegExp(r'(\^|~|>=|<=|>|<|=)\s+'), + (match) => match[1]!, + ); + final comparators = []; var sawToken = false; for (final token in trimmed.split(RegExp(r'\s*,\s*|\s+'))) { From e2eff85b1030f27c80a7eda525272c69b6d8d202 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:29:47 -0500 Subject: [PATCH 37/38] claude autosave 2026-08-07T04:29:47Z --- src/dart/lib/src/resolve.dart | 3 +- src/dart/lib/src/version.dart | 13 +++- src/ts/conformance.test.ts | 142 +++++++++++++++++++++++----------- 3 files changed, 111 insertions(+), 47 deletions(-) diff --git a/src/dart/lib/src/resolve.dart b/src/dart/lib/src/resolve.dart index 6c6b60b..e7a75fc 100644 --- a/src/dart/lib/src/resolve.dart +++ b/src/dart/lib/src/resolve.dart @@ -109,7 +109,8 @@ String? latestStable(PackageMetadata metadata) { for (final version in metadata.versions) { final parsed = parseVersion(version); if (parsed == null || !parsed.isStable) continue; - if (bestParsed == null || parsed.compareTo(bestParsed) > 0) { + // Ties go to the last equal element, matching Rust's `Iterator::max_by`. + if (bestParsed == null || parsed.compareTo(bestParsed) >= 0) { best = version; bestParsed = parsed; } diff --git a/src/dart/lib/src/version.dart b/src/dart/lib/src/version.dart index 300e1bf..c75744f 100644 --- a/src/dart/lib/src/version.dart +++ b/src/dart/lib/src/version.dart @@ -299,6 +299,11 @@ bool looksLikeRange(String input) => wildcard = true; break; } + // Semver forbids leading zeros in numeric identifiers, and Cargo's + // requirement parser enforces it: `2026.07.24` is not a range at all, it is + // an exact tag. Accepting it here would turn a calendar tag into a caret + // range and, for an opaque package, into a spurious `invalid_requirement`. + if (segment.length > 1 && segment.startsWith('0')) return null; final value = int.tryParse(segment); if (value == null) return null; parts.add(value); @@ -347,7 +352,7 @@ List? _parseComparators(String input) { final comparators = []; var sawToken = false; - for (final token in trimmed.split(RegExp(r'\s*,\s*|\s+'))) { + for (final token in glued.split(RegExp(r'\s*,\s*|\s+'))) { if (token.isEmpty) continue; final expanded = _expand(token); if (expanded == null) return null; @@ -422,7 +427,11 @@ String? resolveRequirement(Requirement requirement, List versions) { final parsed = parseVersion(version); if (parsed == null || !parsed.isStable) continue; if (!requirement.matches(version)) continue; - if (bestParsed == null || parsed.compareTo(bestParsed) > 0) { + // `>= 0`, not `> 0`: Rust resolves with `Iterator::max_by`, which + // returns the LAST maximum. Distinct spellings can parse to the same + // version (`1.2.3` and `1.2.3.post1`, `1.0.0` and `v1.0.0`), so the + // tie-break decides which spelling is installed. + if (bestParsed == null || parsed.compareTo(bestParsed) >= 0) { best = version; bestParsed = parsed; } diff --git a/src/ts/conformance.test.ts b/src/ts/conformance.test.ts index 5ad66a7..0ffb83f 100644 --- a/src/ts/conformance.test.ts +++ b/src/ts/conformance.test.ts @@ -1,9 +1,14 @@ -// Runs the shared conformance corpus against the TypeScript implementation. -// The Rust and Dart slices run the same file; a case that passes in one -// language and fails in another is the drift this repository exists to catch. +// Runs every corpus file in ../../conformance/cases against the TypeScript +// implementation. The Rust and Dart slices load the same directory. // // node --test conformance.test.ts // +// Most of these cases were answered by Rust and written out by +// `cargo run --example generate_fuzz_corpus`: Rust delegates the hard part to +// the same `semver` crate Cargo uses, so what is really under test is whether +// this hand-written algebra agrees with Cargo across combinations nobody would +// think to write down by hand. +// // No build step: Node strips the types on the way in. import assert from "node:assert/strict"; @@ -13,56 +18,105 @@ import { test } from "node:test"; import type { PackageMetadata, VersionScheme } from "@zed-pkg/zed-interfaces"; -import { ResolveError, resolveVersion } from "./index.ts"; +import { ResolveError, latestStable, resolveVersion } from "./index.ts"; + +const RESOLUTION_SCHEMA = "zed-lib/conformance/version-resolution/v1"; +const LATEST_SCHEMA = "zed-lib/conformance/latest-stable/v1"; interface Case { readonly name: string; readonly scheme: string; readonly versions: readonly string[]; - readonly requirement: string; - readonly expect: { readonly version?: string; readonly error?: string }; + readonly requirement?: string; + readonly latest?: string | null; + readonly expect: { readonly version?: string | null; readonly error?: string }; } -const corpusPath = path.join( - import.meta.dirname, - "../../conformance/cases/version-resolution.json", -); -const corpus = JSON.parse(fs.readFileSync(corpusPath, "utf8")) as { cases: Case[] }; - -const metadataFor = (scheme: string, versions: readonly string[]): PackageMetadata => ({ - org: "acme", - name: "conformance", - vcs: "git", - repo_url: "https://github.com/acme/conformance", - latest: versions.length ? (versions[versions.length - 1] as string) : null, - versions, - version_scheme: (scheme === "calver" || scheme === "opaque" ? scheme : "semver") as VersionScheme, -}); +interface Corpus { + readonly schema: string; + readonly cases: readonly Case[]; +} + +const casesDir = path.join(import.meta.dirname, "../../conformance/cases"); + +/** `latest` is data for a latest-stable case — including when it is null, which + * is what "the registry recorded nothing" looks like. Resolution cases never + * read it, so they get a convenient fallback instead. */ +function metadataFor(testCase: Case, latestIsData: boolean): PackageMetadata { + const { versions } = testCase; + const fallback = versions.length ? (versions[versions.length - 1] as string) : null; + const scheme = testCase.scheme === "calver" || testCase.scheme === "opaque" + ? testCase.scheme + : "semver"; + return { + org: "acme", + name: "conformance", + vcs: "git", + repo_url: "https://github.com/acme/conformance", + latest: latestIsData ? (testCase.latest ?? null) : (testCase.latest ?? fallback), + versions, + version_scheme: scheme as VersionScheme, + }; +} + +const files = fs + .readdirSync(casesDir) + .filter((name) => name.endsWith(".json")) + .sort(); -test("the corpus is not empty", () => { - assert.ok(corpus.cases.length > 0); +test("the corpus directory is not empty", () => { + assert.ok(files.length > 0); }); -for (const testCase of corpus.cases) { - test(testCase.name, () => { - const metadata = metadataFor(testCase.scheme, testCase.versions); - const { version: want, error: wantError } = testCase.expect; - assert.ok( - (want === undefined) !== (wantError === undefined), - "a case declares exactly one of `version` or `error`", - ); - - if (want !== undefined) { - assert.equal(resolveVersion(metadata, testCase.requirement), want); - return; +let total = 0; + +for (const file of files) { + const corpus = JSON.parse(fs.readFileSync(path.join(casesDir, file), "utf8")) as Corpus; + assert.ok(corpus.cases.length > 0, `${file} has no cases`); + + for (const testCase of corpus.cases) { + total += 1; + + if (corpus.schema === RESOLUTION_SCHEMA) { + test(`${file}: ${testCase.name}`, () => { + const metadata = metadataFor(testCase, false); + const requirement = testCase.requirement; + assert.ok(requirement !== undefined, "resolution cases need a `requirement`"); + const want = testCase.expect.version; + const wantError = testCase.expect.error; + assert.ok( + (want === undefined) !== (wantError === undefined), + "declare exactly one of `version` or `error`", + ); + if (want !== undefined) { + assert.equal(resolveVersion(metadata, requirement), want); + return; + } + assert.throws( + () => resolveVersion(metadata, requirement), + (error: unknown) => { + assert.ok(error instanceof ResolveError); + assert.equal(error.kind, wantError); + return true; + }, + ); + }); + continue; + } + + if (corpus.schema === LATEST_SCHEMA) { + test(`${file}: ${testCase.name}`, () => { + assert.equal(testCase.expect.error, undefined, "latest-stable cases return null"); + assert.equal(latestStable(metadataFor(testCase, true)), testCase.expect.version ?? null); + }); + continue; } - assert.throws( - () => resolveVersion(metadata, testCase.requirement), - (error: unknown) => { - assert.ok(error instanceof ResolveError); - assert.equal(error.kind, wantError); - return true; - }, - ); - }); + + throw new Error(`${file}: unknown corpus schema \`${corpus.schema}\``); + } } + +// A loader bug that silently matched nothing would look like a clean run. +test("the generated corpus was loaded too", () => { + assert.ok(total > 100, `ran only ${total} cases`); +}); From a60fd0ef2f884432aa16ebef6ddfc9a8101529c2 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Thu, 6 Aug 2026 23:31:49 -0500 Subject: [PATCH 38/38] claude autosave 2026-08-07T04:31:49Z --- .github/workflows/ci.yml | 15 +- conformance/README.md | 43 ++++ conformance/cases/latest-stable.json | 98 ++++++++-- conformance/cases/version-resolution.json | 227 ++++++++++++++++++---- src/dart/bin_diverge.dart | 37 ---- src/ts/resolve.ts | 3 +- src/ts/version.ts | 18 +- 7 files changed, 337 insertions(+), 104 deletions(-) delete mode 100644 src/dart/bin_diverge.dart diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b48486..79bdd2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: Check out zed-interfaces uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: - repository: zed-pkg/zed-interfaces + repository: ${{ github.repository_owner }}/zed-interfaces path: zed-interfaces persist-credentials: false show-progress: false @@ -57,6 +57,15 @@ jobs: working-directory: zed-lib run: cargo test --locked --test conformance + # Rust is the oracle for the generated cases, so a change here can rewrite + # what Dart and TypeScript are held to. Regenerating must be a no-op. + - name: Generated corpus is up to date + working-directory: zed-lib + run: | + cargo run --locked --example generate_fuzz_corpus + git diff --exit-code conformance/ \ + || (echo "conformance/ is stale; run 'cargo run --locked --example generate_fuzz_corpus' and commit" && exit 1) + # Each implementation slice runs the same corpus. These jobs are what turn # "three implementations of one contract" from a claim into a check. dart: @@ -73,7 +82,7 @@ jobs: - name: Check out zed-interfaces uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: - repository: zed-pkg/zed-interfaces + repository: ${{ github.repository_owner }}/zed-interfaces path: zed-interfaces persist-credentials: false show-progress: false @@ -107,7 +116,7 @@ jobs: - name: Check out zed-interfaces uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: - repository: zed-pkg/zed-interfaces + repository: ${{ github.repository_owner }}/zed-interfaces path: zed-interfaces persist-credentials: false show-progress: false diff --git a/conformance/README.md b/conformance/README.md index 9ea9632..a7c3005 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -32,7 +32,50 @@ place to pin a surprise: a bare `1.0.0` requirement is a **caret range** in this stack, so it resolves to `1.0.1` when that is published. `=1.0.0` is how a requirement pins one version. +## `cases/latest-stable.json` + +Cases for `latest_stable`, whose `expect` carries only `version` (it returns +null, never an error). `latest` is **data** in these cases, including when it is +null — that is what "the registry recorded nothing" looks like, and a runner +that substitutes the newest version there is quietly answering a different +question. Resolution cases never read `latest`, so they may fall back. + +## `cases/fuzz-*.json` — generated, do not edit + +```sh +cargo run --locked --example generate_fuzz_corpus +``` + +600 pseudo-random cases answered by the **Rust** implementation and replayed +against Dart and TypeScript. Rust is the oracle because it delegates the hard +part to the same `semver` crate Cargo uses, so the property under test is "the +hand-written Dart and TypeScript algebra agrees with Cargo". Deterministic +(fixed-seed LCG, no clock, no entropy), so regenerating rewrites the files byte +for byte and CI can diff them. + +It earned its keep on the first run: 16 cases diverged, in three classes, in +both hand-written implementations independently. + +* An operator may be separated from its version — `>= 1.0.0, < 2.0.0`. Both + tokenizers split on whitespace and orphaned the operator, turning a valid + range into an opaque tag. +* A requirement with leading zeros (`2026.07.24`) is **not** a range: semver + forbids leading zeros in numeric identifiers, so Cargo parses it as an exact + tag. Both had accepted it as a caret range, which also produced a spurious + `invalid_requirement` for opaque packages. +* Ties go to the **last** equal element. Distinct spellings can parse to the + same version (`1.0.0` and `v1.0.0`, `1.2.3` and `1.2.3.post1`); Rust resolves + with `Iterator::max_by`, which returns the last maximum, and both others kept + the first. The tie-break decides which spelling gets installed. + +Each is now also a named case in `version-resolution.json`, because a generated +file records the answer but not the intent. + ## Adding a case Add it here first and watch it fail, then implement. A case that was written after the code tests the code's opinion rather than the contract. + +Verify a new hand-written case against Rust before committing it: Rust is what +consumers already run through `zed-cli`, so a case Rust fails is a case that +mis-states the contract. diff --git a/conformance/cases/latest-stable.json b/conformance/cases/latest-stable.json index 20fdefd..a9a558f 100644 --- a/conformance/cases/latest-stable.json +++ b/conformance/cases/latest-stable.json @@ -5,72 +5,132 @@ { "name": "prereleases are never the latest stable version", "scheme": "semver", - "versions": ["1.0.0", "2.0.0", "2.1.0-rc.1"], + "versions": [ + "1.0.0", + "2.0.0", + "2.1.0-rc.1" + ], "latest": "2.1.0-rc.1", - "expect": { "version": "2.0.0" } + "expect": { + "version": "2.0.0" + } }, { "name": "the newest version wins regardless of list order", "scheme": "semver", - "versions": ["2.0.0", "10.0.0", "1.0.0"], + "versions": [ + "2.0.0", + "10.0.0", + "1.0.0" + ], "latest": "1.0.0", - "expect": { "version": "10.0.0" } + "expect": { + "version": "10.0.0" + } }, { "name": "the published spelling is preserved", "scheme": "semver", - "versions": ["v1.0.0", "v2.0.0"], + "versions": [ + "v1.0.0", + "v2.0.0" + ], "latest": null, - "expect": { "version": "v2.0.0" } + "expect": { + "version": "v2.0.0" + } }, { "name": "calendar versions order by their normalized form", "scheme": "calver", - "versions": ["2026.09.01", "2026.10.01", "2026.01.01"], + "versions": [ + "2026.09.01", + "2026.10.01", + "2026.01.01" + ], "latest": null, - "expect": { "version": "2026.10.01" } + "expect": { + "version": "2026.10.01" + } }, { "name": "an opaque package has no ordering, so the registry's latest stands", "scheme": "opaque", - "versions": ["legacy-api", "nightly"], + "versions": [ + "legacy-api", + "nightly" + ], "latest": "legacy-api", - "expect": { "version": "legacy-api" } + "expect": { + "version": "legacy-api" + } }, { "name": "an opaque latest that is no longer published is not offered", "scheme": "opaque", - "versions": ["legacy-api"], + "versions": [ + "legacy-api" + ], "latest": "withdrawn", - "expect": { "version": null } + "expect": { + "version": null + } }, { "name": "an opaque package with no latest recorded has no answer", "scheme": "opaque", - "versions": ["legacy-api"], + "versions": [ + "legacy-api" + ], "latest": null, - "expect": { "version": null } + "expect": { + "version": null + } }, { "name": "nothing published, nothing to offer", "scheme": "semver", "versions": [], "latest": null, - "expect": { "version": null } + "expect": { + "version": null + } }, { "name": "only prereleases published means no stable version exists", "scheme": "semver", - "versions": ["1.0.0-rc.1", "2.0.0-alpha.1"], + "versions": [ + "1.0.0-rc.1", + "2.0.0-alpha.1" + ], "latest": "2.0.0-alpha.1", - "expect": { "version": null } + "expect": { + "version": null + } }, { "name": "an unparseable tag under a semver scheme is skipped, not crashed on", "scheme": "semver", - "versions": ["1.0.0", "nightly"], + "versions": [ + "1.0.0", + "nightly" + ], "latest": "nightly", - "expect": { "version": "1.0.0" } + "expect": { + "version": "1.0.0" + } + }, + { + "name": "equal versions spelled differently: the last published wins", + "scheme": "semver", + "versions": [ + "1.0.0", + "v1.0.0" + ], + "latest": null, + "expect": { + "version": "v1.0.0" + } } ] } diff --git a/conformance/cases/version-resolution.json b/conformance/cases/version-resolution.json index 086f46e..e7ec4b9 100644 --- a/conformance/cases/version-resolution.json +++ b/conformance/cases/version-resolution.json @@ -5,149 +5,294 @@ { "name": "range picks the highest stable match", "scheme": "semver", - "versions": ["1.0.0", "1.4.0", "1.5.0-rc.1", "2.0.0"], + "versions": [ + "1.0.0", + "1.4.0", + "1.5.0-rc.1", + "2.0.0" + ], "requirement": "^1.2", - "expect": { "version": "1.4.0" } + "expect": { + "version": "1.4.0" + } }, { "name": "prereleases never satisfy a range", "scheme": "semver", - "versions": ["1.0.0", "2.0.0-rc.1"], + "versions": [ + "1.0.0", + "2.0.0-rc.1" + ], "requirement": "^2", - "expect": { "error": "unsatisfied" } + "expect": { + "error": "unsatisfied" + } }, { "name": "the published spelling is preserved, not a normalized one", "scheme": "calver", - "versions": ["2026.06.01", "2026.07.24"], + "versions": [ + "2026.06.01", + "2026.07.24" + ], "requirement": ">=2026.7", - "expect": { "version": "2026.07.24" } + "expect": { + "version": "2026.07.24" + } }, { "name": "a calendar version with a leading zero still orders correctly", "scheme": "calver", - "versions": ["2026.09.01", "2026.10.01"], + "versions": [ + "2026.09.01", + "2026.10.01" + ], "requirement": "^2026", - "expect": { "version": "2026.10.01" } + "expect": { + "version": "2026.10.01" + } }, { "name": "an opaque package resolves an exact tag", "scheme": "opaque", - "versions": ["legacy-api", "release-candidate-1"], + "versions": [ + "legacy-api", + "release-candidate-1" + ], "requirement": "legacy-api", - "expect": { "version": "legacy-api" } + "expect": { + "version": "legacy-api" + } }, { "name": "an opaque package refuses range algebra", "scheme": "opaque", - "versions": ["legacy-api"], + "versions": [ + "legacy-api" + ], "requirement": "^1.0", - "expect": { "error": "invalid_requirement" } + "expect": { + "error": "invalid_requirement" + } }, { "name": "an unknown opaque tag is unsatisfied, not invalid", "scheme": "opaque", - "versions": ["legacy-api"], + "versions": [ + "legacy-api" + ], "requirement": "nope", - "expect": { "error": "unsatisfied" } + "expect": { + "error": "unsatisfied" + } }, { "name": "a range-shaped typo is a requirement error", "scheme": "semver", - "versions": ["1.0.0"], + "versions": [ + "1.0.0" + ], "requirement": "^1.x.y", - "expect": { "error": "invalid_requirement" } + "expect": { + "error": "invalid_requirement" + } }, { "name": "an explicit wildcard binds tighter than an omitted segment", "scheme": "semver", - "versions": ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"], + "versions": [ + "1.0.0", + "1.2.0", + "1.2.9", + "1.9.0", + "2.0.0" + ], "requirement": "1.2.*", - "expect": { "version": "1.2.9" } + "expect": { + "version": "1.2.9" + } }, { "name": "the same requirement with the segment omitted is a caret range", "scheme": "semver", - "versions": ["1.0.0", "1.2.0", "1.2.9", "1.9.0", "2.0.0"], + "versions": [ + "1.0.0", + "1.2.0", + "1.2.9", + "1.9.0", + "2.0.0" + ], "requirement": "1.2", - "expect": { "version": "1.9.0" } + "expect": { + "version": "1.9.0" + } }, { "name": "`x` and `X` are wildcards too, not opaque tags", "scheme": "semver", - "versions": ["1.0.0", "1.9.0", "2.0.0"], + "versions": [ + "1.0.0", + "1.9.0", + "2.0.0" + ], "requirement": "1.x", - "expect": { "version": "1.9.0" } + "expect": { + "version": "1.9.0" + } }, { "name": "a bare wildcard matches the newest stable version", "scheme": "semver", - "versions": ["1.0.0", "2.0.0", "2.1.0-rc.1"], + "versions": [ + "1.0.0", + "2.0.0", + "2.1.0-rc.1" + ], "requirement": "*", - "expect": { "version": "2.0.0" } + "expect": { + "version": "2.0.0" + } }, { "name": "KNOWN GAP: a wildcard typo with no operator degrades to an opaque tag", "scheme": "semver", - "versions": ["1.0.0", "1.9.0"], + "versions": [ + "1.0.0", + "1.9.0" + ], "requirement": "1.x.y", - "expect": { "error": "unsatisfied" } + "expect": { + "error": "unsatisfied" + } }, { "name": "a `v`-prefixed Go tag resolves through the same range", "scheme": "semver", - "versions": ["v1.0.0", "v1.4.0"], + "versions": [ + "v1.0.0", + "v1.4.0" + ], "requirement": "^1.2", - "expect": { "version": "v1.4.0" } + "expect": { + "version": "v1.4.0" + } }, { "name": "Go's +incompatible does not change identity", "scheme": "semver", - "versions": ["v2.0.0+incompatible"], + "versions": [ + "v2.0.0+incompatible" + ], "requirement": "^2", - "expect": { "version": "v2.0.0+incompatible" } + "expect": { + "version": "v2.0.0+incompatible" + } }, { "name": "a PEP 440 prerelease is still a prerelease", "scheme": "semver", - "versions": ["1.2.3rc1", "1.2.2"], + "versions": [ + "1.2.3rc1", + "1.2.2" + ], "requirement": "^1.2", - "expect": { "version": "1.2.2" } + "expect": { + "version": "1.2.2" + } }, { "name": "npm-style whitespace ranges are accepted", "scheme": "semver", - "versions": ["1.0.0", "1.9.0", "2.0.0"], + "versions": [ + "1.0.0", + "1.9.0", + "2.0.0" + ], "requirement": ">=1.2 <2", - "expect": { "version": "1.9.0" } + "expect": { + "version": "1.9.0" + } }, { "name": "a bare semver requirement is a caret range, not an exact pin", "scheme": "semver", - "versions": ["1.0.0", "1.0.1"], + "versions": [ + "1.0.0", + "1.0.1" + ], "requirement": "1.0.0", - "expect": { "version": "1.0.1" } + "expect": { + "version": "1.0.1" + } }, { "name": "`=` is how a semver requirement pins one version", "scheme": "semver", - "versions": ["1.0.0", "1.0.1"], + "versions": [ + "1.0.0", + "1.0.1" + ], "requirement": "=1.0.0", - "expect": { "version": "1.0.0" } + "expect": { + "version": "1.0.0" + } }, { "name": "nothing published is its own failure", "scheme": "semver", "versions": [], "requirement": "^1.0", - "expect": { "error": "no_versions" } + "expect": { + "error": "no_versions" + } }, { "name": "a requirement no version satisfies", "scheme": "semver", - "versions": ["1.0.0", "1.1.0"], + "versions": [ + "1.0.0", + "1.1.0" + ], "requirement": "^9", - "expect": { "error": "unsatisfied" } + "expect": { + "error": "unsatisfied" + } + }, + { + "name": "an operator may be separated from its version by a space", + "scheme": "semver", + "versions": [ + "1.0.0", + "1.9.0", + "2.0.0" + ], + "requirement": ">= 1.0.0, < 2.0.0", + "expect": { + "version": "1.9.0" + } + }, + { + "name": "a requirement with leading zeros is an exact tag, not a range", + "scheme": "opaque", + "versions": [ + "2026.07.24" + ], + "requirement": "2026.07.24", + "expect": { + "version": "2026.07.24" + } + }, + { + "name": "when two spellings parse to the same version, the last published wins", + "scheme": "semver", + "versions": [ + "1.0.0", + "v1.0.0" + ], + "requirement": "^1", + "expect": { + "version": "v1.0.0" + } } ] } diff --git a/src/dart/bin_diverge.dart b/src/dart/bin_diverge.dart deleted file mode 100644 index 4a6f3bf..0000000 --- a/src/dart/bin_diverge.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'package:zed_interfaces/package_metadata.dart'; -import 'package:zed_lib/zed_lib.dart'; - -void main() { - for (final name in ['fuzz-version-resolution', 'fuzz-latest-stable']) { - final doc = jsonDecode(File('../../conformance/cases/$name.json').readAsStringSync()) as Map; - final isLatest = name.contains('latest'); - for (final c in (doc['cases'] as List).cast>()) { - final versions = (c['versions'] as List).cast(); - final scheme = switch (c['scheme'] as String) { - 'calver' => VersionScheme.calver, - 'opaque' => VersionScheme.opaque, - _ => VersionScheme.semver, - }; - final meta = PackageMetadata( - org: 'a', name: 'b', vcs: Vcs.git, repoUrl: 'u', - latest: isLatest ? c['latest'] as String? : (c['latest'] as String? ?? (versions.isEmpty ? null : versions.last)), - versions: versions, versionScheme: scheme); - final expect = c['expect'] as Map; - String got; - if (isLatest) { - got = 'version=${latestStable(meta)}'; - } else { - try { got = 'version=${resolveVersion(meta, c['requirement'] as String)}'; } - on ResolveException catch (e) { got = 'error=${e.kind.wire}'; } - } - final want = expect.containsKey('error') && expect['error'] != null - ? 'error=${expect['error']}' : 'version=${expect['version']}'; - if (got != want) { - print('${c['name']} scheme=${c['scheme']} req=${c['requirement']} versions=$versions'); - print(' rust=$want dart=$got'); - } - } - } -} diff --git a/src/ts/resolve.ts b/src/ts/resolve.ts index 58f3f15..8946d06 100644 --- a/src/ts/resolve.ts +++ b/src/ts/resolve.ts @@ -93,7 +93,8 @@ export function latestStable(metadata: PackageMetadata): string | null { for (const version of metadata.versions) { const parsed = parseVersion(version); if (!parsed || !isStable(parsed)) continue; - if (bestParsed === null || compareVersions(parsed, bestParsed) > 0) { + // Ties go to the last equal element, matching Rust's `Iterator::max_by`. + if (bestParsed === null || compareVersions(parsed, bestParsed) >= 0) { best = version; bestParsed = parsed; } diff --git a/src/ts/version.ts b/src/ts/version.ts index e2cfc76..c5bc8a6 100644 --- a/src/ts/version.ts +++ b/src/ts/version.ts @@ -236,7 +236,11 @@ function partial(raw: string): Partial | null { wildcard = true; break; } - if (!/^\d+$/.test(segment)) return null; + // Semver forbids leading zeros in numeric identifiers, and Cargo's + // requirement parser enforces it: `2026.07.24` is not a range at all, it is + // an exact tag. Accepting it here would turn a calendar tag into a caret + // range and, for an opaque package, into a spurious `invalid_requirement`. + if (!/^\d+$/.test(segment) || (segment.length > 1 && segment.startsWith("0"))) return null; parts.push(Number(segment)); } if (parts.length > 3) return null; @@ -326,9 +330,13 @@ function expand(token: string): VersionBound[] | null { function parseBounds(input: string): VersionBound[] | null { const trimmed = input.trim(); if (trimmed === "") return null; + // `>= 1.0.0, < 2.0.0` is legal — Cargo allows space between an operator and + // its version. Glue them back together before splitting, or the operator + // becomes its own token and the whole requirement reads as an opaque tag. + const glued = trimmed.replace(/(\^|~|>=|<=|>|<|=)\s+/g, "$1"); const comparators: VersionBound[] = []; let sawToken = false; - for (const token of trimmed.split(/\s*,\s*|\s+/)) { + for (const token of glued.split(/\s*,\s*|\s+/)) { if (token === "") continue; const expanded = expand(token); if (!expanded) return null; @@ -373,7 +381,11 @@ export function resolveRequirement( const parsed = parseVersion(version); if (!parsed || !isStable(parsed)) continue; if (!requirementMatches(requirement, version)) continue; - if (bestParsed === null || compareVersions(parsed, bestParsed) > 0) { + // `>= 0`, not `> 0`: Rust resolves with `Iterator::max_by`, which returns + // the LAST maximum. Distinct spellings can parse to the same version + // (`1.2.3` and `1.2.3.post1`, `1.0.0` and `v1.0.0`), so the tie-break + // decides which spelling is installed. + if (bestParsed === null || compareVersions(parsed, bestParsed) >= 0) { best = version; bestParsed = parsed; }