Skip to content

Refactor/version selectors#65

Merged
Arcadi4 merged 8 commits into
mainfrom
refactor/version-selectors
Jul 6, 2026
Merged

Refactor/version selectors#65
Arcadi4 merged 8 commits into
mainfrom
refactor/version-selectors

Conversation

@BFladderbeanawa

@BFladderbeanawa BFladderbeanawa commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Closes #60

Copilot AI review requested due to automatic review settings July 6, 2026 12:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Lucy’s “fuzzy” version selector vocabulary away from the previous latest/compatible model toward a new selector set (any/stable/beta) and updates multiple upstream providers and manifest defaults accordingly.

Changes:

  • Replaces latest/compatible selectors with beta/stable (and shifts defaults toward any) across version parsing, providers, and CLI completion hints.
  • Updates provider-specific selector resolution/fallback behavior (including recursive install resolution fallbacks).
  • Adjusts tests and manifest normalization to reflect the new selector defaults.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
version/version_parse.go Updates ambiguous-selector handling during version parsing.
upstream/providers/spiget/spiget.go Aligns Spiget selector resolution with new selector names.
upstream/providers/spiget/spiget_version.go Updates Spiget version resolution selector set.
upstream/providers/spiget/spiget_conversion_test.go Updates Spiget tests for selector identity expectations.
upstream/providers/neoforge/neoforge.go Updates NeoForge selector handling to new constants.
upstream/providers/modrinth/modrinth.go Updates Modrinth selector resolution behavior (new stable/beta/any mapping).
upstream/providers/modrinth/modrinth_version.go Switches Modrinth “inferable” check to CanInfer().
upstream/providers/modrinth/modrinth_project.go Changes Modrinth dependency selector default from compatible→any.
upstream/providers/mcdr/mcdr.go Updates MCDR provider selector mapping to new selector names.
upstream/providers/mcdr/mcdr_requests.go Updates MCDR request logic to treat new selectors as “latest” where applicable.
upstream/providers/hangar/hangar_version.go Updates Hangar selector mapping to new stable/beta/any names.
upstream/providers/forge/forge.go Updates Forge selector handling to new constants.
upstream/providers/fabric/fabric.go Updates Fabric loader selector recognition to new constants.
upstream/providers/curseforge/curseforge.go Updates CurseForge selector mapping to new stable/beta/any names.
types/type_dependency.go Replaces selector constants and documents the new selector set.
state/manifest.go Changes manifest default selector from compatible→any in multiple normalization/default paths.
state/manifest_test.go Updates manifest tests to expect the new defaults/selectors.
install/install.go Removes special-casing that previously remapped VersionAny→VersionCompatible for identity installs.
install/install_recursive_provider_resolver.go Updates fallback attempt chain for stable/beta/any selectors.
install/install_batch.go Removes batch-time remapping of VersionAny→VersionCompatible.
cmd/cmd_completion_helpers.go Updates CLI version completion candidates to any/stable/beta.
cmd/cmd_add.go Removes add-time remapping of VersionAny→VersionCompatible.
cmd/cmd_add_test.go Updates add tests for the new “any” default.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 177 to 181
switch p.Version {
case types.VersionCompatible:
case types.VersionStable:
v, err = latestCompatibleVersion(p.Name, p.Platform)
case types.VersionAny, types.VersionNone, types.VersionLatest:
case types.VersionBeta, types.VersionAny, types.VersionNone:
v, err = latestVersion(p.Name)
Comment thread state/manifest.go
Comment on lines 349 to 356
func NormalizeManifestVersionIntent(version types.BareVersion) string {
trimmed := strings.TrimSpace(version.String())
switch trimmed {
case "", "any", "none", "unknown":
return types.VersionCompatible.String()
return types.VersionAny.String()
default:
return trimmed
}
Comment thread types/type_dependency.go
Comment on lines +22 to +27
// Version selectors — all three are compatible with the detected server by
// default. They differ only in stability preference:
//
// - VersionAny (default): latest version regardless of release type.
// - VersionStable: only stable/release versions, no beta fallback.
// - VersionBeta: include beta and pre-release versions.
Comment thread version/version_parse.go
@Arcadi4 Arcadi4 requested review from Arcadi4 and Copilot July 6, 2026 12:32
@Arcadi4 Arcadi4 modified the milestone: v0.2 Jul 6, 2026
@Arcadi4 Arcadi4 added this to the v0.1 milestone Jul 6, 2026
@Arcadi4 Arcadi4 self-assigned this Jul 6, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

upstream/providers/modrinth/modrinth_version.go:72

  • getVersion() treats VersionStable as an inferable selector (via CanInfer) but resolves it using latestVersion(), which ignores the stable/compatibility semantics implemented in ResolveVersionSelector (stable -> latestCompatibleVersion). This can return a pre-release or loader-incompatible version when callers pass VersionStable to getVersion/Dependencies.
	versions, err := listVersions(id.Name)
	if err != nil {
		return nil, err
	}
	if id.Version.CanInfer() {
		v, err = latestVersion(id.Name)
		if err != nil {
			return nil, err
		}
		return v, nil
	}

Comment on lines 110 to 119
version, err = latestCompatibleVersion(
input.ToProjectName(project.Slug),
dependent.Platform,
)
if err != nil {
return p, fmt.Errorf("resolve dependency latest version: %w", err)
}
p.Name = input.ToProjectName(project.Slug)
p.Version = types.VersionCompatible
p.Version = types.VersionAny
return p, nil
Comment thread types/type_dependency.go
Comment on lines 19 to +23
// There are several special constants for ambiguous(adaptive) versions.
// You MUST call upstream.InferVersion() before parsing them to ResolvableVersion.
//
// Version selectors — all three are compatible with the detected server by
// default. They differ only in stability preference:
Comment thread types/type_dependency.go
Comment on lines +25 to +27
// - VersionAny (default): latest version regardless of release type.
// - VersionStable: only stable/release versions, no beta fallback.
// - VersionBeta: include beta and pre-release versions.
Comment thread state/manifest_test.go
Comment on lines 359 to 369
updated := UpdateManifestRolesForAdd(
manifest, []types.PackageRequest{
{
FullPackageRef: types.FullPackageRef{
PackageRef: types.PackageRef{
Platform: types.PlatformFabric, Name: "new-root",
},
Version: types.VersionLatest,
Scope: types.SourceModrinth,
Version: types.VersionAny,
Scope: types.SourceModrinth,
},
},
Comment thread state/manifest_test.go
Comment on lines 477 to 495
updated := UpdateManifestRolesForRemove(
manifest,
[]types.FullPackageRef{
{
PackageRef: types.PackageRef{
Platform: types.PlatformFabric,
Name: "root-a",
},
Version: types.VersionCompatible,
Scope: types.SourceAuto,
}, {
PackageRef: types.PackageRef{
Platform: types.PlatformFabric,
Name: "manual-jar",
},
Version: types.VersionCompatible,
Scope: types.SourceAuto,
Version: types.VersionAny,
Scope: types.SourceAuto,
}, {
PackageRef: types.PackageRef{
Platform: types.PlatformFabric,
Name: "manual-jar",
},
Version: types.VersionAny,
Scope: types.SourceAuto,
},
},
Comment thread state/manifest.go
Comment on lines 349 to +353
func NormalizeManifestVersionIntent(version types.BareVersion) string {
trimmed := strings.TrimSpace(version.String())
switch trimmed {
case "", "any", "none", "unknown":
return types.VersionCompatible.String()
return types.VersionAny.String()
@BFladderbeanawa BFladderbeanawa force-pushed the refactor/version-selectors branch from 533ed1e to fe8db9b Compare July 6, 2026 12:58
Copilot AI review requested due to automatic review settings July 6, 2026 17:18
@Arcadi4 Arcadi4 force-pushed the refactor/version-selectors branch from fe8db9b to da54d55 Compare July 6, 2026 17:18
@Arcadi4 Arcadi4 force-pushed the refactor/version-selectors branch from da54d55 to af0ea1b Compare July 6, 2026 17:19
Comment thread upstream/providers/mcdr/mcdr.go Outdated
case types.VersionCompatible:
ws := workspace.New()
case types.VersionStable:
serverInfo := workspace.ServerInfo()
Replace @latest/@compatible with @any/@stable/@beta selector constants. Keep compatibility as the baseline for all fuzzy selectors and encode release stability as the only selector difference.
Preserve VersionAny through install entry points and replace the old @compatible -> @latest -> @any retry chain with @stable -> @beta -> @any.
@Arcadi4 Arcadi4 force-pushed the refactor/version-selectors branch from af0ea1b to 80bfce0 Compare July 6, 2026 17:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

state/manifest.go:287

  • validateManifestEcosystem rejects empty values up-front, so the types.EcoUnspecified case can never match. At the same time, the docs/tests now refer to manifest platform none, which is currently rejected here. Consider explicitly accepting none (and drop the unreachable EcoUnspecified case).
// validateManifestEcosystem remains as a legacy helper for the pre-Task-2 lock
// schema, which still validates a single platform field.
func validateManifestEcosystem(value string) error {
	platform := types.Ecosystem(strings.TrimSpace(value))
	if platform == "" {
		return fmt.Errorf("environment.platform is required")
	}

	switch platform {
	case types.EcoFabric, types.EcoNeoforge, types.EcoForge, types.EcoMcdr, types.EcoUnspecified:
		return nil
	default:
		return fmt.Errorf("invalid environment.platform %q", value)
	}

Comment thread upstream/providers/mcdr/mcdr.go
Comment thread README.md
Comment on lines +251 to +253
### Runtime Topology

Lucy builds a graph of your server's runtime. Each node (Fabric, Forge, Paper, MCDR, Geyser, Velocity) carries a role, a set of capabilities (`fabric_mods`, `bukkit_plugins`, `mcdr_plugins`), and a risk level. Edges describe how nodes relate: one adapts another, one bridges to another. This graph powers `lucy status`, init discovery, and compatibility resolution.
Comment thread README_CN.md
Comment on lines +251 to +253
### 运行时拓扑

Lucy 为你的服务器构建一张运行时图。图中的每个节点(Fabric、Forge、Paper、MCDR、Geyser、Velocity)都有角色、能力(`fabric_mods`、`bukkit_plugins`、`mcdr_plugins`)和风险等级。边描述节点之间的关系:谁适配谁、谁桥接谁、谁代理谁。这张图是 `lucy status`、init 探测和兼容性解析的基础。
Copilot AI review requested due to automatic review settings July 6, 2026 17:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

upstream/providers/modrinth/modrinth_version.go:70

  • getVersion treats VersionStable the same as other inferable selectors via CanInfer() and calls latestVersion, which ignores loader compatibility and stability semantics. This can select a pre-release or an incompatible loader version when the caller requested @stable.
	if id.Version.CanInfer() {
		v, err = latestVersion(id.Name)
		if err != nil {
			return nil, err
		}

Comment on lines +148 to 153
case types.VersionStable:
serverInfo := workspace.ServerInfo()
rel, err = getLatestCompatibleRelease(
id.Name.Pep8String(),
ws.Environments.Mcdr.Version,
)
Comment thread types/type_dependency.go
Comment on lines +22 to +27
// Version selectors — all three are compatible with the detected server by
// default. They differ only in stability preference:
//
// - VersionAny (default): latest version regardless of release type.
// - VersionStable: only stable/release versions, no beta fallback.
// - VersionBeta: include beta and pre-release versions.
Comment on lines +24 to +26
// When a stability-preferring selector fails, fall back to VersionAny
// as a last resort (no stability filtering).
if id.Version == types.VersionStable {
Comment thread README.md
platform name version
```

`@any` is the default and selects the latest compatible version regardless of release type. `@stable` selects the latest compatible release only. `@beta` allows compatible pre-releases.
Comment thread README_CN.md
平台 名称 版本
```

`@any` 是默认值,选择任意稳定性的最新兼容版本。`@stable` 只选择最新兼容正式版。`@beta` 允许兼容预发布版本。
@Arcadi4 Arcadi4 force-pushed the refactor/version-selectors branch from 80bfce0 to a71931a Compare July 6, 2026 17:37
@Arcadi4 Arcadi4 merged commit 82de5c2 into main Jul 6, 2026
5 checks passed
@Arcadi4 Arcadi4 deleted the refactor/version-selectors branch July 6, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redesign version selector

3 participants