13 KiB
Source And Provider Expansion Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Make GitLab and SourceForge real repository-backed install sources, preserve direct URL as a first-class exact-resolution source, and keep zsync as update metadata rather than an install provider.
Architecture: Normalize the source taxonomy first, then add a capability-shaped resolver layer that distinguishes repository-backed sources from exact artifact sources. Preserve truthful install origin data in the registry and let update planning attach richer metadata without rewriting source identity.
Tech Stack: Rust, Cargo workspace, aim-core source and adapter modules, existing fixture-backed integration tests in crates/aim-core/tests, CLI end-to-end tests in crates/aim-cli/tests, existing registry and update planning code.
Follow-up Status
Task 1 hit a classification ambiguity blocker after the initial rollout. The follow-up design and execution live in .plans/007-source-provider-expansion/2026-03-20-task-1-ambiguity-handoff-addendum.md.
Current state on this branch:
- ambiguous GitLab deep paths and one SourceForge nested download path are now preserved as provider-owned candidate kinds during classification
- the first GitLab candidate slice now resolves as a concrete repository-backed install source at the adapter layer
- the SourceForge
files/releases/stable/downloadcandidate slice now resolves as a concrete latest-download install source at the adapter layer - the SourceForge
files/releases/v*/downloadslice is now preserved as a provider-owned candidate and reportsNoInstallableArtifact - unsupported queries remain distinct from provider-owned no-artifact outcomes
Classifier policy for follow-up work:
- accept explicit concrete shapes
- accept explicit provider-candidate shapes
- reject everything else
Future changes should expand the allowlist deliberately rather than adding broad negative-rule coverage for every unsupported provider page family.
Task 1: Lock down source taxonomy with failing classification tests
Files:
- Modify:
crates/aim-core/tests/query_resolution.rs - Modify:
crates/aim-core/src/source/input.rs - Modify:
crates/aim-core/src/domain/source.rs
Step 1: Write the failing tests
Add classification tests that cover:
- GitLab repository and release-like URL forms that should classify as
GitLab - supported SourceForge URL forms that should classify as
SourceForge - direct URLs that must remain
DirectUrl - malformed provider URLs that must fail as unsupported
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test query_resolution
Expected: FAIL because SourceForge is not yet part of the public source taxonomy and current classification rules are too narrow.
Step 3: Write minimal classification changes
Update the source domain and classifier so the public source taxonomy includes the approved source kinds and supported input forms without introducing zsync as an install source.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test query_resolution
Expected: PASS.
Step 5: Commit
git add crates/aim-core/tests/query_resolution.rs crates/aim-core/src/source/input.rs crates/aim-core/src/domain/source.rs
git commit -m "test: cover expanded source taxonomy"
Task 2: Add a shared resolver contract for source capabilities
Files:
- Modify:
crates/aim-core/src/adapters/traits.rs - Modify:
crates/aim-core/src/adapters/mod.rs - Modify:
crates/aim-core/tests/adapter_contract.rs - Modify:
crates/aim-core/src/app/query.rs
Step 1: Write the failing tests
Add contract tests that assert:
- repository-backed resolvers accept only their own source kinds
- exact-resolution resolvers accept only exact artifact kinds
- resolvers can return structured “no installable artifact” outcomes rather than collapsing to unsupported
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test adapter_contract
Expected: FAIL because the current adapter trait does not distinguish source capability outcomes cleanly enough.
Step 3: Write minimal resolver contract changes
Refine the shared adapter or resolver contract to represent:
- unsupported source kind
- supported source with successful artifact resolution
- supported source with no installable artifact found
Keep the API small and do not add terminal concerns.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test adapter_contract
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/adapters/traits.rs crates/aim-core/src/adapters/mod.rs crates/aim-core/tests/adapter_contract.rs crates/aim-core/src/app/query.rs
git commit -m "feat: add capability-shaped resolver contract"
Task 3: Make GitLab a real repository-backed install source
Files:
- Modify:
crates/aim-core/src/adapters/gitlab.rs - Modify:
crates/aim-core/src/app/add.rs - Modify:
crates/aim-core/tests/adapter_contract.rs - Modify:
crates/aim-core/tests/install_integration.rs - Modify:
crates/aim-cli/tests/end_to_end_cli.rs
Step 1: Write the failing tests
Add tests that assert:
- a GitLab source resolves to a concrete install candidate
- install flow persists a truthful GitLab install origin
- CLI integration can install a fixture-backed GitLab source end to end
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test install_integration
Expected: FAIL because GitLab resolution is currently placeholder-level and not wired into the add flow meaningfully.
Step 3: Write minimal implementation
Implement GitLab-specific repository-backed resolution using the new resolver contract and thread the result through the add flow without changing direct URL or zsync semantics.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test install_integration
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/adapters/gitlab.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/adapter_contract.rs crates/aim-core/tests/install_integration.rs crates/aim-cli/tests/end_to_end_cli.rs
git commit -m "feat: add gitlab install source resolution"
Task 4: Preserve direct URL as an exact-resolution source
Files:
- Modify:
crates/aim-core/src/adapters/direct_url.rs - Modify:
crates/aim-core/src/app/add.rs - Modify:
crates/aim-core/tests/install_integration.rs - Modify:
crates/aim-cli/tests/end_to_end_cli.rs
Step 1: Write the failing tests
Add tests that assert:
- direct URL installs continue to resolve exactly to the provided artifact
- registry persistence keeps the original direct URL source kind and locator
- no provider-like reclassification occurs after install
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test install_integration
Expected: FAIL if the new resolver contract or registry changes accidentally regress exact-resolution behavior.
Step 3: Write minimal implementation
Adjust the direct URL path to use the new resolver interfaces while preserving exact-resolution semantics and best-effort metadata only.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test install_integration
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/adapters/direct_url.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/install_integration.rs crates/aim-cli/tests/end_to_end_cli.rs
git commit -m "feat: preserve direct url exact resolution semantics"
Task 5: Add SourceForge as a repository-backed source for supported project forms
Files:
- Modify:
crates/aim-core/src/adapters/sourceforge.rs - Modify:
crates/aim-core/src/source/input.rs - Modify:
crates/aim-core/src/app/add.rs - Modify:
crates/aim-core/tests/adapter_contract.rs - Modify:
crates/aim-core/tests/install_integration.rs - Modify:
crates/aim-cli/tests/end_to_end_cli.rs
Step 1: Write the failing tests
Add tests that assert:
- supported SourceForge URL or project forms classify correctly
- SourceForge resolution can produce a concrete install candidate
- SourceForge installs persist truthful origin data
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test adapter_contract
Expected: FAIL because SourceForge currently returns unsupported from its adapter.
Step 3: Write minimal implementation
Implement only the supported SourceForge project or download forms needed for exact current-product scope. Return structured no-artifact failures for valid-but-non-installable projects.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test adapter_contract
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/adapters/sourceforge.rs crates/aim-core/src/source/input.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/adapter_contract.rs crates/aim-core/tests/install_integration.rs crates/aim-cli/tests/end_to_end_cli.rs
git commit -m "feat: add sourceforge install source resolution"
Task 6: Keep registry origin truthful and update metadata additive
Files:
- Modify:
crates/aim-core/src/registry/model.rs - Modify:
crates/aim-core/src/app/add.rs - Modify:
crates/aim-core/src/app/update.rs - Modify:
crates/aim-core/src/update/channels.rs - Modify:
crates/aim-core/tests/update_planning.rs - Modify:
crates/aim-core/tests/registry_roundtrip.rs
Step 1: Write the failing tests
Add tests that assert:
- GitLab and SourceForge installs preserve original source kind and locator after roundtrip persistence
- direct URL installs remain direct URL installs after metadata inspection
- discovered update channels augment stored state without rewriting source identity
- zsync remains update metadata only
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test update_planning
Expected: FAIL because update planning and registry expectations do not yet fully encode the approved source-versus-update split.
Step 3: Write minimal implementation
Adjust registry and update planning logic so install origin remains canonical and update channels remain additive metadata.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test update_planning
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/registry/model.rs crates/aim-core/src/app/add.rs crates/aim-core/src/app/update.rs crates/aim-core/src/update/channels.rs crates/aim-core/tests/update_planning.rs crates/aim-core/tests/registry_roundtrip.rs
git commit -m "feat: preserve source identity through update planning"
Task 7: Improve provider-aware error reporting without changing CLI shape
Files:
- Modify:
crates/aim-core/src/adapters/traits.rs - Modify:
crates/aim-core/src/app/add.rs - Modify:
crates/aim-cli/src/lib.rs - Modify:
crates/aim-core/tests/install_failures.rs - Modify:
crates/aim-cli/tests/end_to_end_cli.rs
Step 1: Write the failing tests
Add tests that distinguish:
- unsupported source semantics
- supported source with no installable artifact
- transport or integration failure
Step 2: Run test to verify it fails
Run: cargo test --package aim-core --test install_failures
Expected: FAIL because failure reasons are not yet structured enough to preserve those distinctions.
Step 3: Write minimal implementation
Introduce explicit failure categories and thread them through the add flow so the CLI can render clearer provider-aware messages without changing the progress UI architecture.
Step 4: Run test to verify it passes
Run: cargo test --package aim-core --test install_failures
Expected: PASS.
Step 5: Commit
git add crates/aim-core/src/adapters/traits.rs crates/aim-core/src/app/add.rs crates/aim-cli/src/lib.rs crates/aim-core/tests/install_failures.rs crates/aim-cli/tests/end_to_end_cli.rs
git commit -m "feat: clarify provider-aware source resolution failures"
Task 8: Full verification
Files:
- Modify:
README.md - Modify:
crates/aim-core/tests/github_source_discovery.rs - Modify:
crates/aim-core/tests/query_resolution.rs - Modify:
crates/aim-core/tests/install_integration.rs - Modify:
crates/aim-core/tests/update_planning.rs - Modify:
crates/aim-cli/tests/end_to_end_cli.rs
Step 1: Tighten any stale expectations
Update docs and tests so the product contract matches the approved design:
- GitLab and SourceForge are install sources
- direct URL remains exact-resolution
- zsync remains update metadata
Step 2: Run focused workspace verification
Run: cargo test --package aim-core --test query_resolution --test adapter_contract --test install_integration --test update_planning --test install_failures
Expected: PASS.
Step 3: Run CLI verification
Run: cargo test --package aim-cli --test end_to_end_cli
Expected: PASS.
Step 4: Run full workspace verification
Run: cargo fmt --all && cargo test --workspace
Expected: PASS.
Step 5: Commit
git add README.md crates/aim-core/tests/github_source_discovery.rs crates/aim-core/tests/query_resolution.rs crates/aim-core/tests/install_integration.rs crates/aim-core/tests/update_planning.rs crates/aim-core/tests/install_failures.rs crates/aim-cli/tests/end_to_end_cli.rs
git commit -m "docs: align source provider contract and tests"