Skip to content

feat(resources): add managed resource command foundation#244

Merged
munezaclovis merged 4 commits into
mainfrom
feat/managed-resource-command-foundation
May 28, 2026
Merged

feat(resources): add managed resource command foundation#244
munezaclovis merged 4 commits into
mainfrom
feat/managed-resource-command-foundation

Conversation

@munezaclovis

@munezaclovis munezaclovis commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add shared Managed Resource install, update, uninstall, and list command plumbing over manifest refresh, downloads, installs, and state
  • require resource update commands to fetch a fresh artifact manifest instead of falling back to stale cached metadata
  • reuse already-valid installed releases before downloading artifacts again, so idempotent install/update paths stay safe offline
  • make uninstall a removal intent with explicit prune/force options, reject latest as a concrete track, and reject tracks that are not installed
  • report revoked-latest fallback metadata when installing the newest non-revoked artifact in a track

Scope

  • Covers roadmap PR 7: PV-046 and PV-048
  • Leaves real resource CLI namespaces and real adapters for later roadmap PRs
  • Records uninstall intent only; daemon reconciliation still owns runtime stops, artifact removal, data pruning, and installed metadata cleanup

Test plan

  • cargo fmt --all -- --check
  • cargo nextest run -p resources
  • cargo insta test --check --test-runner nextest -p resources --unreferenced reject
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
  • cargo nextest run --workspace --all-features --locked
  • cargo shear
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added a resource management command layer for install, update, uninstall, listing, and track metadata (including revocation and explicit removal-intent with prune/force).
    • Install now reuses existing releases when possible.
    • Added a manifest "refresh latest" operation that fetches and caches the latest manifest.
  • Tests

    • Expanded deterministic integration tests covering install/update/list/uninstall flows, revocation and failure modes, cache/manifest scenarios, and snapshot validations.
  • Chores

    • Crate manifest now references the internal state component and includes a migration for removal-intent.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ad8093b0-0879-4790-adae-9ba0a62eb1b3

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab43b1 and 083d203.

⛔ Files ignored due to path filters (13)
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_reports_cached_manifest_fallback.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_update_list_and_uninstall_fake_adapter.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_uses_existing_release_without_downloading_again.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_keep_installed_state_when_update_validation_fails.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_report_revoked_latest_fallback.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_uninstall_records_prune_and_force_intent.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_uninstall_rejects_in_use_tracks_without_force.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_update_all_installed_tracks_from_one_manifest_refresh.snap is excluded by !**/*.snap
  • crates/state/tests/snapshots/state_foundation__after_reinstall_intent.snap is excluded by !**/*.snap
  • crates/state/tests/snapshots/state_foundation__database_runs_migrations_and_exposes_core_schema.snap is excluded by !**/*.snap
  • crates/state/tests/snapshots/state_foundation__managed_resource_removal_intent_migration_backfills_existing_tracks.snap is excluded by !**/*.snap
  • crates/state/tests/snapshots/state_foundation__managed_resource_tracks_record_desired_and_installed_state.snap is excluded by !**/*.snap
  • crates/state/tests/snapshots/state_foundation__managed_resource_tracks_record_removal_intent_options.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • crates/resources/src/command.rs
  • crates/resources/tests/artifact_cache_download.rs
  • crates/resources/tests/managed_resource_commands.rs
  • crates/state/src/database.rs
  • crates/state/src/migrations.rs
  • crates/state/src/sql/002_managed_resource_removal_intent.sql
  • crates/state/tests/state_foundation.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/state/src/sql/002_managed_resource_removal_intent.sql
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/resources/tests/managed_resource_commands.rs
  • crates/resources/src/command.rs

📝 Walkthrough

Walkthrough

Adds a ManagedResourceCommands layer (install/update/list/uninstall), command-domain types/errors and accessors, installer reuse and staging cleanup, a manifest-cache latest-only refresh, DB removal-intent columns/migration, public re-exports, and deterministic integration tests with scripted fakes and artifact fixtures.

Changes

Managed Resource Commands API

Layer / File(s) Summary
Command API implementation and contracts
crates/resources/Cargo.toml, crates/resources/src/lib.rs, crates/resources/src/command.rs
Adds state workspace dependency, defines ManagedResourceCommandError and ManagedResourceCommandResult<T>, introduces command domain types (install/update/removal intent/uninstall options/track/revoked-latest), and implements ManagedResourceCommands (new/install/update/uninstall/list) with accessors.
Installer reuse and staging updates
crates/resources/src/install.rs
Adds install_existing_release helper; install reuses existing releases when present, prunes older releases, updates current, and ensures staging directory cleanup on success and on errors.
Manifest cache: latest-only refresh
crates/resources/src/cache.rs
Adds ArtifactManifestCache::refresh_latest which fetches/parses/writes the manifest without falling back to a cached copy and returns a Latest-tagged refresh result.
End-to-end deterministic tests and fixtures
crates/resources/tests/managed_resource_commands.rs, crates/resources/tests/artifact_cache_download.rs
Adds ScriptedClient, FakeAdapter, FailingWriter, gzipped-tar artifact builders, manifest builders, snapshot mappers, and many tests exercising install→update→list→uninstall flows plus multiple failure and edge-case scenarios.
State DB schema, queries, and migrations
crates/state/src/database.rs, crates/state/src/migrations.rs, crates/state/src/sql/002_managed_resource_removal_intent.sql, crates/state/tests/state_foundation.rs
Adds removal_prune/removal_force columns to managed_resource_tracks, updates queries/row mappings, adds record_managed_resource_track_removal_intent, and includes migration SQL plus tests validating backfill and behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant ManagedResourceCommands
  participant ArtifactManifestCache
  participant ResourceHttpClient
  participant ArtifactInstaller
  participant ResourceAdapter
  participant Database
  Caller->>ManagedResourceCommands: install(selector, client, adapter)
  ManagedResourceCommands->>ArtifactManifestCache: refresh / refresh_latest(manifest_url)
  ArtifactManifestCache->>ResourceHttpClient: get_text(manifest_url)
  ResourceHttpClient-->>ArtifactManifestCache: manifest JSON
  ArtifactManifestCache-->>ManagedResourceCommands: ArtifactManifest
  ManagedResourceCommands->>ManagedResourceCommands: select_latest(ArtifactManifest, platform)
  ManagedResourceCommands->>ArtifactInstaller: install_existing_release / install(artifact)
  ArtifactInstaller->>ResourceAdapter: validate_installation(install_root)
  ArtifactInstaller-->>ManagedResourceCommands: ArtifactInstall
  ManagedResourceCommands->>Database: record desired/installed state
  Caller->>ManagedResourceCommands: uninstall(resource, track, options)
  ManagedResourceCommands->>Database: read usage_count / write desired-removed
  ManagedResourceCommands-->>Caller: ManagedResourceRemovalIntent
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • prvious/pv#243: Integrates ResourceAdapter and managed-resource state types used by the new command layer.
  • prvious/pv#242: Adds ArtifactManifestCache behaviors that the new refresh_latest and command flows interact with.

Poem

A rabbit hops through manifest trees,
It fetches, caches, and unpacks with ease,
Scripts the bytes and fakes the calls,
Tracks removals, intents, and installs,
Hooray—tests pass, the garden’s at peace! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(resources): add managed resource command foundation' accurately captures the main purpose of the PR: introducing the command foundation for managing resources with install, update, uninstall, and list operations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/managed-resource-command-foundation

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
crates/resources/tests/managed_resource_commands.rs (1)

159-176: ⚡ Quick win

Prefer imported type names over fully-qualified type paths in test signatures.

Import these once at the top (ManagedResourceInstall, ManagedResourceUpdate, ManagedResourceTrackRecord) and use short type names in signatures for consistency.

As per coding guidelines, "PREFER top-level imports over local imports or fully qualified names in Rust".

Also applies to: 191-202

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/resources/tests/managed_resource_commands.rs` around lines 159 - 176,
Replace fully-qualified type paths in the test signatures with top-level
imports: add use statements for ManagedResourceInstall, ManagedResourceUpdate,
and ManagedResourceTrackRecord at the top of the file, then update the impl
blocks and function signatures (impl InstallSummary for
resources::ManagedResourceInstall, impl InstallSummary for
resources::ManagedResourceUpdate, and fn install_summary(install:
&resources::ManagedResourceInstall, ...) ) to use the short names
ManagedResourceInstall, ManagedResourceUpdate, and ManagedResourceTrackRecord
respectively so signatures are consistent with the project guideline.
crates/resources/src/command.rs (1)

2-20: ⚡ Quick win

Prefer top-level imports instead of fully-qualified names here.

Use imports for StateError and ArtifactInstaller to match the Rust style used in nearby code.

Suggested diff
-use state::{Database, ManagedResourceDesiredState, ManagedResourceTrackRecord, PvPaths};
+use state::{Database, ManagedResourceDesiredState, ManagedResourceTrackRecord, PvPaths, StateError};
 ...
 use crate::{
-    ArtifactDownloader, ArtifactManifestCache, ArtifactManifestSource, ArtifactVersion,
+    ArtifactDownloader, ArtifactInstaller, ArtifactManifestCache, ArtifactManifestSource, ArtifactVersion,
     ResourceAdapter, ResourceName, ResourcesError, TargetPlatform, TrackName, TrackSelector,
 };
 ...
-    State(#[from] state::StateError),
+    State(#[from] StateError),
 ...
-        let install = crate::ArtifactInstaller::new(self.paths.resources()).install(
+        let install = ArtifactInstaller::new(self.paths.resources()).install(

As per coding guidelines, "PREFER top-level imports over local imports or fully qualified names in Rust".

Also applies to: 92-92

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/resources/src/command.rs` around lines 2 - 20, The code uses
fully-qualified names (state::StateError and likely ArtifactInstaller) instead
of top-level imports; add `use state::StateError;` and `use
<crate_path>::ArtifactInstaller;` (replace <crate_path> with the actual module
path where ArtifactInstaller lives) at the top of
crates/resources/src/command.rs and update occurrences (e.g., the
ManagedResourceCommandError::State variant and any ArtifactInstaller references)
to use the imported names rather than `state::StateError` or fully-qualified
paths so the file follows the project's top-level import style.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/resources/tests/managed_resource_commands.rs`:
- Around line 259-275: The mocked/scripted client's download implementation
currently maps writer errors to ResourcesError::HttpRequestFailed; update the
error mapping so write_all errors are returned as
ResourcesError::DownloadWriteFailed (include the url and the source.to_string()
as the reason) while keeping the existing pop_front error behavior for missing
byte_responses; locate the download method (working with byte_responses and
write_all) and replace the map_err construction that builds HttpRequestFailed
with one that constructs DownloadWriteFailed.

---

Nitpick comments:
In `@crates/resources/src/command.rs`:
- Around line 2-20: The code uses fully-qualified names (state::StateError and
likely ArtifactInstaller) instead of top-level imports; add `use
state::StateError;` and `use <crate_path>::ArtifactInstaller;` (replace
<crate_path> with the actual module path where ArtifactInstaller lives) at the
top of crates/resources/src/command.rs and update occurrences (e.g., the
ManagedResourceCommandError::State variant and any ArtifactInstaller references)
to use the imported names rather than `state::StateError` or fully-qualified
paths so the file follows the project's top-level import style.

In `@crates/resources/tests/managed_resource_commands.rs`:
- Around line 159-176: Replace fully-qualified type paths in the test signatures
with top-level imports: add use statements for ManagedResourceInstall,
ManagedResourceUpdate, and ManagedResourceTrackRecord at the top of the file,
then update the impl blocks and function signatures (impl InstallSummary for
resources::ManagedResourceInstall, impl InstallSummary for
resources::ManagedResourceUpdate, and fn install_summary(install:
&resources::ManagedResourceInstall, ...) ) to use the short names
ManagedResourceInstall, ManagedResourceUpdate, and ManagedResourceTrackRecord
respectively so signatures are consistent with the project guideline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 309b7623-05c9-47b9-a7a9-61b32c72f62a

📥 Commits

Reviewing files that changed from the base of the PR and between c91db49 and 5947149.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_update_list_and_uninstall_fake_adapter.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_keep_installed_state_when_update_validation_fails.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • crates/resources/Cargo.toml
  • crates/resources/src/command.rs
  • crates/resources/src/lib.rs
  • crates/resources/tests/managed_resource_commands.rs

Comment thread crates/resources/tests/managed_resource_commands.rs
@munezaclovis

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac49a4f38d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/resources/src/command.rs Outdated

for record in installed_tracks {
let track = TrackName::new(record.track)?;
installs.push(self.install(adapter, TrackSelector::Track(track), client)?);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Force update to fetch a fresh manifest

When the update path delegates to install, it inherits ArtifactManifestCache::refresh's HTTP-error fallback to the cached manifest. In the offline or transient-network-failure case where a cached manifest exists, pv update can therefore succeed against stale metadata or reinstall the cached latest artifact instead of reporting that it could not check the current manifest, contrary to the design requirement that update refreshes the artifact manifest every time. Use an update-specific manifest refresh path that does not fall back to cache, or make the fallback behavior explicit.

Useful? React with 👍 / 👎.

Require update commands to fetch a fresh artifact manifest, reuse existing valid releases before downloading artifacts, and make uninstall intent explicit with prune/force options plus invalid-track guards.

Add integration snapshots for stale manifest rejection, idempotent installs, uninstall state durability, reserved alias rejection, and not-installed tracks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/resources/src/install.rs`:
- Around line 114-129: The current call to adapter.validate_installation(...)
(the reuse path in install()) must not propagate errors; instead, catch
validation failures and treat the reused release as corrupt so install() falls
back to a fresh download. Replace the direct call to
adapter.validate_installation(&release_path)? with a match or if let Err(err)
branch that logs/debugs the validation failure and returns Ok(None) (or
otherwise signals "no reuse") so prune_old_releases, update_current_pointer, and
the ArtifactInstall::new return are skipped; only proceed to pruning/updating
and returning Some(ArtifactInstall::new(...)) when validate_installation
succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ab30372b-7595-4464-802e-19c19ce533d0

📥 Commits

Reviewing files that changed from the base of the PR and between ac49a4f and 0ab43b1.

⛔ Files ignored due to path filters (11)
  • crates/resources/tests/snapshots/artifact_cache_download__manifest_cache_refresh_latest_does_not_fall_back_to_cached_manifest.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_update_list_and_uninstall_fake_adapter.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_install_uses_existing_release_without_downloading_again.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_keep_installed_state_when_update_validation_fails.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_report_revoked_latest_fallback.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_uninstall_records_prune_and_force_intent.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_uninstall_rejects_latest_alias_as_concrete_track.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_uninstall_rejects_tracks_that_are_not_installed.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_update_all_installed_tracks_from_one_manifest_refresh.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_update_requires_fresh_manifest_after_cache_exists.snap is excluded by !**/*.snap
  • crates/resources/tests/snapshots/managed_resource_commands__managed_resource_commands_update_without_installed_tracks_does_not_refresh_manifest.snap is excluded by !**/*.snap
📒 Files selected for processing (6)
  • crates/resources/src/cache.rs
  • crates/resources/src/command.rs
  • crates/resources/src/install.rs
  • crates/resources/src/lib.rs
  • crates/resources/tests/artifact_cache_download.rs
  • crates/resources/tests/managed_resource_commands.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/resources/src/lib.rs

Comment on lines +114 to +129
let previous_release = current_release_name(adapter.resource_name(), &current_path)?;
adapter.validate_installation(&release_path)?;
prune_old_releases(
&releases_dir,
artifact.artifact_version(),
previous_release.as_deref(),
)?;
update_current_pointer(&track_dir, artifact.artifact_version())?;

Ok(Some(ArtifactInstall::new(
adapter.resource_name().clone(),
track.clone(),
artifact.artifact_version().clone(),
release_path,
current_path,
)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't let a corrupt reused release block reinstall.

Line 115 currently propagates validate_installation failures out of the reuse path. If releases/<version> exists but is stale/corrupt, install() aborts instead of falling back to a fresh download, so the command cannot self-heal from the exact case this optimization should tolerate.

Suggested fix
         let previous_release = current_release_name(adapter.resource_name(), &current_path)?;
-        adapter.validate_installation(&release_path)?;
+        if adapter.validate_installation(&release_path).is_err() {
+            fs::remove_dir_all_if_exists(&release_path)?;
+            return Ok(None);
+        }
         prune_old_releases(
             &releases_dir,
             artifact.artifact_version(),
             previous_release.as_deref(),
         )?;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let previous_release = current_release_name(adapter.resource_name(), &current_path)?;
adapter.validate_installation(&release_path)?;
prune_old_releases(
&releases_dir,
artifact.artifact_version(),
previous_release.as_deref(),
)?;
update_current_pointer(&track_dir, artifact.artifact_version())?;
Ok(Some(ArtifactInstall::new(
adapter.resource_name().clone(),
track.clone(),
artifact.artifact_version().clone(),
release_path,
current_path,
)))
let previous_release = current_release_name(adapter.resource_name(), &current_path)?;
if adapter.validate_installation(&release_path).is_err() {
fs::remove_dir_all_if_exists(&release_path)?;
return Ok(None);
}
prune_old_releases(
&releases_dir,
artifact.artifact_version(),
previous_release.as_deref(),
)?;
update_current_pointer(&track_dir, artifact.artifact_version())?;
Ok(Some(ArtifactInstall::new(
adapter.resource_name().clone(),
track.clone(),
artifact.artifact_version().clone(),
release_path,
current_path,
)))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/resources/src/install.rs` around lines 114 - 129, The current call to
adapter.validate_installation(...) (the reuse path in install()) must not
propagate errors; instead, catch validation failures and treat the reused
release as corrupt so install() falls back to a fresh download. Replace the
direct call to adapter.validate_installation(&release_path)? with a match or if
let Err(err) branch that logs/debugs the validation failure and returns Ok(None)
(or otherwise signals "no reuse") so prune_old_releases, update_current_pointer,
and the ArtifactInstall::new return are skipped; only proceed to
pruning/updating and returning Some(ArtifactInstall::new(...)) when
validate_installation succeeds.

@munezaclovis
munezaclovis merged commit 78f7378 into main May 28, 2026
1 of 2 checks passed
@munezaclovis
munezaclovis deleted the feat/managed-resource-command-foundation branch May 28, 2026 13:12
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant