Skip to content

[Nightly] anolisa forget copilot-shell fails to resolve alias to cosh #2572

Description

@zhangtaibo

Component

anolisa

Bug Description

anolisa forget copilot-shell does NOT resolve the package-name alias copilot-shell to the canonical component name cosh. The command returns NOT_INSTALLED with component 'copilot-shell' is not installed instead of resolving the alias and returning component 'cosh' is not installed.

This breaks the alias resolution contract established by PR #1275 (issue #1272, released in anolisa 0.1.20), which unified component name alias resolution across all CLI commands. The forget command (and 6 other lifecycle commands: uninstall/update/restart/status/doctor/adapter) should resolve package-name aliases to canonical component names before checking state.

Root cause: lookup_component_alias() in resolution.rs:422-447 requires a loaded ComponentIndex, which comes from component_alias_from_repo_index() in common.rs:373-383load_optional_component_index() in resolution.rs:759-765load_component_index() in resolution.rs:721-756.

The chain fails at two points:

  1. components-v2.toml returns HTTP 404 from the CDN mirror (not yet published)
  2. The v1 fallback to components.toml fails because ComponentIndex::validate() (resolution.rs:476) requires schema_version == 2 (strict), but the v1 file has schema_version = 1
  3. Additionally, ComponentIndexEntry.targets (resolution.rs:56) lacks #[serde(default)], so v1 entries (which omit the targets field) fail TOML deserialization with missing field 'targets'
  4. The targets.is_empty() check (resolution.rs:495) would also reject v1 entries even if deserialization succeeded

When load_optional_component_index returns None, lookup_component_alias returns None, and the caller falls back to the literal input string — so forget copilot-shell treats copilot-shell as a component name instead of resolving it to cosh.

Steps to Reproduce

  1. On a host with anolisa 0.3.1 installed and no component in installed state
  2. Run anolisa --json forget copilot-shell
  3. Observe the JSON response contains "error": {"code": "NOT_INSTALLED", "reason": "component 'copilot-shell' is not installed ..."} — the literal alias copilot-shell is used instead of the canonical name cosh
  4. Compare with anolisa --json forget cosh which returns "reason": "component 'cosh' is not installed ..." — proving the alias was not resolved

Actual Behavior

{
  "ok": false,
  "schema_version": 1,
  "command": "forget copilot-shell",
  "error": {
    "code": "NOT_INSTALLED",
    "reason": "component 'copilot-shell' is not installed — nothing to forget"
  }
}

The response mentions copilot-shell (the alias) instead of cosh (the canonical name). anolisa list also hard-fails with missing field 'targets' when parsing the v1 components.toml.

Expected Behavior

anolisa forget copilot-shell should resolve the alias copilot-shellcosh via the component index, then return:

{
  "ok": false,
  "error": {
    "code": "NOT_INSTALLED",
    "reason": "component 'cosh' is not installed — nothing to forget"
  }
}

The anolisa list command should also succeed by loading the v1 components.toml when v2 is unavailable.

Root Cause

Three issues in src/anolisa/crates/anolisa-cli/src/resolution.rs:

  1. COMPONENT_INDEX_SCHEMA_VERSION = 2 (line 20) with strict != 2 check (line 476): rejects v1 indexes
  2. Missing #[serde(default)] on ComponentIndexEntry.targets (line 56): v1 entries lack targets, causing TOML deserialization failure
  3. entry.targets.is_empty() check (line 495): rejects v1 entries even if deserialization succeeded

The CDN mirror at mirrors.cloud.aliyuncs.com/anolisa/generic/anolisa/v1/ has published components.toml (v1) but NOT components-v2.toml (v2), returning HTTP 404. There is no v2→v1 fallback in load_component_index().

Related: PR #2564 and PR #2566 already implement the fix but are not yet merged to main.

Suggested Fix

In src/anolisa/crates/anolisa-cli/src/resolution.rs:

  1. Change validate() (line 476) from != COMPONENT_INDEX_SCHEMA_VERSION to !matches!(self.schema_version, 1 | 2)
  2. Add #[serde(default)] to ComponentIndexEntry.targets (line 56)
  3. Change the targets emptiness check (line 495) to if self.schema_version >= 2 && entry.targets.is_empty()
  4. Add v2→v1 fallback in load_component_index(): if v2 fetch returns HTTP 404, retry with v1 URL

This matches the fix already implemented in PR #2564 / PR #2566.

Environment

  • OS: Anolis 8 (kernel 5.10.134-19.1.al8.x86_64)
  • anolisa: 0.3.1 (binary at /usr/local/bin/anolisa)
  • RPM: anolisa-0.2.15-2.alnx4.x86_64
  • Nightly run: nightly-20260814-170909
  • Test case: tests/test_rpm_install_uninstall.py::test_forget_accepts_package_name_alias[copilot-shell-to-cosh]

Metadata

Metadata

Labels

component:anolisasrc/anolisapriority:p2Normal: planned product or engineering worktype:bugA confirmed defect or incorrect behavior

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions