Spike: Skill-driven aspire init with unified agent skill#15918
Spike: Skill-driven aspire init with unified agent skill#15918maddymontaquila wants to merge 49 commits intomainfrom
Conversation
These are one-time skills that complete the Aspire initialization after `aspire init` drops the skeleton apphost and aspire.config.json. The agent runs the appropriate skill to scan the repo, wire up projects, configure dependencies, and validate that `aspire start` works. The skills self-remove on success. Co-authored-by: Copilot <[email protected]>
Add AspireInitTypeScript and AspireInitCSharp skill definitions to SkillDefinition.cs with embedded resource roots. Add resource strings, embed skill files in the csproj, and update the evergreen aspire skill to reference the new init skills. Co-authored-by: Copilot <[email protected]>
Strip InitCommand from ~980 lines to ~260 lines. Remove all solution manipulation, template installation, project reference wiring, and RPC scaffolding. New flow: prompt for language, detect .sln, drop bare apphost skeleton + aspire.config.json, install the appropriate init skill, then chain to agent init. Also add Sparkles (dizzy 💫) to KnownEmojis. Co-authored-by: Copilot <[email protected]>
Collapse aspire-init-typescript and aspire-init-csharp into one aspire-init skill. The unified skill handles both languages with conditional sections — the agent reads appHost.language from aspire.config.json to determine which path to follow. Co-authored-by: Copilot <[email protected]>
Add detailed docker-compose/compose.yml scanning guidance — extract services, images, ports, env vars, volumes, depends_on, and build contexts. Map known images to typed Aspire integrations. Move cert trust from a required step to a troubleshooting bullet under validation (aspire start handles it automatically). Co-authored-by: Copilot <[email protected]>
Cover WithReference vs WithEnvironment, endpoint/port patterns (env: for non-.NET), service discovery env var naming, WithExternalHttpEndpoints, dev.localhost domains, URL labels, WaitFor/WaitForCompletion, container lifetimes (persistent), explicit start, parent relationships, volumes, and aspire docs search/get workflow for looking up APIs and integrations. Co-authored-by: Copilot <[email protected]>
Establish the default stance: adapt the AppHost to the app, not vice versa. When a small code change unlocks better integration (WithReference vs WithEnvironment, dynamic ports, OTel endpoint), present the tradeoff with both options and let the user decide. Co-authored-by: Copilot <[email protected]>
Clarify this skill optimizes for local dev experience, not deployment. Recommend persistent container lifetimes, data volumes, dev.localhost URLs. Add guidance for extracting hardcoded external service URLs into AppHost parameters so they're visible and swappable from the dashboard. Co-authored-by: Copilot <[email protected]>
Scan for .env files during repo discovery. Classify each variable as secret (AddParameter with secret:true), plain config (WithEnvironment), or Aspire resource (replace with AddPostgres/AddRedis + WithReference). Goal: eliminate .env files so all config flows through the AppHost. Co-authored-by: Copilot <[email protected]>
Two pre-aspirified apps that serve as eval targets for the aspire-init skill: dotnet-traditional/ — .NET solution with slnx, Vue/Vite frontend, ASP.NET API + Blazor admin + EF Core migration runner, Postgres + Redis, .env with secrets and config. Exercises: full project mode, ServiceDefaults, env var migration, secret parameterization. polyglot/ — Python FastAPI + Go HTTP + C# minimal API + React frontend, Redis cache, external API keys in .env. Exercises: TS apphost single-file, multi-language scanning, OTel wiring, port injection, .env migration. Co-authored-by: Copilot <[email protected]>
Both READMEs now cover: architecture diagram, dependencies, config table (.env vars with secret classification), step-by-step multi-terminal setup, verification endpoints, pain points that Aspire should fix, and expected Aspire outcome after aspirification. Co-authored-by: Copilot <[email protected]>
Strip 'Pain points' and 'Expected Aspire outcome' from the app READMEs (agents would use them as answer keys). App READMEs now only describe the before-state. Eval rubric lives in EVAL-RUBRIC.md in the parent directory with detailed pass/fail checklists for both apps. Co-authored-by: Copilot <[email protected]>
- Add 'Always use latest Aspire APIs' principle: enforce aspire docs search before writing any builder call, never invent APIs - Massively expand OTel section: per-language setup for Node.js, Python, Go, and Java with concrete code samples; surface as user option - Add Step 8 'Dev experience enhancements': surface dev.localhost friendly URLs, dashboard URL labels, and OTel as opt-in suggestions - Renumber steps 9-11 to accommodate new step Co-authored-by: Copilot <[email protected]>
Introduce a 3-tier hierarchy for choosing how to model resources: 1. First-party Aspire.Hosting.* packages (always prefer) 2. CommunityToolkit.Aspire.Hosting.* packages (Go, Rust, etc.) 3. Raw AddExecutable/AddDockerfile/AddContainer (last resort) Update the 'verify before you write' principle with concrete package tables, discovery workflow (aspire list integrations, aspire docs search, aspire add), and examples for both first-party and toolkit. Update Step 4 non-.NET examples to show all 3 tiers with Go as the community toolkit example. Update 'Looking up APIs' reference section with aspire list integrations and toolkit add commands. Co-authored-by: Copilot <[email protected]>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15918Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15918" |
… sln detection - Replace all AddProject<T>/addProject references with AddCsharpApp/ addCsharpApp throughout skill examples (AddProject may be deprecated) - Remove fsproj scanning (not needed) - Make .env file deletion an explicit decision point: never auto-delete, always ask the user since teams may need them for non-Aspire workflows - Strengthen sln/slnx detection: explicitly note it forces full project mode for Visual Studio compatibility Co-authored-by: Copilot <[email protected]>
- Replace npx tsc && node pattern with 'aspire run' in package.json scripts, matching the canonical Aspire template pattern - Add package manager detection step: scan for pnpm-lock.yaml, yarn.lock, or package-lock.json and use the matching tool throughout - Replace hardcoded 'npm install' references with generic guidance that respects the repo's package manager Co-authored-by: Copilot <[email protected]>
IEvangelist
left a comment
There was a problem hiding this comment.
One concern is what does this mean for non-AI users? Can they no longer call aspire init if they don't have an AI to use here?
…clean up language - Rewrite dev.localhost to focus on cookie/session isolation (not friendly URLs) - Replace all AddNpmApp with AddViteApp/AddJavaScriptApp (API removed) - Update Aspire.Hosting.NodeJs → Aspire.Hosting.JavaScript - Add aspire describe/otel/logs to validation step for verifying wiring - Remove 'non-.NET services' phrasing throughout - Simplify OTel prompt language Co-authored-by: Copilot <[email protected]>
- Add 'Prefer HTTPS over HTTP' principle with full guidance - Update all code samples to use WithHttpsEndpoint by default - Add WithHttpsDeveloperCertificate for JS/Python apps throughout - Keep WithHttpEndpoint as documented fallback when HTTPS causes issues - Update dev.localhost examples to use 'https' endpoint names - Note experimental status (ASPIRECERTIFICATES001) Co-authored-by: Copilot <[email protected]>
right now init just drops the blank apphost so itll still do that. I think we get rid of the deterministic JS stuff we are doing since it's wreaking havoc lol |
Co-authored-by: David Pine <[email protected]>
GPT-5.4 review caught that the actual C# API is AddCSharpApp (not AddCsharpApp) and the TS equivalent is addCSharpApp. Fixed all 22 occurrences. Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
|
I was literally just thinking that this was the best approach to brownfield/aspireify an app. |
Co-authored-by: Copilot <[email protected]>
The language selection step (GetOrPromptForProjectAsync with saveSelection: true) writes aspire.config.json to disk before DropAspireConfig runs. This causes DropAspireConfig to find the file already present and skip writing the appHost.path field. Fix: merge into existing file instead of skipping, so the path field is always written regardless of prior file state. Co-authored-by: Copilot <[email protected]>
Key additions based on analyzing agent vs Damian's working excalidraw apphost: - JS resource type decision matrix (addNodeApp vs addJavaScriptApp vs addViteApp) with clear signals for when to use each - withRunScript/withBuildScript documentation with examples — critical for aspire publish to work with TypeScript servers - Monorepo/workspace detection guidance in Step 1 (path resolution, root scripts that delegate, workspace-aware installs) - Framework-specific port binding table (Express, Vite, Next.js, CRA) - BROWSER=none pattern to suppress auto-browser-open - Cross-service env var wiring examples (withEnvironment + endpoint ref) - Never call it '.NET Aspire' — just 'Aspire' - Dashboard URL must include auth token - Updated main TS AppHost example with all new patterns Co-authored-by: Copilot <[email protected]>
- Fix init skill flow: remove early skill install, let agent init prompt handle it naturally; print closing message to invoke agent - Write profiles section to aspire.config.json with random ports matching aspire new templates (both https and http profiles) - Add fallback defaults for ASPNETCORE_URLS, OTLP, and resource service in GuestAppHostProject when no profile provides them - Add all polyglot skeleton templates (Python, Go, Java, Rust) - Fix markdown linter errors (MD040, MD012) in eval READMEs - Isolate eval playground from repo CPM with Directory.Build.props/targets and Directory.Packages.props Co-authored-by: Copilot <[email protected]>
Run 'aspire start' right after scanning to catch config/profile issues early before investing time in project wiring. Renumber all subsequent steps accordingly. Co-authored-by: Copilot <[email protected]>
…UrlForEndpoint The correct way to enable dev.localhost subdomains is to update the applicationUrl in aspire.config.json profiles, not by calling withUrlForEndpoint in AppHost code. This matches how 'aspire new' handles it. Co-authored-by: Copilot <[email protected]>
The language selection step writes aspire.config.json first, so DropAspireConfig was saying 'Updated' even on fresh repos. From the user's perspective this is all one init flow — say 'Created'. Co-authored-by: Copilot <[email protected]>
Say 'AppHost created' instead of 'skeleton created', and print copy-pasteable commands for GitHub Copilot, Claude Code, and OpenCode to invoke the aspire-init skill. Co-authored-by: Copilot <[email protected]>
1ca9c05 to
cf4a676
Compare
After validation passes, the agent prints a summary with the full dashboard URL (including auth token) and resource health status from aspire describe. Co-authored-by: Copilot <[email protected]>
The agent should hand the user a fully running app with the dashboard open, not stop it during cleanup. Co-authored-by: Copilot <[email protected]>
- Add 'Never hardcode URLs' and 'Never use withUrlForEndpoint for dev.localhost' to Key Rules section - Add new 'Never hardcode URLs — use endpoint references' guiding principle with ✅/❌ code examples - Update Step 9 dev.localhost guidance with⚠️ callout and real-world aspire.config.json example (separate otlp/resources subdomains) - Clarify withUrlForEndpoint is ONLY for DisplayText, never for url.Url - Add 'NEVER DO THIS' anti-pattern to cross-service env var wiring - Remove http-only profile from dev.localhost example (match a3 pattern) Co-authored-by: Copilot <[email protected]>
Only print the aspire-init handoff when the user actually selects that one-time skill during agent init. Also switch the follow-up from the generic placeholder command to tool-specific commands based on the selected skill locations: - copilot -i for Copilot skill locations - claude with an initial prompt for Claude Code - opencode --prompt for OpenCode Thread the selected skill/location information back from AgentInitCommand so init can make the follow-up conditional. Adjust NewCommand for the updated return type and add tests for the new init messaging behavior. Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
- Add User Secrets migration guidance to SKILL.md - Add docker-compose profiles awareness to Step 1 scanning - Create references/docker-compose.md for rich compose migration - Rewrite references/full-solution-apphosts.md with large solution triage, incremental core-loop wiring, migration runner modeling, batch legacy pattern decisions, custom MSBuild SDK detection, conditional compilation awareness, and multi-source-root repos Co-authored-by: Copilot <[email protected]>
- Add 'Critical rules' section to SKILL.md with hard DO NOT rules for workload installation, SDK version changes, TFM changes - Add guidance to use aspire CLI commands over raw dotnet for Aspire ops - Strengthen nested global.json guidance in full-solution reference with explicit steps and check-before-create Co-authored-by: Copilot <[email protected]>
- Add config file table: aspire.config.json vs launchSettings.json vs appsettings.json — which mode uses which, do not confuse them - Full project mode uses Properties/launchSettings.json (standard .NET), not aspire.config.json - Tell agents: do not create/modify config files for service projects - Fix Step 2 smoke-test to reference correct config per mode - Update Step 4 ServiceDefaults: placement is agent's decision based on SDK boundary and repo structure, not hardcoded Co-authored-by: Copilot <[email protected]>
- Docker-compose ref: Make auto-generated passwords a loud callout with ❌/✅ examples. Agent must NOT create AddParameter for passwords that typed integrations manage (Postgres, SQL Server, Redis, etc.) - Full-solution ref: Rewrite ServiceDefaults decision tree — exactly two options: skip or modernize individually. Never create IHostBuilder adapter shims. Batch decision for N identical services. - SKILL.md: Add 'Check what integrations auto-manage' section with table of common auto-managed values and docs lookup commands Co-authored-by: Copilot <[email protected]>
InitCommand now invokes 'dotnet new aspire-apphost' via IDotNetCliRunner for full project mode instead of hand-crafting csproj/apphost.cs. The template generates correct launchSettings.json, proper SDK version pins, and a complete Program.cs — eliminating the config file confusion that caused ASPNETCORE_URLS crashes. - Replace DropCSharpProjectSkeletonAsync with template invocation - Inject IDotNetCliRunner into InitCommand - Update SKILL.md to reflect template-generated AppHost is correct - Update tests to verify template invocation instead of file contents Co-authored-by: Copilot <[email protected]>
Add step-by-step loop: validate core → add next batch → validate → repeat until all selected services are wired. Explicitly state the skill is not complete until everything the user selected is running. Co-authored-by: Copilot <[email protected]>
- Document WithoutHttpsCertificate() for plain Redis instead of AddContainer() fallback - Add rule to check/fix preview SDK versions in template-generated AppHost .csproj - Add guidance to search for existing OTel/Polly/health checks before creating ServiceDefaults Co-authored-by: Copilot <[email protected]>
- Reduce SKILL.md from 1,297 to 664 lines (-49%) - Fix docker-compose password contradiction (example now matches guidance) - Deduplicate rules repeated 3-5x: WithUrlForEndpoint, hardcoded URLs, API lookup, HTTPS guidance, dashboard token - Extract 3 new reference files for progressive disclosure: - apphost-wiring.md: API lookup tiers + wiring patterns (365 lines) - opentelemetry.md: per-language OTel setup recipes (112 lines) - javascript-apps.md: JS resource types + TS config (121 lines) - Trim over-explanations (motivational .env text, OTel intro, etc.) - All references remain one level deep from SKILL.md Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Once #15814 merges this would need to be updated to correctly resolve API docs.
| description: "One-time skill for completing Aspire initialization after `aspire init` has dropped the skeleton AppHost and aspire.config.json. This skill scans the repository, discovers projects, wires up the AppHost (TypeScript or C#), configures dependencies and OpenTelemetry, validates that `aspire start` works, and self-removes on success." | ||
| --- | ||
|
|
||
| # Aspire Init |
There was a problem hiding this comment.
Rather than this being an optional post aspire init, could we make it so that it would work either way? For example, what if I haven't called aspire init myself already - could this detect that and call it for me?
- Remove SemVersion code incorrectly spliced into InitCommand JSON block - Remove unused usings from main merge (Semver package was removed) - Restore GuestAppHostProject fallback defaults for dashboard URLs Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Description
Spike: Skill-driven
aspire init— refactors theaspire initcommand from a monolithic ~980-line implementation into a thin skeleton launcher that delegates the heavy lifting to an agent skill.What changed
New: Unified
aspire-initskill (.agents/skills/aspire-init/SKILL.md)aspire initdrops the skeleton AppHostappHost.languagefromaspire.config.json)Aspire.Hosting.*→ Community Toolkit → raw fallbacksaspire startModified:
InitCommand.cs— gutted from ~980 to ~260 lines. Now drops skeleton files and triggers the skill.Modified: CLI infrastructure —
SkillDefinition.cs,CommonAgentApplicators.cs,.csproj, resx/Designer.cs, xlf files updated for single unified skill.New: Eval playground apps (
playground/aspirify-eval/)dotnet-traditional/: .NET LOB app (slnx, Vue frontend, ASP.NET API + Blazor admin + EF Core migrations + Postgres + Redis)polyglot/: Polyglot microservices (Python FastAPI + Go HTTP + C# minimal API + React frontend + Redis)EVAL-RUBRIC.md: Scoring rubric for blind agent evals (kept outside app dirs)Eval results
Ran blind agent evals against both apps (agents get skill but NOT rubric):
Fixes #15911
Checklist