Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
e4ba87d
feat(cli): compile page code-behind safely
csharpfritz Apr 29, 2026
a27306b
feat(cli): port NuGet asset extraction and EDMX conversion to native C#
csharpfritz May 6, 2026
6c4fc72
chore: WingtipToys Run 32 benchmark output and sample improvements
csharpfritz May 6, 2026
750dab3
feat(cli): add ServerCodeBlockTransform and TemplateFieldChildCompone…
csharpfritz May 6, 2026
a148070
chore: Run 33 benchmark report and gap analysis
csharpfritz May 6, 2026
0f674ab
chore: WingtipToys migration Run 34 — 25/25 tests passing
csharpfritz May 6, 2026
a6fa245
Fix Run 34 shim and transform gaps
csharpfritz May 6, 2026
aa8f70c
Add Run 35 gap transforms
csharpfritz May 6, 2026
d35ff5c
Fix DisplayExpressionTransform to emit idiomatic @expr for simple exp…
csharpfritz May 7, 2026
a00373f
Fix Run 37 gaps: G1 display-expr, G2 ScriptManager strip, G4 compile-…
csharpfritz May 7, 2026
24c144a
Protect BWFC data control migrations
csharpfritz May 7, 2026
851c709
Fix FormView SSR first-render and SessionShim string round-trip
csharpfritz May 7, 2026
f4a9e9c
Add WingtipToys migration benchmark Run 39
csharpfritz May 7, 2026
79a324d
Add WingtipToys migration benchmark reports Run 35-38
csharpfritz May 7, 2026
0606280
Add regression tests for FormView SSR and SessionShim round-trip
csharpfritz May 7, 2026
b9689d1
Add runtime scaffold detection for benchmark migrations
csharpfritz May 7, 2026
a8ba153
Run Wingtip benchmark 40
csharpfritz May 7, 2026
19b0fe7
chore: log Run 40 benchmark results and merge decisions
csharpfritz May 7, 2026
1bdbb1f
Fix BWFC data control template emission for ListView, FormView, GridView
csharpfritz May 7, 2026
4e211ea
chore: log template emission fix session
csharpfritz May 7, 2026
76e4916
Add CartSessionKeyTransform for stable cart persistence
csharpfritz May 7, 2026
83eed88
Add compile-surface quarantine for non-migratable pages
csharpfritz May 7, 2026
f3a3946
WingtipToys migration benchmark Run 41
csharpfritz May 7, 2026
1db2b3f
Fix quarantine allowlist, static files, and antiforgery gaps from Run 41
csharpfritz May 7, 2026
9fac3fa
docs(ai-team): Scribe memory consolidation
csharpfritz May 7, 2026
3bfe62c
WingtipToys migration benchmark Run 42 — 25/25, 22:00, 96% first-pass
csharpfritz May 8, 2026
0558fa2
Update copilot-instructions.md with CLI, migration toolkit, and migra…
csharpfritz May 8, 2026
de2ab85
Add migration benchmark progression and sample complexity ordering
csharpfritz May 8, 2026
fb08940
docs(ai-team): Merge Bishop spawn decisions and logs
csharpfritz May 8, 2026
290cea4
Fix G3 auth redirect scaffold and G4 validator type inference
csharpfritz May 8, 2026
f64e1c3
Run 43: 25/25 acceptance tests — G3+G4 validated, runtime fixes
csharpfritz May 8, 2026
7e6823e
Fix G6 route aliasing and G7 quarantine bypass
csharpfritz May 8, 2026
78678c7
feat: add FormView DataItem parameter + Content SSR fallback + Run 44…
csharpfritz May 8, 2026
bdce418
docs(ai-team): Merge bishop TemplateField fix decisions; orchestratio…
csharpfritz May 8, 2026
22a17a9
feat: WingtipToys Run 45 — 25/25 acceptance tests, TemplateField pres…
csharpfritz May 8, 2026
66498f1
fix(ci): remove WingtipToys tests from CI integration tests
csharpfritz May 8, 2026
e827d26
ci: disable CodeQL on PRs/push, keep manual dispatch only
csharpfritz May 8, 2026
caef3c2
ci: disable Squad workflows, keep manual dispatch only
csharpfritz May 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
151 changes: 146 additions & 5 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Both should render:
## Technology Stack

- **.NET Version**: .NET 10.0 (see `global.json` for SDK version)
- **Framework**: Blazor (Server-Side and WebAssembly)
- **Framework**: Blazor (migration target is .NET 10 static SSR; samples also include Server-Side and WebAssembly)
- **Project Type**: Razor Class Library (`Microsoft.NET.Sdk.Razor`)
- **Testing Framework**: xUnit with bUnit for Blazor component testing
- **Assertion Library**: Shouldly
Expand All @@ -51,14 +51,32 @@ Both should render:

```
/docs -- User documentation (MkDocs)
/samples -- Usage samples
/samples -- Usage samples and migration benchmarks (ordered by complexity ↓)
BeforeWebForms/ -- Original Web Forms sample (.NET Framework)
AfterBlazorServerSide/ -- Blazor Server-Side samples
AfterBlazorClientSide/ -- Blazor WebAssembly samples
AfterBlazorServerSide/ -- Blazor Server-Side component samples
AfterBlazorServerSide.Tests/ -- Playwright tests for the sample app
AfterBlazorClientSide/ -- Blazor WebAssembly component samples
SharedSampleObjects/ -- Shared models/data for samples
WingtipToys/ -- ★ Current benchmark focus — e-commerce app (products, cart, checkout, identity)
AfterWingtipToys/ -- Migrated WingtipToys output (cleared + regenerated each benchmark run)
ContosoUniversity/ -- Next benchmark — university CRUD app (EF, master-detail, search)
AfterContosoUniversity/ -- Migrated Contoso University output
DepartmentPortal/ -- Most complex benchmark — multi-page portal (advanced data binding, nested controls)
AfterDepartmentPortal/ -- Migrated DepartmentPortal output
/src
BlazorWebFormsComponents/ -- Main component library
BlazorWebFormsComponents.Test/ -- Unit tests with bUnit
BlazorWebFormsComponents.Analyzers/ -- Roslyn analyzers
BlazorWebFormsComponents.Analyzers.Test/ -- Analyzer tests
BlazorWebFormsComponents.Cli/ -- Web Forms to Blazor CLI pipeline and scaffolding
BlazorAjaxToolkitComponents/ -- AJAX Toolkit component library
WingtipToys.AcceptanceTests/ -- WingtipToys Playwright acceptance suite
ContosoUniversity.AcceptanceTests/ -- ContosoUniversity Playwright acceptance suite
/tests
BlazorWebFormsComponents.Cli.Tests/ -- CLI transform and pipeline tests
/migration-toolkit -- Wrapper scripts, skills, methodology, and benchmark helpers
scripts/ -- bwfc-migrate.ps1, bwfc-scan.ps1, and compatibility wrappers
skills/ -- bwfc-migration, bwfc-identity-migration, bwfc-data-migration, migration-standards, l3-performance-optimization
```

## Component Architecture
Expand Down Expand Up @@ -288,6 +306,29 @@ When testing component properties or state, use `FindComponent<T>()`:
5. **No ViewState**: Store state in private fields or session (ViewState property exists but is syntax-only)
6. **PostBack Compatibility**: `WebFormsPageBase` provides `IsPostBack`, `PostBack` event, and `__doPostBack()` JS interop bridge

## Migration Rules

These are hard rules for migration work in this repository:

1. **Use the toolkit entry point**: Start project migrations with `migration-toolkit/scripts/bwfc-migrate.ps1` or the `webforms-to-blazor migrate` CLI it forwards to. Do not invent ad hoc regex converters or one-off migration scripts.
2. **Always target Blazor static SSR**: Generated apps target .NET 10 static server-side rendering. Do not switch the whole app to interactive Blazor Server; only opt into interactive render modes deliberately and per page.
3. **Trust the shims**: `WebFormsPageBase` preserves `Page.Request`, `Page.Response`, `Page.Session`, `Page.Server`, `Page.Cache`, `Page.ClientScript`, `IsPostBack`, and `ViewState`. Keep migrated code-behind compiling against those shims instead of rewriting to native ASP.NET Core services during Layer 1 or Layer 2 work.
4. **Preserve BWFC data controls**: Never replace `ListView`, `FormView`, `GridView`, `DataList`, or `Repeater` with manual HTML tables or divs. Fix the generated BWFC markup, templates, item types, or child components instead.
5. **Register transforms twice**: Every new CLI transform must be registered in both `src/BlazorWebFormsComponents.Cli/Program.cs` DI and `tests/BlazorWebFormsComponents.Cli.Tests/TestHelpers.cs` so the runtime pipeline and isolated test pipeline stay aligned.
6. **Respect quarantine boundaries**: `PageQuarantineDetector` should quarantine non-essential `Account/`, `Admin/`, `Checkout/`, mobile, payment, or compile-surface blocker pages, but benchmark-critical home, about, contact, product, catalog, and cart flows stay on the runnable path whenever possible.

### Migration Benchmark Progression

The `samples/` folder contains benchmark apps ordered by increasing complexity. Each app exercises more of the CLI and BWFC component surface:

| Sample | Complexity | Key Challenges | Status |
|--------|-----------|----------------|--------|
| **WingtipToys** | ★★☆ | E-commerce: products, cart, checkout, identity, EF data binding | **Current focus** — active benchmark runs |
| **ContosoUniversity** | ★★☆ | University CRUD: master-detail, search, EF migrations | Acceptance tests exist |
| **DepartmentPortal** | ★★★ | Multi-page portal: advanced data binding, nested controls, complex layouts | Future target — most sophisticated |

Always complete the current benchmark focus before moving to the next. Improvements to the CLI and toolkit should be validated against the current focus app first, then regression-tested against simpler samples.

## Migration Shims

The library provides compile-compatibility shims on `WebFormsPageBase` so migrated code-behind compiles unchanged:
Expand All @@ -314,6 +355,81 @@ When adding new components:
4. Add sample page in `/samples/AfterBlazorServerSide/Pages/ControlSamples/`
5. Document in `/docs/` folder (see Documentation Requirements below)

## Migration CLI & Toolkit

### Primary Entry Points

- `src/BlazorWebFormsComponents.Cli/Program.cs` defines the `webforms-to-blazor` CLI entry point and command surface (`migrate`, `convert`, `prescan`, `scan`, `assets extract`, `edmx convert`).
- `migration-toolkit/scripts/bwfc-migrate.ps1` is the supported migration-toolkit wrapper. It resolves the CLI project and forwards to `migrate` or `prescan` instead of maintaining a separate regex pipeline.
- The migration-toolkit skill set currently includes `bwfc-migration`, `bwfc-identity-migration`, `bwfc-data-migration`, `migration-standards`, and `l3-performance-optimization`.

### Pipeline Overview

`MigrationPipeline` orchestrates the full migration sequence:

1. `ProjectScaffolder` generates the .NET 10 Blazor static SSR scaffold unless `--skip-scaffold` is used.
2. `WebConfigTransformer` converts `Web.config` settings into `appsettings.json`.
3. Ordered markup transforms run first.
4. Ordered code-behind transforms run second.
5. `SemanticPatternCatalog` applies higher-level page rewrites.
6. `PageQuarantineDetector` performs a late compile-surface pass and writes `migration-artifacts/quarantine-manifest.json` when pages must be stubbed.
7. Static assets, source files, App_Start artifacts, NuGet assets, EDMX output, and redirect annotations are copied or generated.

The CLI currently has **24 core markup transforms plus directive/infrastructure markup passes** and **27 code-behind transforms** wired through `Program.cs`.

### Transform Registration Pattern

When adding a transform:

1. Create the transform class in `src/BlazorWebFormsComponents.Cli/Transforms/`.
2. Register it in `BuildServiceProvider()` in `src/BlazorWebFormsComponents.Cli/Program.cs`.
3. Add it to `CreateDefaultPipeline()` in `tests/BlazorWebFormsComponents.Cli.Tests/TestHelpers.cs`.
4. Add or update focused transform tests and pipeline coverage.

```csharp
// Program.cs
services.AddSingleton<IMarkupTransform, MyNewTransform>();

// TestHelpers.cs
var markupTransforms = new List<IMarkupTransform>
{
new MyNewTransform(),
};
```

### Scaffolding System

- `RuntimeDetector` aggregates runtime signal detectors for Entity Framework, session, identity, and `Global.asax` usage.
- `ProjectScaffolder` generates the project file, `_Imports.razor`, `Components/App.razor`, `Components/Routes.razor`, `Components/Layout/MainLayout.razor`, and launch settings.
- `ProgramCsEmitter` generates `Program.cs` for .NET 10 static SSR, including `AddRazorComponents()`, `AddBlazorWebFormsComponents()`, `UseStaticFiles()`, and `UseAntiforgery()`.
- `DatabaseProviderDetector` and `WebConfigTransformer` carry forward database provider and connection-string wiring.

### Quarantine System

- `PageQuarantineDetector` creates build-safe placeholder pages for compile-surface blockers and emits a manifest under `migration-artifacts/quarantine-manifest.json`.
- Essential benchmark pages (home, about, contact, product, catalog, shopping cart, add-to-cart flows) are exempt from incidental quarantine signals.
- Quarantined pages keep stub `.razor` and `.razor.cs` files plus the transformed original code-behind as an artifact for later Layer 2 or Layer 3 repair.

### Acceptance Test Suites

Use these suites as the migration quality gate for benchmark apps:

```bash
# WingtipToys migrated app
# Set WINGTIPTOYS_BASE_URL first if the app is not on https://localhost:5001

dotnet build src/WingtipToys.AcceptanceTests
pwsh src/WingtipToys.AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install chromium
dotnet test src/WingtipToys.AcceptanceTests

# ContosoUniversity benchmark/original app
# Set CONTOSO_BASE_URL first if the app is not on http://localhost:44380

dotnet build src/ContosoUniversity.AcceptanceTests
pwsh src/ContosoUniversity.AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install chromium
dotnet test src/ContosoUniversity.AcceptanceTests
```

## Documentation Requirements

**IMPORTANT**: All features, fixes, and new components MUST include documentation updates.
Expand Down Expand Up @@ -372,10 +488,33 @@ dotnet build
# Run tests
dotnet test

# Run CLI tests
dotnet test tests/BlazorWebFormsComponents.Cli.Tests

# Prescan a Web Forms app
dotnet run --project src/BlazorWebFormsComponents.Cli -- prescan -i samples/WingtipToys

# Run the migration CLI
dotnet run --project src/BlazorWebFormsComponents.Cli -- migrate -i samples/WingtipToys -o samples/AfterWingtipToys

# Run server-side samples
dotnet run --project samples/AfterBlazorServerSide
```

### Acceptance Test Commands

```bash
# WingtipToys migrated app (set WINGTIPTOYS_BASE_URL first if needed)
dotnet build src/WingtipToys.AcceptanceTests
pwsh src/WingtipToys.AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install chromium
dotnet test src/WingtipToys.AcceptanceTests

# ContosoUniversity benchmark/original app (set CONTOSO_BASE_URL first if needed)
dotnet build src/ContosoUniversity.AcceptanceTests
pwsh src/ContosoUniversity.AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install chromium
dotnet test src/ContosoUniversity.AcceptanceTests
```

## Key Interfaces

- `IStyle` - Styling properties (BackColor, ForeColor, CssClass, etc.)
Expand Down Expand Up @@ -544,7 +683,9 @@ When making changes, ensure all related files are updated:
| **Existing component modified** | Unit tests in `src/BlazorWebFormsComponents.Test/ComponentName/`, sample page if behavior changed, `docs/Category/ComponentName.md` if API changed |
| **New migration shim added** | Shim class in `src/BlazorWebFormsComponents/`, register in `ServiceCollectionExtensions.cs` via `AddBlazorWebFormsComponents()`, update `docs/Migration/` guide, update `copilot-instructions.md` Migration Shims section |
| **Base class changed** (`BaseWebFormsComponent`, `BaseStyledComponent`, `DataBoundComponent`) | Check all components inheriting from it — changes cascade to every component. Run full test suite. |
| **CLI transform added** | Transform in `src/BlazorWebFormsComponents.Cli/`, test in `tests/BlazorWebFormsComponents.Cli.Tests/`, update `docs/cli/transforms.md`, update `docs/cli/index.md` transform count |
| **CLI transform added** | Transform in `src/BlazorWebFormsComponents.Cli/Transforms/`, register it in `src/BlazorWebFormsComponents.Cli/Program.cs` and `tests/BlazorWebFormsComponents.Cli.Tests/TestHelpers.cs`, add or update transform tests, update `docs/cli/transforms.md`, update `docs/cli/index.md` transform count |
| **CLI scaffolding/runtime changed** | Files in `src/BlazorWebFormsComponents.Cli/Scaffolding/` or `Pipeline/`, matching tests in `tests/BlazorWebFormsComponents.Cli.Tests/`, `migration-toolkit/README.md` or methodology docs if operator workflow changes, and `.github/copilot-instructions.md` if migration guidance changes |
| **Migration toolkit wrapper or skill changed** | Matching files in `migration-toolkit/scripts/` or `migration-toolkit/skills/`, relevant `docs/Migration/` or `docs/cli/` pages, and `.github/copilot-instructions.md` when the recommended migration workflow changes |
| **Analyzer rule added** | Rule in `src/BlazorWebFormsComponents.Analyzers/`, test in `src/BlazorWebFormsComponents.Analyzers.Test/`, update `docs/Analyzers/` |
| **Target framework changed** | `Directory.Build.props` (version properties), all `.csproj` files (`TargetFrameworks`), `global.json`, `.github/workflows/build.yml` (dotnet-version), `.github/copilot-setup-steps.yml` |
| **Documentation added/changed** | `docs/` markdown file, `mkdocs.yml` (`nav:` entry if new), verify local build passes with `docker run --rm -v "$(pwd):/docs" mkdocs build --strict` |
Expand Down
1 change: 1 addition & 0 deletions .github/skills/wingtip-migration-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ Focus on:

- Keeping the generated project shape in `samples\AfterWingtipToys\`
- Preserving Web Forms semantics through BWFC shims where available
- **NEVER replace generated BWFC data controls (`ListView`, `FormView`, `GridView`, `DataList`, `Repeater`) with manual HTML. Fix the generated markup to work with the BWFC component instead.**
- Fixing build errors iteratively until the app runs cleanly enough for acceptance validation
- Treating the migration toolkit as the thing under test; manual fixes should be documented as toolkit gaps

Expand Down
29 changes: 0 additions & 29 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,6 @@
name: "CodeQL Security Scanning"

on:
push:
branches:
- 'main'
- 'dev'
- 'v*'
paths:
- 'src/**'
- 'samples/**'
- 'tests/**'
- '.github/workflows/codeql.yml'
- 'global.json'
- 'Directory.Build.props'
- 'nuget.config'
pull_request:
branches:
- 'main'
- 'dev'
- 'v*'
paths:
- 'src/**'
- 'samples/**'
- 'tests/**'
- '.github/workflows/codeql.yml'
- 'global.json'
- 'Directory.Build.props'
- 'nuget.config'
schedule:
# Run every Monday at 6:00 UTC
- cron: '0 6 * * 1'
workflow_dispatch:

jobs:
Expand Down
9 changes: 1 addition & 8 deletions .github/workflows/squad-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ name: Squad CI
# dotnet project — configure build/test commands below

on:
pull_request:
branches: [dev, preview, main, insider]
types: [opened, synchronize, reopened]
push:
branches: [dev, insider]

permissions:
contents: read
workflow_dispatch:

jobs:
test:
Expand Down
10 changes: 0 additions & 10 deletions .github/workflows/squad-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@ name: Squad Docs — Build & Deploy

on:
workflow_dispatch:
push:
branches: [preview]
paths:
- 'docs/**'
- '.github/workflows/squad-docs.yml'

permissions:
contents: read
pages: write
id-token: write

jobs:
build:
Expand Down
12 changes: 0 additions & 12 deletions .github/workflows/squad-heartbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,8 @@ name: Squad Heartbeat (Ralph)
# Run 'squad upgrade' to sync installed copies from source templates.

on:
# React to completed work or new squad work
issues:
types: [closed, labeled]
pull_request:
types: [closed]

# Manual trigger
workflow_dispatch:

permissions:
issues: write
contents: read
pull-requests: read

jobs:
heartbeat:
runs-on: ubuntu-latest
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/squad-insider-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ name: Squad Insider Release
# dotnet project — configure build, test, and insider release commands below

on:
push:
branches: [insider]

permissions:
contents: write
workflow_dispatch:

jobs:
release:
Expand Down
7 changes: 1 addition & 6 deletions .github/workflows/squad-issue-assign.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
name: Squad Issue Assign

on:
issues:
types: [labeled]

permissions:
issues: write
contents: read
workflow_dispatch:

jobs:
assign-work:
Expand Down
7 changes: 1 addition & 6 deletions .github/workflows/squad-label-enforce.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
name: Squad Label Enforce

on:
issues:
types: [labeled]

permissions:
issues: write
contents: read
workflow_dispatch:

jobs:
enforce:
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/squad-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ name: Squad Preview Validation
# dotnet project — configure build, test, and validation commands below

on:
push:
branches: [preview]

permissions:
contents: read
workflow_dispatch:

jobs:
validate:
Expand Down
10 changes: 0 additions & 10 deletions .github/workflows/squad-promote.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@ name: Squad Promote

on:
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run — show what would happen without pushing'
required: false
default: 'false'
type: choice
options: ['false', 'true']

permissions:
contents: write

jobs:
dev-to-preview:
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/squad-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ name: Squad Release
# dotnet project — configure build, test, and release commands below

on:
push:
branches: [main]

permissions:
contents: write
workflow_dispatch:

jobs:
release:
Expand Down
7 changes: 1 addition & 6 deletions .github/workflows/squad-triage.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
name: Squad Triage

on:
issues:
types: [labeled]

permissions:
issues: write
contents: read
workflow_dispatch:

jobs:
triage:
Expand Down
Loading
Loading