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-383 → load_optional_component_index() in resolution.rs:759-765 → load_component_index() in resolution.rs:721-756.
The chain fails at two points:
components-v2.toml returns HTTP 404 from the CDN mirror (not yet published)
- 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
- Additionally,
ComponentIndexEntry.targets (resolution.rs:56) lacks #[serde(default)], so v1 entries (which omit the targets field) fail TOML deserialization with missing field 'targets'
- 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
- On a host with anolisa 0.3.1 installed and no component in installed state
- Run
anolisa --json forget copilot-shell
- 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
- 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-shell → cosh 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:
COMPONENT_INDEX_SCHEMA_VERSION = 2 (line 20) with strict != 2 check (line 476): rejects v1 indexes
- Missing
#[serde(default)] on ComponentIndexEntry.targets (line 56): v1 entries lack targets, causing TOML deserialization failure
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:
- Change
validate() (line 476) from != COMPONENT_INDEX_SCHEMA_VERSION to !matches!(self.schema_version, 1 | 2)
- Add
#[serde(default)] to ComponentIndexEntry.targets (line 56)
- Change the targets emptiness check (line 495) to
if self.schema_version >= 2 && entry.targets.is_empty()
- 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]
Component
anolisa
Bug Description
anolisa forget copilot-shelldoes NOT resolve the package-name aliascopilot-shellto the canonical component namecosh. The command returnsNOT_INSTALLEDwithcomponent 'copilot-shell' is not installedinstead of resolving the alias and returningcomponent '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
forgetcommand (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()inresolution.rs:422-447requires a loadedComponentIndex, which comes fromcomponent_alias_from_repo_index()incommon.rs:373-383→load_optional_component_index()inresolution.rs:759-765→load_component_index()inresolution.rs:721-756.The chain fails at two points:
components-v2.tomlreturns HTTP 404 from the CDN mirror (not yet published)components.tomlfails becauseComponentIndex::validate()(resolution.rs:476) requiresschema_version == 2(strict), but the v1 file hasschema_version = 1ComponentIndexEntry.targets(resolution.rs:56) lacks#[serde(default)], so v1 entries (which omit thetargetsfield) fail TOML deserialization withmissing field 'targets'targets.is_empty()check (resolution.rs:495) would also reject v1 entries even if deserialization succeededWhen
load_optional_component_indexreturnsNone,lookup_component_aliasreturnsNone, and the caller falls back to the literal input string — soforget copilot-shelltreatscopilot-shellas a component name instead of resolving it tocosh.Steps to Reproduce
anolisa --json forget copilot-shell"error": {"code": "NOT_INSTALLED", "reason": "component 'copilot-shell' is not installed ..."}— the literal aliascopilot-shellis used instead of the canonical namecoshanolisa --json forget coshwhich returns"reason": "component 'cosh' is not installed ..."— proving the alias was not resolvedActual 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 ofcosh(the canonical name).anolisa listalso hard-fails withmissing field 'targets'when parsing the v1 components.toml.Expected Behavior
anolisa forget copilot-shellshould resolve the aliascopilot-shell→coshvia the component index, then return:{ "ok": false, "error": { "code": "NOT_INSTALLED", "reason": "component 'cosh' is not installed — nothing to forget" } }The
anolisa listcommand 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:COMPONENT_INDEX_SCHEMA_VERSION = 2(line 20) with strict!= 2check (line 476): rejects v1 indexes#[serde(default)]onComponentIndexEntry.targets(line 56): v1 entries lacktargets, causing TOML deserialization failureentry.targets.is_empty()check (line 495): rejects v1 entries even if deserialization succeededThe CDN mirror at
mirrors.cloud.aliyuncs.com/anolisa/generic/anolisa/v1/has publishedcomponents.toml(v1) but NOTcomponents-v2.toml(v2), returning HTTP 404. There is no v2→v1 fallback inload_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:validate()(line 476) from!= COMPONENT_INDEX_SCHEMA_VERSIONto!matches!(self.schema_version, 1 | 2)#[serde(default)]toComponentIndexEntry.targets(line 56)if self.schema_version >= 2 && entry.targets.is_empty()load_component_index(): if v2 fetch returns HTTP 404, retry with v1 URLThis matches the fix already implemented in PR #2564 / PR #2566.
Environment