Skip to content

Harden Aspire skills bundle loading, validation, and caching - #19068

Merged
Ella Hathaway (ellahathaway) merged 21 commits into
mainfrom
ellahathaway-invalidate-aspire-skill-cache
Aug 18, 2026
Merged

Ella Hathaway (ellahathaway) merged 21 commits into
mainfrom
ellahathaway-invalidate-aspire-skill-cache

Conversation

@ellahathaway

@ellahathaway Ella Hathaway (ellahathaway) commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Description

The Aspire skills cache was keyed only by bundle version. If the contents of a published archive changed without a version change, the CLI continued loading the old extracted bundle from disk.

This PR makes the archive's SHA-512 digest part of the cache identity by storing each extracted bundle under <bundle-version>/<archive-sha512>. A CLI with a known embedded SHA-512 reuses only that exact cache leaf. Multiple same-version generations can coexist so CLIs carrying different snapshots do not replace each other's cache; inactive leaves age out according to their .lastused timestamps. Legacy flat cache entries are removed when a digest-addressed leaf is published. There is no migration for the unshipped .archive-sha256 layout.

GitHub release metadata and artifact attestations still identify release assets by SHA-256. GitHub-sourced cache leaves therefore persist .github-archive-sha256 alongside .archive-sha512; the installer uses that mapping to find the matching SHA-512 leaf before downloading the asset again. Downloaded bytes must match the advertised GitHub SHA-256 when one is present, while SHA-512 remains the bundle/cache integrity identity. The attestation verifier remains SHA-256-based.

The acquisition flow was also reorganized so each type has a clearer responsibility:

  • AspireSkillsInstaller selects the source and owns download, attestation, caching, locking, fallback, and cleanup policy.
  • AspireSkillsBundleProvider verifies and extracts archives, validates manifests and files, and creates or loads bundles.
  • EmbeddedAspireSkillsBundleProvider adapts the bundle embedded in the CLI and delegates bundle creation to the shared provider.
  • AspireSkillsBundle is a validated in-memory model, allowing its source directory to be replaced or removed safely after loading.

Remote fetching remains hidden and disabled by default, while explicit configuration is still honored. Network failures, truncated responses, and timeouts fall back to a previously verified matching cache or the embedded snapshot without swallowing caller cancellation.

Additional validation rejects unsafe archive paths and skill names, missing or excluded SKILL.md files, duplicate paths, incompatible manifests, archive digest mismatches, and files whose hashes do not match the manifest. Current bundles use per-file SHA-512; the already-attested v0.0.1 archive retains its legacy per-file SHA-256 hashes.

Offline behavior remains provenance-aware: when GitHub is unavailable, the CLI may reuse a cached GitHub bundle only when it was previously verified against the expected workflow. Installer-owned digest, provenance, and freshness markers are removed from extracted archive content and recreated from the acquisition result, so an archive cannot assert its own cache identity or provenance.

Fixes #19025

Track archive digests in the version cache, replace stale same-version content, preserve verified offline fallback, and separate bundle construction from installer acquisition and cache policy.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b41df8ad-bb69-4f8c-9447-88f3fd5206d3
Copilot AI balanced review requested due to automatic review settings August 6, 2026 18:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

@ellahathaway

Copy link
Copy Markdown
Contributor Author

PR testing

Result: ✅ Local source verification passed

All validation below ran locally on Windows against exact PR head ed8f8c3f7. GitHub runners remained queued, so the official dogfood artifact was unavailable and was not tested.

Automated validation

  • CLI source build: passed with 0 warnings and 0 errors
  • Focused bundle, installer, and Agent Init tests: 88/88 passed
  • Full Aspire.Cli.Tests run: 4,766 passed, 50 skipped, and 3 unrelated five-second timeouts under full-suite contention
  • Isolated timeout rerun: all affected methods passed together (5/5 in 1 second)

Local end-to-end validation

These were process-level scenarios, not unit tests. I rebuilt aspire.exe from the PR source and invoked the real executable with:

aspire agent init --workspace-root <fresh-workspace> --skill-locations standard --skills aspire --non-interactive

Each scenario used a fresh temporary workspace and an isolated ASPIRE_HOME.

Scenario What was validated Result
Fresh embedded installation Installed the embedded aspire skill and verified the cache directory and .archive-sha256 marker. ✅
Embedded digest mismatch Replaced the cached digest with zeroes and added stale content; Agent Init replaced the cache, removed the stale content, and restored the expected digest. ✅
Legacy cache recovery Deleted the digest marker; Agent Init replaced the legacy cache and recreated the marker. ✅
Malformed cache recovery Corrupted skill-manifest.json; Agent Init rejected and repaired the cache. ✅
Verified GitHub acquisition Enabled remote fetch, downloaded the real v0.0.1 release, verified its attestation, replaced the embedded cache, and recorded .github-attestation-verified. ✅
Verified GitHub cache reuse Added a sentinel to a valid provenance-marked cache; it remained after rerunning, proving the matching cache was loaded without replacement. ✅
GitHub same-version digest mismatch Changed the verified cache digest and added stale sentinels; Agent Init downloaded and verified the real release, replaced the cache, removed stale content, and restored the release digest. ✅

The published aspire-skills-v0.0.1.tgz digest was:

sha256:8a8022a250818c730c78a5054f485e0a09ec80ac60da63910cf5091684ceec9a

The GitHub scenarios emulated CLI 13.4.0 because the published v0.0.1 bundle supports >=13.4.0 <13.5.0. With the native 13.5.0-dev identity, the incompatible remote bundle was correctly rejected and the installer safely fell back to the embedded snapshot.

No PR-specific failures found. Official packaged-artifact and hosted-CI validation remain pending because the GitHub jobs were still queued.

@IEvangelist

Copy link
Copy Markdown
Member

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: ed8f8c3f7f29c5743f481af2c72cc0a90bfeed94
  • Official PR CLI: Not available. The Add Dogfooding Comment workflow run 31125094622 remained queued for more than 50 minutes and produced no Dogfood this PR comment.
  • Source Checkout: Detached temporary worktree verified at the exact expected commit.
  • Source-Built CLI: Physical version 13.5.0-dev; remote bundle tests used an explicit stable / 13.4.0 identity because the published v0.0.1 skills bundle supports 13.4.x.
  • Status: PARTIAL - source identity verified; packaged-artifact verification blocked by queued CI.

Changes Analyzed

Files Changed

  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundle.cs
  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs
  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs
  • src/Aspire.Cli/Agents/AspireSkills/EmbeddedAspireSkillsBundleProvider.cs
  • src/Aspire.Cli/Program.cs
  • tests/Aspire.Cli.Tests/Agents/AspireSkillsBundleTests.cs
  • tests/Aspire.Cli.Tests/Agents/AspireSkillsInstallerTests.cs
  • tests/Aspire.Cli.Tests/Commands/AgentInitCommandTests.cs
  • tests/Aspire.Cli.Tests/TestServices/FakePlaywrightServices.cs

Change Categories

  • CLI changes
  • Test changes
  • Hosting integration changes
  • Dashboard changes
  • Template changes
  • Client/component changes
  • VS Code extension changes
  • CI infrastructure changes

Test Scenarios Executed

Scenario 1: Focused source tests

Objective: Exercise bundle validation, digest invalidation, provenance, cache locking/cleanup, embedded fallback, and Agent Init integration at the exact PR head.

Coverage Type: Automated unit/integration

Status: PASS

Command:

dotnet test --project tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class '*.AspireSkillsInstallerTests' --filter-class '*.AspireSkillsBundleTests' --filter-class '*.AgentInitCommandTests' --filter-not-trait 'quarantined=true' --filter-not-trait 'outerloop=true'

Result: 88 passed, 0 failed, 0 skipped.

Evidence: evidence\focused-tests.log

Scenario 2: Embedded bundle installation and matching-cache reuse

Objective: Run the real source-built CLI against fresh workspaces with remote fetch disabled, install the aspire skill, verify digest metadata, and reuse the matching cache.

Coverage Type: Happy path

Status: PASS

Result: .github\skills\aspire\SKILL.md was installed in both workspaces, .archive-sha256 contained a normalized 64-character digest, and a cache sentinel survived the second run. Debug output explicitly reported the cached bundle was used.

Evidence:

  • evidence\embedded-first-run.log
  • evidence\embedded-second-run.log
  • evidence\embedded-cache-summary.txt

Scenario 3: Embedded same-version digest mismatch

Objective: Simulate stale content for the same bundle version by replacing the digest marker and adding a stale sentinel.

Coverage Type: Unhappy path

Status: PASS

Expected Outcome: Reject and replace the stale cache, remove stale content, restore the trusted embedded digest, and install the requested skill.

Result: The cache was replaced atomically, the sentinel was removed, and digest 8a8022a250818c730c78a5054f485e0a09ec80ac60da63910cf5091684ceec9a was restored.

Evidence:

  • evidence\embedded-digest-mismatch.log
  • evidence\embedded-digest-mismatch-summary.txt

Scenario 4: Verified GitHub acquisition and cache reuse

Objective: Exercise the opt-in remote-fetch path against the real microsoft/aspire-skills v0.0.1 release.

Coverage Type: Happy path / provenance

Status: PASS

Identity: ASPIRE_CLI_CHANNEL=stable, ASPIRE_CLI_VERSION=13.4.0; no commit or packages override.

Result: The release was downloaded and attested, .github-attestation-verified was created, the recorded digest matched 8a8022a250818c730c78a5054f485e0a09ec80ac60da63910cf5091684ceec9a, and a sentinel survived a matching-cache rerun.

Evidence:

  • evidence\emulated-cli-version.log
  • evidence\remote-first-run.log
  • evidence\remote-second-run.log
  • evidence\remote-cache-summary.txt

Scenario 5: GitHub same-version digest mismatch

Objective: Change the digest of a provenance-marked cache and confirm the current GitHub release replaces it.

Coverage Type: Unhappy path

Status: PASS

Expected Outcome: Download and re-attest the release, replace stale content, and restore both digest and provenance markers.

Result: The stale sentinel was removed, the release digest was restored, and the GitHub attestation marker was recreated.

Evidence:

  • evidence\remote-digest-mismatch.log
  • evidence\remote-digest-mismatch-summary.txt

Scenario 6: Verified GitHub cache while offline

Objective: Force GitHub requests through a refused local proxy and confirm a previously verified GitHub cache remains usable.

Coverage Type: Boundary / recovery

Status: PASS

Expected Outcome: Reuse only the provenance-marked cache when release metadata cannot be fetched.

Result: Debug output recorded GitHub acquisition failure followed by reuse of the previously verified cache. Its sentinel, digest, and attestation marker remained intact.

Evidence:

  • evidence\offline-verified-cache.log
  • evidence\offline-verified-summary.txt

Scenario 7: Untrusted mismatched cache while offline

Objective: Remove the GitHub attestation marker, change the digest, block GitHub, and verify the cache cannot assert its own provenance or identity.

Coverage Type: Security boundary / unhappy path

Status: PASS

Expected Outcome: Reject the untrusted cache and replace it from the trusted embedded bundle without creating a GitHub attestation marker.

Result: Debug output explicitly rejected the missing provenance and mismatched digest. The stale sentinel was removed, the embedded digest was restored, and no GitHub attestation marker was present afterward.

Evidence:

  • evidence\offline-unverified-cache.log
  • evidence\offline-unverified-summary.txt

Scenario Not Executed

Official dogfood CLI installation and template smoke test

Status: BLOCKED

No dogfood comment or installable packaged artifact was available because the workflow remained queued. Per the PR-testing artifact gate, the official CLI version could not be matched to the PR head, so artifact-based aspire new and smoke testing were not attempted.

Summary

Scenario Status Notes
Focused source tests PASS 88/88
Embedded install and cache reuse PASS Real CLI process, fresh workspaces
Embedded digest mismatch PASS Stale cache replaced
Verified GitHub acquisition/reuse PASS Real release and attestation
GitHub digest mismatch PASS Re-downloaded and replaced
Verified cache offline fallback PASS Provenance-aware reuse
Untrusted cache offline fallback PASS Rejected and replaced from embedded
Official dogfood artifact BLOCKED Workflow queued; no artifact/comment

Overall Result

SOURCE BEHAVIOR VERIFIED; PACKAGED PR ARTIFACT PENDING

No PR-specific failures were found in the exact-head source tests or process-level scenarios. Full PR verification remains incomplete until the official dogfood artifact is published and its reported commit matches the PR head.

Recommendation

Once workflow run 31125094622 publishes the dogfood comment, run only the remaining artifact-version check and a minimal packaged aspire agent init smoke scenario. No source change is recommended from the completed validation.

@IEvangelist David Pine (IEvangelist) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Found two correctness issues and one regression-coverage gap.

Comment thread src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs Outdated
Comment thread src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs
Comment thread tests/Aspire.Cli.Tests/Agents/AspireSkillsInstallerTests.cs Outdated
Copilot AI review requested due to automatic review settings August 6, 2026 19:28
@ellahathaway
Ella Hathaway (ellahathaway) force-pushed the ellahathaway-invalidate-aspire-skill-cache branch 2 times, most recently from aa01db8 to ed8f8c3 Compare August 6, 2026 19:29
Preserve known GitHub digests during offline fallback, reject null manifest entries, and strengthen digest invalidation and CLI cache reuse coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b41df8ad-bb69-4f8c-9447-88f3fd5206d3
@ellahathaway

Copy link
Copy Markdown
Contributor Author

Copilot review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19068

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19068"

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Fall back to verified cache or the embedded bundle for non-caller HTTP cancellation while preserving explicit caller cancellation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a679117e-daef-41d5-b8ce-013012e63e78
Copilot AI review requested due to automatic review settings August 17, 2026 17:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.

Comment thread src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs
Track whether current GitHub release metadata was available so an advertised asset without a usable digest cannot revive an unpinned same-version cache leaf.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a679117e-daef-41d5-b8ce-013012e63e78
Copilot AI review requested due to automatic review settings August 17, 2026 18:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

@github-actions

This comment has been minimized.

Exercise cancellation only after lock contention, prove cache reuse when the last-used marker cannot be updated, and remove redundant disabled-fetch cache coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a679117e-daef-41d5-b8ce-013012e63e78
Copilot AI review requested due to automatic review settings August 17, 2026 18:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

2 / 101 test projects · 5 jobs, from 12 changed files.

Selected test projects (2 / 101)

Aspire.Cli.EndToEnd.Tests, Aspire.Cli.Tests

Selected jobs (5)

cli-starter, deployment-e2e, extension-e2e, polyglot, typescript-api-compat


How these were chosen — grouped by what changed

📦 affected project Aspire.Cli
→ 1 test: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Cli.EndToEnd.Tests/AgentCommandTests.cs (changed test)
→ 1 directly: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Cli.Tests/Agents/AspireSkillsBundleTests.cs (changed test)
→ 1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Agents/AspireSkillsInstallerTests.cs (changed test)
→ 1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Commands/AgentInitCommandTests.cs (changed test)
→ 1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/TestServices/FakePlaywrightServices.cs (changed test)
→ 1 directly: Aspire.Cli.Tests

Job reasons

Job Triggered by
cli-starter • affected project Aspire.Cli
• selected test Aspire.Cli.Tests
deployment-e2e affected project Aspire.Cli
extension-e2e • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundle.cs, src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs, src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs, src/Aspire.Cli/Agents/AspireSkills/EmbeddedAspireSkillsBundleProvider.cs, src/Aspire.Cli/Agents/AspireSkills/SkillBundleManifest.cs, src/Aspire.Cli/Agents/AspireSkills/TemporaryCacheDirectory.cs, src/Aspire.Cli/Program.cs, tests/Aspire.Cli.EndToEnd.Tests/AgentCommandTests.cs, tests/Aspire.Cli.Tests/Agents/AspireSkillsBundleTests.cs, tests/Aspire.Cli.Tests/Agents/AspireSkillsInstallerTests.cs, tests/Aspire.Cli.Tests/Commands/AgentInitCommandTests.cs, tests/Aspire.Cli.Tests/TestServices/FakePlaywrightServices.cs
• affected project Aspire.Cli
polyglot affected project Aspire.Cli
typescript-api-compat affected project Aspire.Cli

Selection computed for commit 5b859be.

@ellahathaway

Copy link
Copy Markdown
Contributor Author

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: 5b859beeed75e6e3e08e2a55cea0a413b5c67bdc
  • Installed Version: 13.6.0-pr.19068.g5b859bee
  • Installed Binary: C:\Users\ellahathaway\AppData\Local\Temp\aspire-pr-test-19068-86465e3bd2d14284aedae7766fe12439\dogfood\pr-19068\bin\aspire.exe
  • Status: Verified - the packaged PR CLI reports the expected short commit 5b859bee.

Changes Analyzed

Files Changed

  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundle.cs
  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs
  • src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs
  • src/Aspire.Cli/Agents/AspireSkills/EmbeddedAspireSkillsBundleProvider.cs
  • src/Aspire.Cli/Agents/AspireSkills/SkillBundleManifest.cs
  • src/Aspire.Cli/Agents/AspireSkills/TemporaryCacheDirectory.cs
  • src/Aspire.Cli/Program.cs
  • Five matching CLI unit/E2E test and fake-service files

Change Categories

  • CLI changes - bundle validation, dual-digest acquisition, cache identity, locking, cleanup, fallback
  • Test changes - unit, command, and CLI E2E coverage
  • Hosting integration changes
  • Dashboard changes
  • Template changes
  • Client/component changes
  • VS Code extension changes
  • CI infrastructure changes

Test Scenarios Executed

Scenario 1: Focused exact-head source suite

Objective: Exercise bundle/provider validation, SHA-512 and legacy SHA-256 handling, GitHub mapping, metadata availability, timeouts, cancellation, cache locking/cleanup, embedded fallback, and Agent Init integration.

Coverage Type: Automated unit/integration

Status: Passed

Result: 127 passed, 0 failed, 0 skipped.

Evidence: focused-tests.log

Scenario 2: Fresh packaged embedded installation

Objective: Run the official PR CLI with remote fetch left at its production default.

Coverage Type: Happy path

Status: Passed

Result: Debug output reported remote fetch disabled. The CLI installed aspire, aspire-init, aspire-monitoring, and aspire-orchestration; created one 128-character SHA-512 cache leaf; and wrote a matching .archive-sha512 marker.

Evidence:

  • embedded-cache/first-init.log
  • embedded-cache/result.json

Scenario 3: Exact SHA-512 cache reuse

Objective: Prove a matching embedded leaf is loaded rather than replaced.

Coverage Type: Happy path / cache hit

Status: Passed

Result: Debug output reported a cache hit and a sentinel placed in the leaf survived the second Agent Init run.

Evidence: embedded-cache/second-init-cache-hit.log

Scenario 4: Corrupt SHA-512 marker recovery

Objective: Corrupt .archive-sha512, remove installed skills, and verify safe replacement.

Coverage Type: Unhappy path / recovery

Status: Passed

Expected Outcome: Reject the invalid leaf, restore the trusted SHA-512 identity, remove stale content, and reinstall all requested skills.

Result: The marker was restored to the 128-character leaf identity, the sentinel was removed, and all four skills were reinstalled.

Evidence: embedded-cache/third-init-corrupt-marker.log

Scenario 5: Real GitHub acquisition, attestation, and mapping

Objective: Enable the hidden remote-fetch feature explicitly and acquire the real microsoft/aspire-skills v0.0.1 release under supported CLI identity stable/13.4.0.

Coverage Type: Happy path / provenance

Status: Passed

Result: The CLI honored explicit configuration, verified GitHub provenance, created .github-attestation-verified, persisted GitHub SHA-256 8a8022a250818c730c78a5054f485e0a09ec80ac60da63910cf5091684ceec9a, mapped it to SHA-512 leaf d968e7c9268d92c5964490ee5f96182c06a1d48879fe3f56e496544c2ec172596307a82cb4d8d1ee5f680db33570c3f12aae8768f186a5deac973d2ca06ca8bf, and reused that leaf without downloading it again.

Evidence:

  • remote-cache/enable-remote-fetch.log
  • remote-cache/first-remote-init.log
  • remote-cache/second-remote-cache-hit.log
  • remote-cache/result.json

Scenario 6: Offline verified-cache fallback

Objective: Block GitHub through a refused local proxy while a provenance-marked leaf exists.

Coverage Type: Boundary / recovery

Status: Passed

Expected Outcome: Reuse only the verified GitHub leaf when release metadata cannot be fetched.

Result: Debug output reported the verified offline fallback, and the cache sentinel and attestation marker survived.

Evidence: offline-boundaries/verified-cache-offline.log

Scenario 7: Offline untrusted-cache rejection

Objective: Remove provenance, corrupt the archive marker, block GitHub, and rerun Agent Init.

Coverage Type: Security boundary / unhappy path

Status: Passed

Expected Outcome: Reject the untrusted cache and replace it from the embedded snapshot without retaining GitHub provenance metadata.

Result: The stale sentinel was removed, the SHA-512 marker was restored, all requested skills were installed, and both .github-attestation-verified and .github-archive-sha256 were absent afterward.

Evidence:

  • offline-boundaries/unverified-cache-offline.log
  • offline-boundaries/result.json

Scenario 8: PR hive template and AppHost lifecycle smoke

Objective: Create a fresh aspire-empty app from the downloaded PR hive and verify the generated file-based AppHost runs.

Coverage Type: Packaged CLI smoke

Status: Passed

Result: aspire new created apphost.cs; aspire start launched it; aspire ps reported it running; the dashboard returned HTTP 200; and aspire stop stopped it cleanly.

Evidence:

  • template-smoke/aspire-new.log
  • template-smoke/aspire-start-verified.log
  • template-smoke/aspire-ps-verified.log
  • template-smoke/aspire-stop-verified.log
  • template-smoke/result.json

Summary

Scenario Status Notes
Artifact version verification Passed Exact PR short commit 5b859bee
Focused source suite Passed 127/127
Fresh embedded install Passed Default-off remote fetch; SHA-512 leaf
Exact cache reuse Passed Sentinel survived
Corrupt marker recovery Passed Invalid leaf replaced
Remote acquisition and mapping Passed Real GitHub attestation and SHA-256 to SHA-512 mapping
Verified cache offline Passed Provenance-aware reuse
Untrusted cache offline Passed Rejected and replaced from embedded
PR hive AppHost smoke Passed Dashboard HTTP 200; clean stop

Overall Result

PR VERIFIED

The official PR artifact matches the latest head and all approved happy-path, recovery, provenance, offline, and packaged CLI scenarios passed. No PR-specific failures were found.

@adamint Adam Ratzman (adamint) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good overall; one cache-migration cleanup gap remains.

Comment thread src/Aspire.Cli/Agents/AspireSkills/AspireSkillsInstaller.cs
@ellahathaway
Ella Hathaway (ellahathaway) merged commit 555997d into main Aug 18, 2026
370 checks passed
@ellahathaway
Ella Hathaway (ellahathaway) deleted the ellahathaway-invalidate-aspire-skill-cache branch August 18, 2026 17:36
@microsoft-github-policy-service microsoft-github-policy-service Bot modified the milestones: 13.5, 13.6 Aug 18, 2026
@aspire-repo-bot

Copy link
Copy Markdown
Contributor

✅ No documentation update needed.

Step 5 branch taken: docs_optional → internal_refactor

Triggered signals: none (signal_count: 0, recommendation: docs_optional)

Rationale: All 12 changed files are internal CLI implementation/test files under src/Aspire.Cli/Agents/AspireSkills/ (AspireSkillsBundle.cs, AspireSkillsBundleProvider.cs, AspireSkillsInstaller.cs, EmbeddedAspireSkillsBundleProvider.cs, SkillBundleManifest.cs, TemporaryCacheDirectory.cs), plus Program.cs and test files under tests/Aspire.Cli.Tests / tests/Aspire.Cli.EndToEnd.Tests. The PR title ("Harden Aspire skills bundle loading, validation, and caching") and body confirm this is a purely internal hardening of the skills cache-key scheme (adding SHA-512 archive digest to the cache path), acquisition-flow reorganization (installer/provider responsibility split), and additional integrity/provenance validation. No new CLI commands, flags, options, or public API surface were added, and no user-visible behavior, output format, or error-message contract changes (the existing Embedded Aspire skills archive failed SHA-512 verification... error message already documented in get-started/aspire-skills.mdx is unchanged in meaning). This matches the internal_refactor allowlist category: touches src/ but introduces no new/changed public types, methods, options, or strings that affect documented user experience.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ CI Failure Analysis: Possible Flaky Test(s)

The CI build failed due to test failure(s) that appear unrelated to the PR changes. These may be flaky tests.

Suspected flaky test(s):

  • Aspire.Hosting.Maui.Tests.MauiBuildQueueTests.ReleaseSemaphoreAfterLaunchAsync_SkipsReplayStateAndReleasesOnStableState in job Tests / Hosting.Maui / Hosting.Maui (windows-latest)

Suggested actions:

  • Re-run the failed CI jobs to confirm if the failure is intermittent
  • If the test continues to fail, consider quarantining it using /quarantine-test <test name> <issue URL>
  • Search existing issues to see if this test is already known to be flaky

You can re-run the failed jobs from the workflow run page.

@github-actions github-actions Bot locked and limited conversation to collaborators Sep 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Invalidate cached Aspire skills bundles when archive content changes

4 participants