14 KiB
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
upminstead ofaim - 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/appimagesand/opt/upm/appimages - desktop entry filenames use
upm-<stable-id>.desktop
Step 2: Run the focused tests to verify failure
Run:
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:
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
upmandupm-core - binary name to
upm - crate imports from
aim_coretoupm_core - crate imports from
aim_clitoupm - clap command name from
aimtoupm - default config, registry, payload-root, and desktop-entry paths to
upm
Step 4: Run the focused tests to verify pass
Run:
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
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_PREFERENCEis ignored - provider fixture execution uses the renamed
UPM_*interfaces through CLI-facing tests - managed install and summary output use
upmpaths and desktop prefixes
Step 2: Run the focused tests to verify failure
Run:
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
aimcompatibility reads are removed instead of preserved
Step 4: Run the focused tests to verify pass
Run:
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
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_hitsusing a stub external search providerbuild_add_plan_with_registered_providers_delegates_appimagehub_like_sourcesusing 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:
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 ExternalAddProviderpub struct ExternalAddResolutionpub struct ProviderRegistry<'a>
Requirements:
ProviderRegistrycarriessearch_providers: Vec<&'a dyn SearchProvider>andexternal_add_providers: Vec<&'a dyn ExternalAddProvider>build_search_resultscan delegate tobuild_search_results_withusing providers supplied by the callerbuild_add_plan_with_reporter_and_policygets a sibling entrypoint that accepts aProviderRegistry- 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:
cargo test --package upm-core --test provider_registry
Expected: PASS.
Step 5: Commit
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:
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.rsimplementingExternalAddProvider - AppImageHub search provider logic out of
upm-core/src/app/search.rsintocrates/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;insrc/adapters/mod.rspub mod appimagehub;insrc/source/mod.rs- built-in AppImageHub search-provider construction in
src/app/search.rs - direct
AppImageHubAdapterimports insrc/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:
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
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 firefoxstill includes AppImageHub results- direct
upm appimagehub/2338455install 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:
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
ProviderRegistryforupm-core - registers the
upm-appimagesearch provider - registers the
upm-appimageexternal 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:
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
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-coreas the headless application layerupm-appimageas the first installable provider module- compatibility behavior for existing
aimconfig 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:
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:
cargo fmt --all
cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
Expected: PASS.
Step 4: Commit
git add README.md .architecture/overview.md .architecture/roadmap.md
git commit -m "docs: describe upm core and module split"