Walkthrough

Modernize .NET Demo

One /squad autopilot request — no per-step prompting — modernizes a real legacy app in place from .NET Framework 4.8 → .NET 10: dependency research, a pre-implementation council (architecture, security, RAI), a security Risk Gate, the SDK-style upgrade itself, and a review loop that finds real issues, remediates them, and re-reviews to zero findings before it says Go. The headline is the closed loop: the gate stopped, a human approved with conditions, the work shipped, review caught gaps, and the squad fixed them and proved it — all on one repo.

Open the demo repo on GitHub →

What you are proving

That a single autopilot line can take a legacy codebase and autonomously drive a complete, council-reviewed in-place framework upgrade — and, just as importantly, that the built-in Risk Gate and review loop keep a human in control and refuse to declare success until the findings are actually zero. Unlike the Migration Autopilot walkthrough, which stopped at the gate and escalated, this run shows the full closed loop: gate → conditional approval → implement → review → remediate → clean re-review → Go. The squad derived the whole Research → Council → Plan → Implement → Review pipeline itself.

CapabilitySquad member (role)Notes
Upgrade-path researchAlpha (researcher)Dependency & compatibility assessment; three blockers — non-SDK csproj, MSTest v1/GAC, dotnet CLI runbook.
Modernization planningBeta (lead), Epsilon (modernizer)Sequenced the SDK conversion, test-stack swap, and config cleanup with gate criteria.
Council (arch, security, RAI)Zeta, Eta, Theta (architect, security, rai)Go-With-Conditions; Security flagged High Risk and fired the Risk Gate.
In-place upgradeGamma (developer)SDK-style .csproj, net10.0, NuGet MSTest, dotnet CLI + global.json pinning.
Quality review + gateDelta (tester)The star of this demo — found workflow gaps, then re-reviewed the fixes to zero.

Before you start

This demo runs against a prepared repository, hve-squad-modernize-dotnet — the Legacy Inventory Manager, a small app that is intentionally legacy: a class library, a console front-end, and 20 MSTest unit tests, all starting on .NET Framework 4.8. The whole run edits the repo in place; there is no cloud and no spend, so it is safe to run live.

PrerequisiteWhyCheck
hve-squad installedThe modernization cast — researcher, lead, modernizer, developer, tester, architect, security, RAI — is dispatched by the coordinator.apm install "Peter-N91/hve-squad"
VS Code + Copilot (agent mode)The coordinator dispatches the cast as subagents.
The hve-squad-modernize-dotnet repoHolds the legacy .NET Framework 4.8 solution (Core, ConsoleApp, Tests).Open it as the workspace.
.NET 10 SDKNeeded for the in-place upgrade to build and run the modernized net10.0 projects.dotnet --version

In place, not a rewrite. The squad upgrades the existing solution — same domain models, same tests, same behavior — it does not scaffold a new app. That is the point: modernization you could hand to a maintainer, with every change owned by a named member and persisted as decisions and history under .copilot-tracking/squad/.

The one request

The entire demo is this single autopilot line. It names the outcome, not the steps — the squad sequences the pipeline itself:

/squad mode=autopilot request="Modernize this repository from .NET Framework 4.8 to .NET 10. Assess the current projects and dependencies, define the target state, and carry out the in-place upgrade end-to-end."

Narrate: "One line, no babysitting. Autopilot runs Research → Council → Plan → Implement → Review, stops only where risk demands a human, and won't claim success until the findings are zero."

Where it self-escalated first

Early on, the researcher (Alpha) reported it was missing the delegation tooling it needed and paused the pipeline rather than guessing. The human approved a roster override — the Squad Modernization Planner took over the research duties — and the run resumed. It is a small moment, but it is the safety story in miniature: the squad stops and asks instead of forcing a bad path.

What autopilot produced (Research → Council)

Research completed with a conditional Go, then a pre-implementation council assessed the upgrade from three angles before any code changed:

StageOwner(s)OutputStatus
1 · ResearchAlphaDependency & compatibility findings; blockers B1 non-SDK csproj, B2 MSTest v1/GAC, B3 framework-specific App.config, B4 VS-path-dependent build.✅ Go (conditional)
2 · CouncilZeta, Eta, ThetaArchitecture (test-platform discontinuity, build/config drift), Security (High Risk: missing SAST+SCA, undefined dependency-trust policy), RAI (non-material).✅ Go-With-Conditions
3 · Risk GateHumanSecurity High Risk fired the gate — approved with conditions in advisory strictness mode.✅ Approved
4 · ImplementGamma, EpsilonSDK-style conversion, NuGet MSTest, App.config cleanup, dotnet CLI workflows, global.json pinning.✅ Complete
5 · ReviewDeltaValidation + remediation loop.✅ Go (after remediation)
6 · ValidateFinal-outcome validation.⏸ Awaiting user (Promote-to-RC)

The Risk Gate — where it stopped for a human

The council verdict was unanimous Go-With-Conditions, but Security (Eta) rated the work High Risk and named two hard blockers, which fired the Risk Gate. Autopilot did not push past it — it paused and handed the decision to the human:

RoleVerdictKey conditions
Architecture (Zeta)Go-With-ConditionsDocument the test-platform migration; add a build-contract stability plan; make the config-modernization strategy explicit.
Security (Eta)Go-With-Conditions · High RiskAdd a SAST + SCA scanning workflow and a defined dependency-trust policy before modernized code merges.
RAI (Theta)Go-With-ConditionsNon-material scope; keep review/quality gates and audit traceability intact.

The human chose Approve-With-Conditions in advisory strictness mode: the pipeline resumes, the conditions ride along into the plan, and non-critical issues are logged and tracked rather than silently ignored. The squad never picks for you at a risk gate.

What the upgrade actually changed

With the gate cleared, the developer (Gamma) and modernizer (Epsilon) carried out the in-place upgrade — resolving every research blocker:

BlockerBeforeAfter
Project formatLegacy non-SDK .csproj, .NET Framework 4.8SDK-style .csproj targeting net10.0
Test stackMSTest v1 wired through the GACNuGet MSTest (Microsoft.NET.Test.Sdk, MSTest.TestFramework, MSTest.TestAdapter)
Build & testVisual Studio path-dependentdotnet CLI with SDK pinned in global.json
App configFramework-specific App.config metadataStale config removed
CI / securityNonedotnet-ci.yml + security-scanning.yml (SAST + SCA) added

Independent validation reported a clean dotnet restore, Debug and Release builds, and 20/20 tests passing — same tests, same behavior, new framework. The analyzer / nullability hardening (B5) was deferred by design and tracked as a follow-on, not silently dropped.

The review loop — where it proved the work

This is the payoff. The first review (Delta) passed the build but did not wave the work through — it found three real issues and sent the work back:

#FindingSeverityWhy it matters
1CodeQL job can drift to the runner's preinstalled SDKMediumSecurity scan wasn't pinned to global.json, so it could validate a different SDK than CI.
2CI triggers only on PR + manual dispatchMediumDirect pushes to main or merge-queue edges could bypass CI entirely.
3Empty App.config still includedLowHarmless at runtime, but ambiguous for maintainers.

The squad ran a remediation loop: pinned the CodeQL SDK via actions/setup-dotnet with global.json, added a push trigger for main, and removed the empty App.config include. The re-review came back 0 Critical · 0 High · 0 Medium · 0 Low with 20/20 tests still green — verdict Go.

This is the whole point of the demo. A model that just generated code would have handed over a green build and called it done. The squad reviewed its own work, named three concrete gaps with file and line, fixed them, and re-proved the result to zero findings before claiming success — with a human approving the risk gate along the way.

The decision point

With a clean Go verdict, the run halts at final-outcome validation and lets the human choose — it never promotes for you:

The whole run took 8 turns across 11 dispatches for roughly $0.72 (~72 AI credits), with two human interventions — the researcher override and the risk-gate approval — every decision persisted under .copilot-tracking/squad/.

Failure-safe fallbacks

If…Then…
A role reports missing toolingThat is the self-escalation story — the squad pauses and asks for a roster override rather than forcing a bad path. Show the decision log entry.
The .NET 10 SDK is not installedResearch, council, and planning still run; only the live build/test needs the SDK. Show global.json pinning instead.
Review comes back clean on the first passPoint at the review artifact anyway — the remediation loop is the differentiator; describe the findings it would have caught.
Someone asks "just upgrade it and ship"The squad still runs the Risk Gate and review loop — it never skips the gate or claims success past open findings.

Closing talking points