refactor: rename aim to upm and extract appimage module

This commit is contained in:
stoorps 2026-03-21 22:39:11 +00:00
parent af13e98eb3
commit 863c57e473
Signed by: stoorps
SSH key fingerprint: SHA256:AZlPfu9hTu042EGtZElmDQoy+KvMOeShLDan/fYLoNI
117 changed files with 2622 additions and 887 deletions

View file

@ -0,0 +1,410 @@
# UPM Rename And Core Extraction Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Rename the product from `aim` to `upm`, remove legacy `aim` runtime interfaces, extract the shared headless backend into `upm-core`, and move AppImage-specific transport and provider logic into a separate `upm-appimage` module without regressing current AppImage workflows.
**Architecture:** Execute this in vertical slices. First rename the workspace, binary, paths, environment interfaces, and tests to `upm` without carrying legacy `aim` compatibility. Next introduce a narrow provider-composition seam in `upm-core` so AppImage-specific add and search logic can move into `upm-appimage` without creating a dependency cycle. Finally rewire the `upm` CLI to assemble built-in providers, update docs, and run full verification.
**Tech Stack:** Rust workspace, Cargo manifests, clap CLI, ratatui frontend crate, core domain/app modules, fixture-backed provider tests, workspace-wide `cargo test` and `cargo clippy`.
---
### Task 1: Rename the workspace, binary, and default runtime paths to `upm`
**Files:**
- Modify: `Cargo.toml`
- Rename: `crates/aim-cli` -> `crates/upm`
- Rename: `crates/aim-core` -> `crates/upm-core`
- Modify: `crates/upm/Cargo.toml`
- Modify: `crates/upm/src/main.rs`
- Modify: `crates/upm/src/lib.rs`
- Modify: `crates/upm/src/cli/args.rs`
- Modify: `crates/upm/src/config.rs`
- Modify: `crates/upm/src/cli/config.rs`
- Modify: `crates/upm-core/Cargo.toml`
- Modify: `crates/upm-core/src/platform/mod.rs`
- Modify: `crates/upm-core/src/integration/paths.rs`
- Modify: `crates/upm-core/src/integration/policy.rs`
- Test: `crates/upm/tests/cli_smoke.rs`
- Test: `crates/upm/tests/cli_commands.rs`
- Test: `crates/upm/tests/config_loading.rs`
- Test: `crates/upm-core/tests/install_paths.rs`
- Test: `crates/upm-core/tests/install_policy.rs`
**Step 1: Write the failing rename expectations**
Update the selected tests to assert:
- the binary name is `upm`
- clap parses `upm` instead of `aim`
- default config path is `~/.config/upm/config.toml`
- default registry path is `~/.local/share/upm/registry.toml`
- default managed payload roots are `.local/lib/upm/appimages` and `/opt/upm/appimages`
- desktop entry filenames use `upm-<stable-id>.desktop`
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --package aim-cli --test cli_smoke
cargo test --package aim-cli --test config_loading
cargo test --package aim-core --test install_paths
cargo test --package aim-core --test install_policy
```
Expected: FAIL because the workspace still exposes `aim`, `aim-cli`, `aim-core`, and `aim` default paths.
**Step 3: Perform the crate and manifest rename**
Run:
```bash
git mv crates/aim-cli crates/upm
git mv crates/aim-core crates/upm-core
```
Then update:
- workspace members and default members in `Cargo.toml`
- package names to `upm` and `upm-core`
- binary name to `upm`
- crate imports from `aim_core` to `upm_core`
- crate imports from `aim_cli` to `upm`
- clap command name from `aim` to `upm`
- default config, registry, payload-root, and desktop-entry paths to `upm`
**Step 4: Run the focused tests to verify pass**
Run:
```bash
cargo test --package upm --test cli_smoke
cargo test --package upm --test cli_commands
cargo test --package upm --test config_loading
cargo test --package upm-core --test install_paths
cargo test --package upm-core --test install_policy
```
Expected: PASS.
**Step 5: Commit**
```bash
git add Cargo.toml crates/upm crates/upm-core
git commit -m "refactor: rename workspace to upm"
```
### Task 2: Remove remaining `aim`-named runtime interfaces
**Files:**
- Modify: `crates/upm/src/config.rs`
- Modify: `crates/upm/src/cli/config.rs`
- Modify: `crates/upm/src/lib.rs`
- Modify: `crates/upm/src/ui/prompt.rs`
- Modify: `crates/upm-core/src/platform/mod.rs`
- Modify: `crates/upm-core/src/source/github.rs`
- Modify: `crates/upm-core/src/source/appimagehub.rs`
- Modify: `crates/upm-core/src/integration/refresh.rs`
- Test: `crates/upm/tests/config_loading.rs`
**Step 1: Write the failing strict-rename expectations**
Update representative tests to cover:
- config lookup uses `UPM_CONFIG_PATH`
- registry lookup uses `UPM_REGISTRY_PATH`
- old `AIM_*` config and registry overrides are ignored
- tracking preference uses `UPM_TRACKING_PREFERENCE`
- old `AIM_TRACKING_PREFERENCE` is ignored
- provider fixture execution uses the renamed `UPM_*` interfaces through CLI-facing tests
- managed install and summary output use `upm` paths and desktop prefixes
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --package upm --test config_loading
cargo test --package upm --test search_cli
cargo test --package upm --test end_to_end_cli
cargo test --package upm --test ui_summary
```
Expected: FAIL because representative CLI and config flows still depend on old `aim` names.
**Step 3: Remove the remaining `aim` interfaces**
Update the codebase so renamed runtime interfaces are consistently `upm`:
- environment variable names use `UPM_*`
- helper/debug prefixes print `[upm]`
- GitHub user agent identifies as `upm/0.1`
- old `aim` compatibility reads are removed instead of preserved
**Step 4: Run the focused tests to verify pass**
Run:
```bash
cargo test --package upm --test config_loading
cargo test --package upm --test search_cli
cargo test --package upm --test end_to_end_cli
cargo test --package upm --test ui_summary
```
Expected: PASS.
**Step 5: Commit**
```bash
git add crates/upm/src/config.rs crates/upm/src/cli/config.rs crates/upm/src/lib.rs crates/upm/src/ui/prompt.rs crates/upm-core/src/platform/mod.rs crates/upm-core/src/source/github.rs crates/upm-core/src/source/appimagehub.rs crates/upm-core/src/integration/refresh.rs crates/upm/tests/config_loading.rs
git commit -m "refactor: remove remaining aim runtime interfaces"
```
### Task 3: Add a provider-composition seam in `upm-core`
**Files:**
- Create: `crates/upm-core/src/app/providers.rs`
- Modify: `crates/upm-core/src/app/mod.rs`
- Modify: `crates/upm-core/src/app/add.rs`
- Modify: `crates/upm-core/src/app/search.rs`
- Modify: `crates/upm-core/src/lib.rs`
- Create: `crates/upm-core/tests/provider_registry.rs`
**Step 1: Write the failing provider-composition tests**
Create `crates/upm-core/tests/provider_registry.rs` with two focused tests:
- `build_search_results_with_registered_providers_uses_external_hits` using a stub external search provider
- `build_add_plan_with_registered_providers_delegates_appimagehub_like_sources` using a stub external add provider that returns a fixed artifact and release
The tests should prove that `upm-core` orchestration can consume provider-supplied search and add behavior without hardcoding AppImage-specific modules.
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --package upm-core --test provider_registry
```
Expected: FAIL because the orchestration layer still hardcodes AppImageHub in `app/add.rs` and `app/search.rs`.
**Step 3: Introduce the narrow composition API**
Create `crates/upm-core/src/app/providers.rs` with minimal types:
- `pub trait ExternalAddProvider`
- `pub struct ExternalAddResolution`
- `pub struct ProviderRegistry<'a>`
Requirements:
- `ProviderRegistry` carries `search_providers: Vec<&'a dyn SearchProvider>` and `external_add_providers: Vec<&'a dyn ExternalAddProvider>`
- `build_search_results` can delegate to `build_search_results_with` using providers supplied by the caller
- `build_add_plan_with_reporter_and_policy` gets a sibling entrypoint that accepts a `ProviderRegistry`
- core built-ins remain in `upm-core`; only AppImage-specific exact-resolution and search logic should move behind the new registry seam
Keep the interface intentionally small. Do not attempt plugin loading or dynamic discovery yet.
**Step 4: Run the focused tests to verify pass**
Run:
```bash
cargo test --package upm-core --test provider_registry
```
Expected: PASS.
**Step 5: Commit**
```bash
git add crates/upm-core/src/app/providers.rs crates/upm-core/src/app/mod.rs crates/upm-core/src/app/add.rs crates/upm-core/src/app/search.rs crates/upm-core/src/lib.rs crates/upm-core/tests/provider_registry.rs
git commit -m "refactor: add provider composition seam to upm-core"
```
### Task 4: Extract AppImage-specific logic into `upm-appimage`
**Files:**
- Modify: `Cargo.toml`
- Create: `crates/upm-appimage/Cargo.toml`
- Create: `crates/upm-appimage/src/lib.rs`
- Create: `crates/upm-appimage/src/add.rs`
- Create: `crates/upm-appimage/src/search.rs`
- Create: `crates/upm-appimage/src/source/mod.rs`
- Create: `crates/upm-appimage/src/source/appimagehub.rs`
- Modify: `crates/upm-core/src/adapters/mod.rs`
- Modify: `crates/upm-core/src/source/mod.rs`
- Modify: `crates/upm-core/src/app/add.rs`
- Modify: `crates/upm-core/src/app/search.rs`
- Create: `crates/upm-appimage/tests/appimagehub_search.rs`
- Modify: `crates/upm-core/tests/adapter_contract.rs`
- Modify: `crates/upm-core/tests/adapter_smoke.rs`
**Step 1: Write the failing extracted-module test**
Create `crates/upm-appimage/tests/appimagehub_search.rs` by moving the current AppImageHub search expectations out of `upm-core` and updating imports to target the new crate.
Also update the affected `upm-core` tests so they no longer import `AppImageHubAdapter` from `upm-core` directly.
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --package upm-appimage --test appimagehub_search
```
Expected: FAIL because the new crate does not exist yet.
**Step 3: Create the new crate and move AppImageHub implementation into it**
Move the AppImageHub-specific code into the new crate:
- transport and fixture logic from `upm-core/src/source/appimagehub.rs`
- AppImage-backed exact-resolution logic into `crates/upm-appimage/src/add.rs` implementing `ExternalAddProvider`
- AppImageHub search provider logic out of `upm-core/src/app/search.rs` into `crates/upm-appimage/src/search.rs`
`upm-appimage` should depend on `upm-core`, not the other way around.
Leave `SourceKind::AppImageHub`, `SourceInputKind::AppImageHub*`, and `NormalizedSourceKind::AppImageHub` in `upm-core` for this milestone. The deeper provider/domain generalization belongs to the next milestone.
**Step 4: Remove direct AppImageHub wiring from `upm-core`**
Update `upm-core` so it no longer declares:
- `pub mod appimagehub;` in `src/adapters/mod.rs`
- `pub mod appimagehub;` in `src/source/mod.rs`
- built-in AppImageHub search-provider construction in `src/app/search.rs`
- direct `AppImageHubAdapter` imports in `src/app/add.rs`
After this step, AppImage behavior should exist only through the provider registry seam from Task 3.
**Step 5: Run the focused tests to verify pass**
Run:
```bash
cargo test --package upm-appimage --test appimagehub_search
cargo test --package upm-core --test adapter_contract
cargo test --package upm-core --test adapter_smoke
```
Expected: PASS.
**Step 6: Commit**
```bash
git add Cargo.toml crates/upm-appimage crates/upm-core/src/adapters/mod.rs crates/upm-core/src/source/mod.rs crates/upm-core/src/app/add.rs crates/upm-core/src/app/search.rs crates/upm-core/tests/adapter_contract.rs crates/upm-core/tests/adapter_smoke.rs
git commit -m "refactor: extract appimage support into upm-appimage"
```
### Task 5: Rewire the `upm` CLI to assemble built-in providers from modules
**Files:**
- Modify: `crates/upm/Cargo.toml`
- Create: `crates/upm/src/providers.rs`
- Modify: `crates/upm/src/lib.rs`
- Test: `crates/upm/tests/search_cli.rs`
- Test: `crates/upm/tests/end_to_end_cli.rs`
- Test: `crates/upm/tests/ui_summary.rs`
**Step 1: Write the failing CLI integration expectations**
Update CLI integration tests to prove that:
- `upm search firefox` still includes AppImageHub results
- direct `upm appimagehub/2338455` install flow still succeeds through the CLI
- the final summary output still renders the new `upm`-prefixed paths and desktop-entry names
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --package upm --test search_cli
cargo test --package upm --test end_to_end_cli
cargo test --package upm --test ui_summary
```
Expected: FAIL because `upm` does not yet assemble AppImage providers through the extracted module.
**Step 3: Add CLI-side provider assembly**
Create `crates/upm/src/providers.rs` that:
- builds the `ProviderRegistry` for `upm-core`
- registers the `upm-appimage` search provider
- registers the `upm-appimage` external add provider
Update `crates/upm/src/lib.rs` so dispatch paths call the provider-aware core entrypoints instead of hardcoded core defaults.
Do not move progress rendering or config loading into `upm-core`; the CLI remains the presentation layer.
**Step 4: Run the focused tests to verify pass**
Run:
```bash
cargo test --package upm --test search_cli
cargo test --package upm --test end_to_end_cli
cargo test --package upm --test ui_summary
```
Expected: PASS.
**Step 5: Commit**
```bash
git add crates/upm/Cargo.toml crates/upm/src/providers.rs crates/upm/src/lib.rs crates/upm/tests/search_cli.rs crates/upm/tests/end_to_end_cli.rs crates/upm/tests/ui_summary.rs
git commit -m "refactor: compose providers from upm modules"
```
### Task 6: Update docs and run full workspace verification
**Files:**
- Modify: `README.md`
- Modify: `.architecture/overview.md`
- Modify: `.architecture/roadmap.md`
**Step 1: Update product and architecture docs**
Document:
- the workspace rename to `upm`
- `upm-core` as the headless application layer
- `upm-appimage` as the first installable provider module
- compatibility behavior for existing `aim` config and registry locations
- the fact that provider composition now happens in the CLI rather than through hardcoded AppImage paths in `upm-core`
**Step 2: Verify the docs mention the new structure**
Run:
```bash
rg -n "upm-core|upm-appimage|legacy aim|ProviderRegistry|upm" README.md .architecture/overview.md .architecture/roadmap.md
```
Expected: matches showing the renamed crates, provider split, and compatibility note.
**Step 3: Run the full verification suite**
Run:
```bash
cargo fmt --all
cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Expected: PASS.
**Step 4: Commit**
```bash
git add README.md .architecture/overview.md .architecture/roadmap.md
git commit -m "docs: describe upm core and module split"
```