Sample output. The real primary deliverable is a schema-validated audit.json, committed to the project repo — every field is machine-checked before anything downstream trusts it. audit.md, shown below, is deterministically rendered from that JSON for human readability, and the cms-upgrade-estimate skill reads the JSON directly to produce the effort estimate. All company names, solution names, file paths, and figures here are fictional and anonymized.
CMS 12 → CMS 13 Upgrade Audit
Solution: Harborview.CMS (harborview-cms)
Audited by: AI (ESAI MCP — cms-upgrade-audit skill v1.11.0, optimizely-cms-12to13 module v1.8.27)
Cross-module: optimizely-graph (Find→Graph detected) · optimizely-opti-id (Opti ID path detected)
Executive Summary
This is a large, DXP-hosted Optimizely CMS 12 solution (95 content types, 68 NuGet packages, 9 scheduled jobs, Find integration in 12 files, Optimizely Identity active) requiring a three-path upgrade to CMS 13 (.NET 10.0): CMS 12→13, Find→Graph, and Opti ID completion. Complexity is large-tier, driven by:
- 11 tab names with spaces — the app cannot start on CMS 13 until these are fixed.
- ServiceLocator.Current across 28 files / 62+ occurrences — the highest-cost single item and a runtime-fragility risk.
- Find is deeply integrated — facets, best bets, visitor filtering, and a custom initialization module.
- Optimizely Identity (DXP) is active and requires Opti ID completion before the CMS 13 cutover.
- Three vendor packages have unconfirmed CMS 13 support.
Five items Require Human Input (RHI) and must be resolved before the upgrade can be fully scoped.
| Severity | Count | Meaning |
|---|---|---|
| P0 Fatal | 1 | Blocks startup on CMS 13 — must fix first. |
| P1 Build error | 8 | Prevents compilation — must fix to build. |
| P2 Behavioral | 5 | Compiles, but runtime behavior changes. |
| Migration paths | 3 | CMS 12→13, Find→Graph, Opti ID completion. |
A human decision is required before scope can be confirmed for: Find best-bets data migration; Find autocomplete/analytics (Graph has autocomplete, but on a different data source — no like-for-like migration); Opti ID role mapping / SSO scope; the unresolved vendor package set; and a startup-ordering risk after Find removal.
Breaking Changes Detected (excerpt)
| Severity | Issue | Fix |
|---|---|---|
| P0 | Tab names with spaces — FATAL startup crash | Rename to PascalCase; add [Display(Name = "...")] to preserve the UI label. |
| P1 | ContentArea.FilteredItems obsoleted-as-error | Prefer HTML/Tag Helper rendering (filters applied automatically); .Items is unfiltered, so apply rendering filters explicitly where items are enumerated in C#. |
| P2 | SiteDefinition.Current static access deprecated | Replace with injected IApplicationResolver. |
| P3 | EPiServer.Logging.ILogger no longer DI-registered (type still compiles) | Tech debt in project code: migrate to Microsoft.Extensions.Logging.ILogger. |
Find → Graph Coverage & Hole Map
Every detected Find call site is classified into one of four migration classes, so gaps are resolved at scoping rather than discovered mid-execution. This is a read-only forecast.
| Class | Count | % | Meaning |
|---|---|---|---|
| direct-swap | 22 | 38% | 1:1 mechanical replacement. |
| pattern-rewrite | 26 | 45% | Query shape changes — automatable with review. |
| manual-rhi | 6 | 10% | A human decision is needed. |
| no-equivalent | 4 | 7% | No Graph capability exists. |
Recommended Execution Order
Resolve RHI items first
Confirm vendor CMS 13 support and get stakeholder decisions on the Find autocomplete/analytics replacement and Opti ID scope.
Phase 0 — Pre-Startup Blockers
Fix the 11 tab names. Must be done before the app can start on CMS 13.
Phase 1–4 — Packages, Framework, API fixes, Behavioral changes
Work through the full breaking-change list in dependency order.
Phase 5 — Runtime Verification
Start the application, validate content save/publish, re-index content URLs, verify CMS UI login.
Opti ID and Graph (separate workstreams)
Run after the CMS platform upgrade compiles — never in parallel.