Summary
aspire update currently tries to upgrade an application through deterministic CLI logic: discover an AppHost, traverse known project references, update SDK/package versions and manifests, then restore. We have accumulated enough evidence that this cannot reliably produce a coherent upgrade across real repositories.
We should make the project-update path agentic, following the model established by aspire init and the aspireify skill. aspire update --self is a separate, deterministic acquisition operation and is out of scope for this change.
Motivation
An Aspire repository upgrade is not just a package-version edit. It can require coordinated reasoning across:
- Multiple C# and TypeScript AppHosts, including AppHosts not connected through project references.
Aspire.AppHost.Sdk, aspire.config.json, package references, Central Package Management, repository tool manifests, and NuGet source/channel configuration.
- Centrally pinned transitive dependencies whose constraints change with the new Aspire version.
- Source changes required by obsoletions or breaking changes in Aspire and adjacent dependencies.
- Restore/build failures that only become visible after the initial edits and require iterative diagnosis.
During Aspire 13.6 dogfooding, updating dotnet/eShop#1039 left the repository with package downgrades and mixed SDK versions because not every AppHost was updated. Once the repository entered that state, normal NuGet tooling could no longer evaluate it, so the remaining migration had to be completed manually.
This is consistent with the pattern in existing issues:
The common problem is architectural: a fixed updater can handle known project shapes, but it cannot reliably understand and repair an arbitrary repository-wide dependency graph.
Proposal
Turn project updating into an official aspire-update skill and reduce aspire update to a thin launcher/bootstrapper, similar to aspire init:
- Resolve the requested Aspire target version/channel and make that information available to the skill.
- Ensure the official update skill is available in the detected agent environment and provide or initiate the appropriate invocation.
- Have the skill inspect the entire repository before editing: solutions, every AppHost, test projects, shared props/targets, CPM files, Aspire configuration, tool manifests, NuGet configuration, and relevant source.
- Present a coherent repository-wide upgrade plan rather than independently updating one selected AppHost.
- Apply version and source migrations together, then run restore and build validation.
- Diagnose and repair dependency conflicts, required source migrations, and obsoletion failures iteratively.
- Report success only when the repository validates. If it cannot complete the migration, leave an actionable diagnosis and clearly identify unresolved changes.
The skill should minimize unrelated edits, preserve intentional custom feeds and package constraints, and avoid silently overriding user-owned configuration.
Acceptance criteria
aspire update --self retains its current acquisition-focused behavior.
- The project-update workflow discovers and aligns all AppHosts in a repository, not only the selected AppHost and its project-reference closure.
- C#, TypeScript, multi-AppHost, CPM, custom-feed, and repository-tool scenarios are covered by an evaluation corpus.
- The workflow updates SDK/package/configuration state coherently and handles required source migrations.
- Restore/build failures prevent a success result and produce actionable diagnostics.
- Representative complex repositories, including eShop and Community Toolkit-style layouts, can be upgraded without manual dependency peeling.
- Documentation explains the required agent environment, confirmation model, non-interactive story, and fallback behavior when no supported agent is available.
Design questions
- Should the current deterministic updater remain temporarily behind a legacy option, or be deprecated immediately?
- What should
aspire update do when no supported agent environment is available?
- How should automation and non-interactive CI consume the skill while retaining reproducibility and approval controls?
- Should the update skill remain installed for future upgrades or behave as a one-time skill like
aspireify?
Summary
aspire updatecurrently tries to upgrade an application through deterministic CLI logic: discover an AppHost, traverse known project references, update SDK/package versions and manifests, then restore. We have accumulated enough evidence that this cannot reliably produce a coherent upgrade across real repositories.We should make the project-update path agentic, following the model established by
aspire initand theaspireifyskill.aspire update --selfis a separate, deterministic acquisition operation and is out of scope for this change.Motivation
An Aspire repository upgrade is not just a package-version edit. It can require coordinated reasoning across:
Aspire.AppHost.Sdk,aspire.config.json, package references, Central Package Management, repository tool manifests, and NuGet source/channel configuration.During Aspire 13.6 dogfooding, updating dotnet/eShop#1039 left the repository with package downgrades and mixed SDK versions because not every AppHost was updated. Once the repository entered that state, normal NuGet tooling could no longer evaluate it, so the remaining migration had to be completed manually.
This is consistent with the pattern in existing issues:
aspire updatedoesn't fully upgrade sdk #11458: only one AppHost/test project is upgraded, producing conflicting SDK versions.aspire updateso it can handle multi-apphost repos like Community Toolkit #11590: multi-AppHost repositories are left partially upgraded.aspire updateis limited when we don't update other dependencies when CPM is in use. #11655 and [CLI] [Regression]aspire updatesucceeds silently but leaves CPM projects broken with NU1109 package downgrade onaspire run#19537: CPM updates complete successfully but leave package-downgrade failures.The common problem is architectural: a fixed updater can handle known project shapes, but it cannot reliably understand and repair an arbitrary repository-wide dependency graph.
Proposal
Turn project updating into an official
aspire-updateskill and reduceaspire updateto a thin launcher/bootstrapper, similar toaspire init:The skill should minimize unrelated edits, preserve intentional custom feeds and package constraints, and avoid silently overriding user-owned configuration.
Acceptance criteria
aspire update --selfretains its current acquisition-focused behavior.Design questions
aspire updatedo when no supported agent environment is available?aspireify?