refactor: add upm application facade and module api
This commit is contained in:
parent
005d6ebfdb
commit
e2a01d3095
36 changed files with 1058 additions and 607 deletions
|
|
@ -2,57 +2,59 @@
|
|||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Validate AppImage as the first real provider module by making `upm-core` treat provider composition as the normal path for capability discovery, remote show resolution, and update execution.
|
||||
**Goal:** Make `upm-appimage` the first real package-manager module by moving AppImage-specific acquisition paths behind a module boundary and exposing a single application facade from `upm-core` to the CLI and future GUI.
|
||||
|
||||
**Architecture:** Keep AppImage-specific transport and resolution logic in `upm-appimage`. Extend `upm-core` only with generic provider-registry contracts and plumbing so the CLI can compose providers once and reuse that composition across `search`, `add`, `show`, and `update`. Avoid introducing speculative provider hooks for `remove` or `list`; those flows are already generic and should stay that way until a real provider needs more surface area.
|
||||
**Architecture:** `upm-core` becomes the application boundary. It should own a public facade, internal orchestration services, and module registration and composition. `upm` stays a thin frontend and must stop composing AppImage behavior directly. `upm-appimage` becomes the AppImage package-manager module and should absorb AppImageHub plus the other AppImage-producing backends that are still modeled as top-level source concepts in the core.
|
||||
|
||||
**Tech Stack:** Rust workspace, `upm`, `upm-core`, `upm-appimage`, Cargo integration tests, fixture-backed provider tests, CLI end-to-end tests.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Add capability discovery to `ProviderRegistry`
|
||||
### Task 1: Define the public application facade in `upm-core`
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/upm-core/src/app/providers.rs`
|
||||
- Modify: `crates/upm-core/src/app/`
|
||||
- Modify: `crates/upm-core/src/lib.rs`
|
||||
- Test: `crates/upm-core/tests/provider_registry.rs`
|
||||
- Test: `crates/upm-core/tests/`
|
||||
|
||||
**Step 1: Write the failing capability-discovery expectations**
|
||||
**Step 1: Write the failing facade expectations**
|
||||
|
||||
Extend `crates/upm-core/tests/provider_registry.rs` to assert:
|
||||
Add focused tests proving that:
|
||||
|
||||
- the registry can report which provider ids are registered
|
||||
- the registry can report whether a provider supports search and/or external add
|
||||
- empty registries report no capabilities
|
||||
- `upm-core` exposes one public application-facing entrypoint for frontend consumers
|
||||
- that entrypoint can be constructed without the CLI owning module composition
|
||||
- the public surface delegates to internal services instead of exposing module wiring details
|
||||
|
||||
Keep the expectations generic. Do not encode AppImage-only behavior into the registry API.
|
||||
Keep the assertions about API shape and ownership, not AppImage specifics.
|
||||
|
||||
**Step 2: Run the focused test to verify failure**
|
||||
**Step 2: Run the focused tests to verify failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test provider_registry
|
||||
cargo test --package upm-core
|
||||
```
|
||||
|
||||
Expected: FAIL because `ProviderRegistry` is still only a passive bag of references.
|
||||
Expected: FAIL because the current public surface still assumes narrower provider plumbing and does not expose the intended facade cleanly.
|
||||
|
||||
**Step 3: Implement minimal capability discovery**
|
||||
**Step 3: Implement the minimal facade**
|
||||
|
||||
Update `crates/upm-core/src/app/providers.rs` so `ProviderRegistry` exposes a small, stable query surface such as:
|
||||
Introduce or reshape the public API so `upm-core` exposes a single high-level application facade.
|
||||
|
||||
- a way to enumerate registered provider ids
|
||||
- a way to report capabilities for a provider id
|
||||
- a small capability record rather than operation-specific booleans scattered around callers
|
||||
The public boundary should:
|
||||
|
||||
Do not add plugin loading, global registries, or dynamic configuration yet.
|
||||
- represent product operations such as search, add, show, update, remove, and config handling
|
||||
- hide module registry and orchestration details from frontends
|
||||
- stay thin and delegate work to internal services
|
||||
|
||||
**Step 4: Run the focused test to verify pass**
|
||||
Do not add dynamic plugin loading yet.
|
||||
|
||||
**Step 4: Run the focused tests to verify pass**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test provider_registry
|
||||
cargo test --package upm-core
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
|
@ -60,113 +62,115 @@ Expected: PASS.
|
|||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add crates/upm-core/src/app/providers.rs crates/upm-core/src/lib.rs crates/upm-core/tests/provider_registry.rs
|
||||
git commit -m "feat: add provider capability discovery"
|
||||
git add crates/upm-core/src crates/upm-core/tests
|
||||
git commit -m "feat: add application facade to upm-core"
|
||||
```
|
||||
|
||||
### Task 2: Route remote `show` through registered providers
|
||||
### Task 2: Move module composition out of the CLI and into `upm-core`
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/upm-core/src/app/`
|
||||
- Modify: `crates/upm/src/lib.rs`
|
||||
- Modify: `crates/upm/src/providers.rs`
|
||||
- Test: `crates/upm-core/tests/`
|
||||
- Test: `crates/upm/tests/end_to_end_cli.rs`
|
||||
|
||||
**Step 1: Write the failing ownership expectations**
|
||||
|
||||
Add coverage proving that:
|
||||
|
||||
- the CLI does not assemble AppImage module composition directly
|
||||
- the application facade can build or receive module composition internally
|
||||
- CLI command paths still behave the same through the new boundary
|
||||
|
||||
Prefer one core ownership test and one CLI integration test.
|
||||
|
||||
**Step 2: Run the focused tests to verify failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
```
|
||||
|
||||
Expected: FAIL because the CLI still owns direct provider assembly.
|
||||
|
||||
**Step 3: Move composition into `upm-core`**
|
||||
|
||||
Update the architecture so:
|
||||
|
||||
- `upm-core` owns module registration and composition
|
||||
- the CLI constructs the application facade rather than AppImage-specific registries
|
||||
- direct module composition in `crates/upm/src/providers.rs` is removed or reduced to generic application bootstrapping
|
||||
|
||||
Keep CLI UX, rendering, and summary formatting unchanged.
|
||||
|
||||
**Step 4: Run the focused tests to verify pass**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add crates/upm-core/src crates/upm/src/lib.rs crates/upm/src/providers.rs crates/upm/tests/end_to_end_cli.rs
|
||||
git commit -m "refactor: move module composition into upm-core"
|
||||
```
|
||||
|
||||
### Task 3: Turn `upm-appimage` into the AppImage package-manager boundary
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/upm-appimage/src/`
|
||||
- Modify: `crates/upm-core/src/domain/source.rs`
|
||||
- Modify: `crates/upm-core/src/app/add.rs`
|
||||
- Modify: `crates/upm-core/src/app/show.rs`
|
||||
- Modify: `crates/upm/src/lib.rs`
|
||||
- Test: `crates/upm-core/tests/show_resolution.rs`
|
||||
- Test: `crates/upm/tests/end_to_end_cli.rs`
|
||||
|
||||
**Step 1: Write the failing `show` expectations**
|
||||
|
||||
Add coverage proving that:
|
||||
|
||||
- remote `show appimagehub/<id>` resolves through the registered provider path
|
||||
- installed-app `show` behavior remains unchanged
|
||||
- unsupported queries still fail distinctly from provider-backed remote queries
|
||||
|
||||
Prefer one new `upm-core` test for remote resolution and one CLI-facing assertion in `crates/upm/tests/end_to_end_cli.rs`.
|
||||
|
||||
**Step 2: Run the focused tests to verify failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test show_resolution
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
```
|
||||
|
||||
Expected: FAIL because the remote show path still calls the add planner without a `ProviderRegistry`.
|
||||
|
||||
**Step 3: Thread provider composition through `show`**
|
||||
|
||||
Update the show pipeline so:
|
||||
|
||||
- `upm-core` exposes provider-aware show entrypoints alongside the current defaults
|
||||
- remote show resolution uses `build_add_plan_with_registered_providers` rather than the provider-blind path
|
||||
- the CLI wraps remote show dispatch in `providers::with_provider_registry(...)`
|
||||
|
||||
Keep installed-record rendering and summary formatting unchanged.
|
||||
|
||||
**Step 4: Run the focused tests to verify pass**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test show_resolution
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add crates/upm-core/src/app/show.rs crates/upm/src/lib.rs crates/upm-core/tests/show_resolution.rs crates/upm/tests/end_to_end_cli.rs
|
||||
git commit -m "feat: route show through provider registry"
|
||||
```
|
||||
|
||||
### Task 3: Route `update` execution through registered providers
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/upm-core/src/app/update.rs`
|
||||
- Modify: `crates/upm/src/lib.rs`
|
||||
- Test: `crates/upm-core/tests/update_planning.rs`
|
||||
- Test: `crates/upm/tests/end_to_end_cli.rs`
|
||||
- Test: `crates/upm-appimage/tests/`
|
||||
- Test: `crates/upm-core/tests/`
|
||||
|
||||
**Step 1: Write the failing `update` expectations**
|
||||
**Step 1: Write the failing module-boundary expectations**
|
||||
|
||||
Add coverage proving that:
|
||||
|
||||
- AppImage-backed records can be refreshed through the update path with registered providers
|
||||
- existing GitHub and direct-url update behavior remains unchanged
|
||||
- the update execution path still restores previous payloads on failure
|
||||
- AppImage-backed acquisition through GitHub, GitLab, SourceForge, direct URLs, and AppImageHub resolves through `upm-appimage`
|
||||
- `upm-core` no longer treats those AppImage-producing backends as top-level package-manager concepts
|
||||
- add, show, and update continue to work through normalized module contracts
|
||||
|
||||
Prefer focused `upm-core` tests plus one CLI integration assertion for an AppImage-backed update review or execution path.
|
||||
Prefer module-focused tests plus a small number of core integration tests.
|
||||
|
||||
**Step 2: Run the focused tests to verify failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test update_planning
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
cargo test --package upm-appimage
|
||||
cargo test --package upm-core
|
||||
```
|
||||
|
||||
Expected: FAIL because update execution still rebuilds add plans without a `ProviderRegistry`.
|
||||
Expected: FAIL because AppImage acquisition paths are still split between the core and the AppImage module.
|
||||
|
||||
**Step 3: Thread provider composition through `update`**
|
||||
**Step 3: Move AppImage-specific acquisition logic behind the module**
|
||||
|
||||
Update the update pipeline so:
|
||||
Reshape the source and module boundary so:
|
||||
|
||||
- provider-aware update entrypoints exist in `upm-core`
|
||||
- `execute_update` rebuilds plans through the provider-aware add planner
|
||||
- the CLI wraps `update` execution in `providers::with_provider_registry(...)`
|
||||
- AppImage-specific GitHub, GitLab, SourceForge, AppImageHub, and direct URL handling lives in `upm-appimage`
|
||||
- `upm-core` coordinates AppImage work through normalized module contracts
|
||||
- core source taxonomy is reduced or reframed so package-manager concepts stay above backend minutia
|
||||
|
||||
Do not generalize the update-channel model yet. Reuse the current channel semantics and only change how provider-backed plans are rebuilt.
|
||||
Do not over-generalize for Flatpak or future providers yet. Only extract what the AppImage module demonstrably needs.
|
||||
|
||||
**Step 4: Run the focused tests to verify pass**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-core --test update_planning
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
cargo test --package upm-appimage
|
||||
cargo test --package upm-core
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
|
@ -174,57 +178,57 @@ Expected: PASS.
|
|||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add crates/upm-core/src/app/update.rs crates/upm/src/lib.rs crates/upm-core/tests/update_planning.rs crates/upm/tests/end_to_end_cli.rs
|
||||
git commit -m "feat: route updates through provider registry"
|
||||
git add crates/upm-appimage/src crates/upm-core/src crates/upm-appimage/tests crates/upm-core/tests
|
||||
git commit -m "refactor: make upm-appimage the appimage module boundary"
|
||||
```
|
||||
|
||||
### Task 4: Lock AppImage in as the reference provider module
|
||||
### Task 4: Route search, add, show, and update through the application facade
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/upm-appimage/tests/appimagehub_search.rs`
|
||||
- Modify: `crates/upm-core/src/app/`
|
||||
- Modify: `crates/upm/src/lib.rs`
|
||||
- Modify: `crates/upm/tests/end_to_end_cli.rs`
|
||||
- Modify: `crates/upm/tests/ui_summary.rs`
|
||||
- Test: `crates/upm-core/tests/provider_registry.rs`
|
||||
- Test: `crates/upm-core/tests/`
|
||||
|
||||
**Step 1: Write the failing reference-provider expectations**
|
||||
**Step 1: Write the failing facade-routing expectations**
|
||||
|
||||
Add end-to-end coverage proving that AppImage support is fully module-driven:
|
||||
|
||||
- `search` still surfaces AppImageHub hits through the registry
|
||||
- `show` for AppImageHub remote queries works through the registry
|
||||
- `update` can refresh AppImage-backed records through the registry
|
||||
- `search` flows through the public application facade
|
||||
- `add` flows through the public application facade
|
||||
- `show` flows through the public application facade
|
||||
- `update` flows through the public application facade
|
||||
- user-facing summaries still render truthful `upm` paths and origins
|
||||
|
||||
Keep the assertions focused on module composition rather than UI restyling.
|
||||
Keep the assertions focused on boundary correctness rather than UI restyling.
|
||||
|
||||
**Step 2: Run the focused tests to verify failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-appimage --test appimagehub_search
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
cargo test --package upm --test ui_summary
|
||||
```
|
||||
|
||||
Expected: FAIL until the new `show` and `update` registry plumbing is complete.
|
||||
Expected: FAIL until the facade is the normal command path.
|
||||
|
||||
**Step 3: Tighten provider-contract validation**
|
||||
**Step 3: Tighten application-boundary validation**
|
||||
|
||||
Update the tests so they prove:
|
||||
|
||||
- AppImage is composed only through `upm-appimage`
|
||||
- `ProviderRegistry` is the shared composition point for all AppImage-facing command paths
|
||||
- AppImage is still not reintroduced as a hardcoded built-in inside `upm-core`
|
||||
- frontend command handlers call the application facade rather than module-specific helpers
|
||||
- AppImage is composed only through `upm-core` and `upm-appimage`
|
||||
- AppImage is not reintroduced as a hardcoded built-in in the CLI
|
||||
|
||||
Do not move AppImageHub back into `all_adapter_kinds()`.
|
||||
Do not reintroduce package-manager-specific branching in the CLI.
|
||||
|
||||
**Step 4: Run the focused tests to verify pass**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cargo test --package upm-appimage --test appimagehub_search
|
||||
cargo test --package upm --test end_to_end_cli
|
||||
cargo test --package upm --test ui_summary
|
||||
```
|
||||
|
|
@ -234,35 +238,35 @@ Expected: PASS.
|
|||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add crates/upm-appimage/tests/appimagehub_search.rs crates/upm/tests/end_to_end_cli.rs crates/upm/tests/ui_summary.rs crates/upm-core/tests/provider_registry.rs
|
||||
git commit -m "test: validate appimage as reference provider module"
|
||||
git add crates/upm-core/src crates/upm/src/lib.rs crates/upm/tests/end_to_end_cli.rs crates/upm/tests/ui_summary.rs crates/upm-core/tests
|
||||
git commit -m "refactor: route commands through upm-core facade"
|
||||
```
|
||||
|
||||
### Task 5: Update architecture docs and run full verification
|
||||
### Task 5: Lock the architecture into docs and verify the workspace
|
||||
|
||||
**Files:**
|
||||
- Modify: `.architecture/overview.md`
|
||||
- Modify: `.architecture/roadmap.md`
|
||||
- Modify: `README.md`
|
||||
|
||||
**Step 1: Update docs for Milestone 1 completion state**
|
||||
**Step 1: Update docs for the new module model**
|
||||
|
||||
Document:
|
||||
|
||||
- capability discovery in `ProviderRegistry`
|
||||
- provider-aware `show` and `update` execution paths
|
||||
- AppImage as the first validated provider module on the new architecture
|
||||
- the explicit non-goal that `remove` and `list` remain generic until a provider needs extra hooks
|
||||
- `upm-core` as the application boundary
|
||||
- one public application facade over smaller internal services
|
||||
- CLI and GUI as thin frontends
|
||||
- `upm-appimage` as the AppImage package-manager boundary with internal acquisition backends
|
||||
|
||||
**Step 2: Verify the docs mention the Milestone 1 state**
|
||||
**Step 2: Verify the docs mention the agreed architecture**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
rg -n "ProviderRegistry|capabilit|upm-appimage|show|update" README.md .architecture/overview.md .architecture/roadmap.md
|
||||
rg -n "upm-core|facade|upm-ui|upm-appimage|module" README.md .architecture/overview.md .architecture/roadmap.md
|
||||
```
|
||||
|
||||
Expected: matches describing the expanded provider surface.
|
||||
Expected: matches describing the application boundary, thin frontends, and module ownership.
|
||||
|
||||
**Step 3: Run full verification**
|
||||
|
||||
|
|
@ -280,5 +284,5 @@ Expected: PASS.
|
|||
|
||||
```bash
|
||||
git add README.md .architecture/overview.md .architecture/roadmap.md
|
||||
git commit -m "docs: describe appimage provider milestone"
|
||||
git commit -m "docs: describe application facade architecture"
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue