refactor: rename aim to upm and extract appimage module
This commit is contained in:
parent
af13e98eb3
commit
863c57e473
117 changed files with 2622 additions and 887 deletions
|
|
@ -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"
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue