Forge
markdowndeeb25a2
1<!-- English translation of adr/0090-launch-profiles-and-debug-startup-configurations.md. Canonical Russian: ../../adr/0090-launch-profiles-and-debug-startup-configurations.md -->
2
3# ADR 0090: Launch profiles and multiple debug startup configurations (VS-style)
4
5**Status:** Accepted · Implemented
6**Date:** 2026-04-23
7
8## Related ADRs
9
10| ADR | Role |
11|-----|------|
12| [0002](0002-debug-human-agent-parity.md) | unified debug layer for human and agent |
13| [0028](0028-user-settings-toml-localappdata-and-secrets.md) | user settings — `settings.toml`, `%LocalAppData%\CascadeIDE\`, secrets separate |
14| [0029](0029-configuration-toml-canonical-ui-facade.md) | TOML-first config; holistic settings UI **deferred**; point UI is **canon facade** |
15| [0093](0093-mfd-embedded-browser-for-launch-url.md) | embedded launch URL on MFD (extends profiles and launchBrowser) |
16
17### Outside ADR
18
19| Document | Role |
20|----------|------|
21| [MCP-PROTOCOL.md](../../MCP-PROTOCOL.md) | `debug_launch` and related tools |
22| [MsBuildDebugTargetResolver.cs](../../../Services/MsBuildDebugTargetResolver.cs) | MSBuild debug target resolver |
23
24## Summary
25
26- **Launch profiles** and multiple debug startup configurations (as in VS).
27- Storage, MCP, migration from `startup-project.json`.
28- Optional URL on MFD — [0093](0093-mfd-embedded-browser-for-launch-url.md).
29
30---
31
32## Context
33
34Today **one solution** has **at most one** explicit startup project: path to `.csproj` in `.cascade-ide/startup-project.json` as single `StartupProjectRelativePath`. F5 and interactive `debug_launch` resolve **one** target; MSBuild configuration for debug is effectively **Debug** in the resolver.
35
36In Visual Studio and SDK projects the familiar model is **several named profiles** — different projects, configurations (Debug/Release/…), command-line args, working directory, environment variables. Developer switches “current profile” and presses F5 without resetting startup project each time.
37
38Without this Cascade IDE stays closer to “one start per solution”, weak for monorepos, multiple executables in one `.sln`, and “run API / console / test host” without a file dialog.
39
40**Web (ASP.NET Core)** is not “later”: typical portal/SPA-host solutions (including product **EDW.Portal**, scope `portal` in operational memory) depend on `Properties/launchSettings.json`: Kestrel **URLs**, `ASPNETCORE_ENVIRONMENT`, sometimes `launchBrowser`, profiles (`http` / `https` / IIS). Without mapping these fields into DAP launch (process env + host args if needed) F5 in CIDE **will not** match familiar `dotnet run` / VS. Console exe is a subset; **web is mandatory** v1 horizon per this ADR.
41
42<a id="adr0090-decision"></a>
43
44## Decision (direction)
45
46Introduce a **launch profile catalog** in the workspace zone, with **currently selected profile**, and run debug (DAP launch) **through the active profile**, not sole `StartupProjectRelativePath`.
47
48<a id="adr0090-profile-model-v1"></a>
49
50### Minimal profile model (v1)
51
52Per profile, at minimum:
53
54- **Id** — stable name within solution (display name may match or localize separately).
55- **Project** — path to `.csproj` / `.fsproj` **relative to solution root** (same base as `BreakpointsFileService.GetWorkspaceRoot(solutionPath)`).
56- **MSBuild configuration** — e.g. `Debug` / `Release` (string; default `Debug` for debug).
57- **Program arguments** — optional, string list or quoted string rules (refine at implementation).
58- **Working directory** — optional; if empty — inherit from [IdeDapDebugSession](../../../Services/IdeDapDebugSession.cs) (`ResolveLaunchWorkingDirectory` logic exists).
59
60- **Process environment variables** — for web at minimum merge what profile supplies (often `ASPNETCORE_ENVIRONMENT=Development`). Implementation: env in DAP `launch` (extend [IdeDapDebugSession](../../../Services/IdeDapDebugSession.cs) if missing), no silent drop.
61
62<a id="adr0090-aspnet-v1"></a>
63
64### ASP.NET Core / web (v1, not deferred)
65
66Profile must express what is already in `launchSettings.json` for `commandName: Project` (Kestrel):
67
68- **`applicationUrl`** — one or several bindings (`;` as in SDK template or URL array in TOML); on launch set in environment as `dotnet` does (typically `ASPNETCORE_URLS` or host-aligned — refine with `dotnet`/hosts).
69- **`launchBrowser`** — optional; if `true`, open URL after start (CIDE wrapper if added; else mark deferred/v2 explicitly).
70- Separate profiles like `http` / `https` — multiple named entries in TOML, 1:1 import from `launchSettings.profiles` where possible.
71
72**IIS Express** (`commandName: IISExpress`) and full VS IIS parity — **may** be separate phase; ADR minimum: Kestrel + `Project` — web v1 baseline; IIS — best effort or separate ticket after baseline.
73
74**Import:** reading web project `Properties/launchSettings.json`, TOML in `.cascade-ide` must **preserve URL and env semantics** so portal-style scenarios do not break vs `dotnet run --launch-profile …`.
75
76<a id="adr0090-storage"></a>
77
78### Storage
79
80- **Canonical format: TOML**, not JSON — e.g. `.cascade-ide/launch-profiles.toml` (plus schema version key, e.g. `version = 1`). Same philosophy as user/canonical IDE config ([0028](0028-user-settings-toml-localappdata-and-secrets.md), [0029](0029-configuration-toml-canonical-ui-facade.md)): readability, comments, one style with `settings` / `workspace` beside repo.
81- **One file** per open solution (path to `.sln` / standalone `.csproj` — as for breakpoints and startup): **profile list** and **active** profile (`active_profile` or equivalent), no second file to desync.
82- **JSON** (`Properties/launchSettings.json`) remains external de-facto SDK/VS standard — **not** duplicated as primary canon in `.cascade-ide`; **import/export** into TOML model.
83
84**Migration:** if only `startup-project.json` exists, on first read build **one** default profile (name like `Default` / from project name), set active, write `launch-profiles.toml`, keep old JSON for strangler until explicit removal.
85
86<a id="adr0090-ui"></a>
87
88### UI
89
90- Visible **current profile selector** (toolbar or explorer strip / debug banner) — **keyboard-first** per [0013](0013-command-surface-and-discoverability.md).
91- Commands: manage profiles (add/delete/duplicate) — MFD or modal by volume ([0074](0074-settings-ui-mfd-compact-layout-overflow.md) overflow policy).
92- F5 / “start debugging” uses **active profile** without `.dll` dialog when resolve succeeds ([0002](0002-debug-human-agent-parity.md) parity).
93
94<a id="adr0090-mcp-parity"></a>
95
96### Agent parity (MCP / IdeCommands) — v1 contract
97
98Debug launch contract at `IdeCommands.DebugLaunch` and `MCP-PROTOCOL`:
99
100- Command: `debug_launch`.
101- Mode A (explicit target): `workspace_path` + `target_path` (as today, backward compatible).
102- Mode B (profile): `profile_name` (optional) + open workspace/solution context.
103 - if `profile_name` omitted, use `active_profile`;
104 - if profile not found — explicit contract error (no silent random startup fallback).
105- Additional: `netcoredbg_path`, `program_args`.
106- If both `target_path` and `profile_name` — **`target_path` wins** (explicit agent path stronger than profile).
107
108Human and agent share F5/Launch meaning: “launch by active profile”; direct `target_path` kept for point scenarios.
109
110<a id="adr0090-dotnet-alignment"></a>
111
112### .NET alignment
113
114- **Optional import** from `Properties/launchSettings.json` (after v1) — less friction for `dotnet`/VS projects. Canon remains **TOML in `.cascade-ide`**; **semantic compatibility** with standard `launchSettings`, not bitwise file identity.
115- Optional **export** to `launchSettings`-like form for other tools — not mandatory.
116
117<a id="adr0090-build-resolve"></a>
118
119### Build resolve
120
121- [MsBuildDebugTargetResolver](../../../Services/MsBuildDebugTargetResolver.cs): pass **configuration** from profile (`-p:Configuration=...`), not only constant `Debug`, when active profile is source of truth.
122
123<a id="adr0090-consequences"></a>
124
125## Consequences
126
127- Refactor `MainWindowViewModel` / `StartupProjectStore` toward **“set + active”** model; old APIs — strangler.
128- Tests: TOML parse, migration from single `startup-project.json`, import **web** `launchSettings`, F5 scenarios: console + **Kestrel** with valid URL.
129- User Guide — product layer, not mandatory ADR volume (see [README](README.md)).
130
131<a id="adr0090-rejected"></a>
132
133## Rejected / deferred alternatives
134
135- **Only** read `launchSettings.json` without own file — rejected: worse for IDE MVP parity (monorepos, paths relative to solution, stable agent contract in `.cascade-ide` beside breakpoints).
136- **Multiple parallel debug sessions** in one IDE — out of scope (one DAP session unless separately fixed).
137
138<a id="adr0090-implementation-status"></a>
139
140## Rollout status
141
142- Storage canon: `.cascade-ide/launch-profiles.toml`, migration from `startup-project.json`, `MsBuildDebugTargetResolver` with profile configuration, DAP `launch` with `env` and optional cwd, `debug_launch` with `profile_name` and explicit contract errors; tests `LaunchProfilesStoreTests`, docs `IdeCommands` / `MCP-PROTOCOL.md`.
143
144<a id="adr0090-implementation-checklist"></a>
145
146## Implementation checklist (decision → code)
147
1481. Introduce `.cascade-ide/launch-profiles.toml` (profiles + `active_profile`) and migration from `startup-project.json`.
1492. Update debug resolve: `MsBuildDebugTargetResolver` gets `Configuration` from profile.
1503. Update `debug_launch` pipeline: `profile_name`, clear errors (`profile_not_found`, `active_profile_missing`, `profile_target_unresolved`), compatibility with `workspace_path + target_path`.
1514. Sync docs: XML-doc `IdeCommands.DebugLaunch`, `docs/MCP-PROTOCOL.md`, ADR index links if needed.
1525. Test plan: console profiles Debug/Release with different args; ASP.NET Core import `applicationUrl`/env and launch by profile; negative: missing profile and unresolvable target give explicit errors.
153
View only · write via MCP/CIDE