| name | migrate-plan |
| description | Creates a structured KX13-to-XbyK migration plan with overview and detail documents. Use when planning, configuring, or preparing a Kentico Xperience 13 to Xperience by Kentico content migration, or when the user mentions migration plan, migration configuration, or upgrade from KX13. |
| compatibility | Optionally uses a Kentico documentation lookup tool for XbyK content model verification. |
| argument-hint | [source-content-model-path] [target-content-model-path?] |
Migration Plan Creation
Produces two documents: a Migration Overview (concise, human-readable) and a Migration Detail (comprehensive, AI-consumable). Takes structured content model descriptions or free-text descriptions as input.
Workflow
Step 1: Read Reference Materials
- Read migration-tool.md for migration tool capabilities, supported data, extension points, and configuration options.
- If you need documentation links, read migration-docs.md.
- If a Kentico documentation lookup tool is available, use it for additional context on XbyK content types, reusable field schemas, Content hub, or Page Builder.
Step 2: Understand the Source Content Model
If a file path was provided, read the source content model files. If a direct description was provided, analyze it to identify:
- Page types and their fields (note any inheritance, macros in defaults, or field categories — these are NOT supported by the migration tool). Document the class inheritance hierarchy (
ClassInheritsFromClassID relationships) — this is critical for determining which classes can safely be excluded. Parent classes must not be excluded even if they have 0 instances, or all child classes will fail during --page-types. Collect ClassID (numeric) for every page type — ICmsTree.NodeClassID is an int, and ContentItemDirectorBase filters like LinkChildren use .Where(c => c.NodeClassID == <int>), not class code names. The numeric ClassID must be available in the plan for anyone writing director or extension code.
- Custom tables and module classes
- Page Builder widgets in use (distinguish built-in vs custom)
- Page relationships (linked pages, child pages) — see the "Linked Pages in KX13" section in migration-tool.md for how to identify linked pages (
NodeLinkedNodeID IS NOT NULL), their characteristics (shared content, separate tree node, no own data), and common KX13 patterns (taxonomy, reused-content folders)
docrelationships field data (CMS_Relationship table) — when the source audit includes a "Page Relationships (CMS_Relationship)" section, use it to understand which docrelationships fields have actual relationship data, which pages they connect, and what the target page types are. Each ad-hoc relationship name contains the field GUID (ClassName_FieldGUID), making it possible to map relationship rows back to specific page type fields. This data is critical for planning ConvertFrom transforms that resolve docrelationships NodeIDs to target values (taxonomy tags, content item references, webpage references). Include the full relationship data in the detail document's Source Content Model section.
- Parent-child hierarchies where children could become content item references — identify page types that are direct children of another page type and are candidates for Content Hub conversion (e.g.,
Company children under a ContactPage, product children under a store section). These can be linked as references via LinkChildren in ContentItemDirectorBase.Direct(). Also identify intermediate non-content nodes (e.g., CMS.Folder) that may sit between the target parent and the child pages, as these affect the director implementation.
- Media handling (attachments, media libraries, text fields with Media selection form control — text fields can be converted to content item assets via
OptInFeatures.CustomMigration.FieldMigrations configuration; file/attachment fields automatically migrate as Legacy.Attachment content items with working asset references)
Ask clarifying questions if critical information is missing (page types, page relationships, widgets).
Step 3: Resolve Migration Approach Decisions
Read migration-approach-categories.md for the full list of migration approach categories (A through J).
If a target content model was provided, analyze it, then compare it against the source model to identify structural divergences — places where the target departs from a straightforward 1:1 migration. Use the "When to ask — target model provided" triggers in each category.
If no target content model was provided, walk through the source model and use the "When to ask — no target model" triggers to identify which categories apply. The default option in each category is a straightforward migration; only ask about categories where the source model has characteristics that make the non-default option worth considering.
For each applicable category, ask the user which option they prefer before generating the plan. Present the options concisely with clear trade-off summaries. If there are 3+ decisions, present all of them and collect all answers at once. After collecting answers, proceed to generate the plan using the chosen approaches and record which option was selected.
Step 4: Create the Migration Overview
Read MIGRATION_OVERVIEW_TEMPLATE.md and produce the overview document covering:
Manual Steps — Pre-migration setup (items to create before migration), post-migration tasks (creating wrapper pages, populating references, optionally curating Legacy.Attachment items into custom asset types), target-only entities (content types and taxonomies with no source equivalent that must be created manually), and unsupported features with recommended XbyK alternatives. Note: ToolApiController deployment for Source Instance API Discovery is NOT a manual step — the appsettings skill handles it automatically during configuration generation (see migrate-appsettings Step 1c). Do not list it as a pre-migration manual step. When a pre-migration step involves creating a taxonomy whose tag GUIDs are needed by field transforms, the step description must tell the user to fill in the tag GUIDs in the detail document's lookup table and include a markdown link to the relevant Custom Value Transforms subsection in the detail document (e.g., [fill in the tag GUIDs](migration-detail.md#doctoremergencyshift--doctorprofiledoctorprofileemergencyshift)). Before listing any step as "manual", critically evaluate whether the migration tool can handle it via configuration or code extensions — only list it as manual if there is genuinely no migration tool mechanism. Do not list project setup (creating the XbyK project), source instance prerequisites, or other assumed setup steps. Reusable field schemas created by ReusableSchemaBuilder in IClassMapping are automatic — never list them as manual.
Content Model Mapping Overview — High-level tables showing Content Hub conversions, webpage mappings, merge/split scenarios, exclusions, taxonomy planning (migrated from KX13 categories vs. new), and reusable field schemas. No appsettings.json fragments or code — just class names and brief summaries. Content types that exist only in the target model (no source equivalent) must be listed in the "Target-Only Entities" section with pre/post-migration timing. Taxonomies not migrated from KX13 categories must be marked as "Manual (pre-migration)" if needed by field transforms during migration (i.e., a ConvertFrom or IFieldMigration references tag GUIDs at migration time), or "Manual (post-migration)" if only referenced by target-only content types that are created after migration or used solely for editorial classification.
Field Mapping Overview — Key transformations summarized by source class with complexity notes in the transformation summary text (no dedicated effort column). Attachment field migration paths. No ConvertFrom details or lookup dictionaries.
Widget Transformation Overview — Built-in widgets (auto-migrate), custom widget mappings, section mappings. Brief summaries with complexity notes in summary text (no dedicated effort column), no property-level detail.
Page Relationship Overview — Strategies (materialize, store_reference, etc.) described in plain language.
Execution Summary — A table of all migrate CLI parameters with a Status column. Set Status to Required for parameters actively needed by this migration run; leave as — for parameters that are available but not required. Default to including all applicable CLI steps (--sites, --custom-modules, --users, --page-types, --pages, --categories, --media-libraries, --forms) — it is safer to run a step that finds no data than to omit one that silently skips content. Each parameter is displayed as inline code (e.g., `--sites`). An optional Notes column can add brief context (dependencies, what data the step covers). Do not use checkbox syntax (- [x] / - [ ]) as it does not render in standard markdown previewers. Do NOT include a code extensions summary table here — code extensions are already listed in the dedicated "Code Extensions Summary" section earlier in the document.
Operational Notes — Iterative migration guidance (upsert behavior, --bypass-dependency-check for repeated runs), bulk deletion requirements (data types that require manual cleanup before re-runs: contacts/activities, consent agreements, form submissions, custom module class data), and logging/troubleshooting guidance (console output, log file location at logs/log.txt — relative to the CLI project directory and configured by Logging.pathFormat in appsettings.json).
Step 5: Create the Migration Detail
Read MIGRATION_DETAIL_TEMPLATE.md and produce the detail document covering:
Source Content Model — Full page type field tables with ClassID (numeric ID from CMS_Class) included in each page type's heading or summary row, class inheritance hierarchy (when any page type has ClassInheritsFromClassID), custom tables, module classes, Page Builder component inventories.
Target Content Model — Full content type definitions with Created By indicators (Migration tool vs Manual), reusable field schemas with field lists, taxonomy definitions with tag values and creation method. The migration tool only creates content types from source data (via IClassMapping during --page-types) and taxonomies from KX13 categories (via --categories). Types with no source equivalent must be marked "Manual" with pre/post-migration timing. Reusable field schemas created by ReusableSchemaBuilder in an IClassMapping are automatic and must not be listed as manual.
Content Model Mapping — ConvertClassesToContentHub lists with appsettings.json fragments, IClassMapping registrations, merge/split field mapping tables, exclusion configuration with EntityConfigurations JSON, and taxonomy planning (migrated KX13 categories vs. new taxonomies with creation method).
Field Mappings — Complete field change tables (source → target with rename, data type change, form component change). Use the Field Type and Form Control Mapping table in migration-tool.md for default data type → form component mappings. For every field with a data type or form control change, explicitly assign a mechanism — see the "Field definition changes" gotcha below. Include a Custom Form Control Fields subsection listing any source form controls not covered by the built-in mapping table (e.g., countrySelector, emailinput, URLSelector). For each, state the source data type + form control, the target data type + form component, and the handling mechanism: built-in catch-all, appsettings.json FieldMigrations config, IFieldMigration code, or IClassMapping.WithFieldPatch. Include SEO metadata mapping, file/attachment migration paths (including OptInFeatures.CustomMigration.FieldMigrations configuration for text fields with Media selection form control), and custom value transforms with detailed transformation logic (ConvertFrom targets, lookup dictionaries, edge cases). In lookup dictionary tables where XbyK tag GUIDs are not yet known (assigned when the taxonomy is created pre-migration), use TODO as the placeholder value (e.g., TODO in the "XbyK Tag GUID" column) so these are easy to find and fill in later.
Page Relationship Handling — Linked page strategies with ContentItemDirectorBase configuration, linked page audit (every linked page with explicit strategy), child-as-reference mappings with ancestor level calculations, pages-as-widgets configuration.
Widget Transformations — Source Instance API Discovery config, section type mappings with property transforms, custom widget mappings with full property-level detail, IWidgetPropertyMigration transforms with examples.
Execution Plan — Complete appsettings.json configuration (including TargetWorkspaceName and AssetRootFolders when applicable) and full code extensions table (every IClassMapping, ContentItemDirectorBase, IWidgetMigration, IWidgetPropertyMigration, IFieldMigration with descriptions). For code extensions, reference ModelFacade for source data querying and IImporter with UMT models (ContentItemModel, DataClassModel, ContentItemLanguageMetadataModel, WebPageItemModel) for target writes where relevant. Do NOT include a "Migration Command" section — the migration command checklist belongs exclusively in the overview document.
Validate plan completeness before presenting:
- Every target content type has a creation path (migration tool via
IClassMapping, manual pre-migration, or manual post-migration)
- Every source page type/class has a disposition (mapped, converted to Content Hub, merged, excluded, or default migration)
- No class in the Exclusions
ExcludeCodeNames list is a parent class (ClassInheritsFromClassID) of any class being migrated — parent classes with 0 instances must NOT be excluded
- All linked pages in the KX13 page tree are audited with explicit strategies
- Error/utility pages (404, maintenance, redirects) are explicitly handled — either excluded or mapped
Validate plan internal consistency before presenting:
- Code extension counts: The count for each extension type in the overview's "Code Extensions Summary" table must exactly match the number of rows of that type in the detail's "Code Extensions to Implement" table. If a widget transformation section describes
IWidgetMigration code for a widget, there must be a corresponding row in the code extensions table.
- Widget strategy consistency: Each custom widget must tell exactly one story across: (1) the widget transformation section (overview + detail), (2) the code extensions summary/table, (3) the "Unsupported features" section, and (4) manual steps. A widget cannot simultaneously be described as "automated via
IWidgetMigration" in the widget section and "unsupported / post-migration only" in the unsupported features section. If a widget's structural migration is automated but its underlying KX13 feature has no XbyK equivalent (e.g., newsletter subscription engine), the unsupported features entry must clearly scope what is unsupported (the feature/engine) vs. what is automated (the widget structure/property migration).
- Child-as-reference vs. post-migration manual: Before marking any "populate content item references" as a post-migration manual step, verify whether
LinkChildren (in ContentItemDirectorBase.Direct()) can handle it automatically during --pages. Direct parent-child relationships where both types are converted to Content Hub should use LinkChildren. Only mark as post-migration manual when: (a) the reference connects content types that are not in a parent-child tree relationship, (b) the reference field connects types where the child is not a direct child (grandchildren through folders may require LinkChildren on the intermediate node), or (c) the reference field was invented for the target model with no source hierarchy equivalent.
- Manual step scope: When a director fills reference fields at migration time, the corresponding manual step (if any) should be scoped to "verify and fix references" rather than "populate all references manually". Do not list a manual step for work that the migration tool handles automatically.
- Field definition change coverage: Every field in the Field Changes tables that has a data type change or form control change must have a clear handling mechanism. Cross-reference against the built-in Field Type and Form Control Mapping table in migration-tool.md. If a source data type + form control combination appears in the built-in table, no action is needed. If it does not appear (custom or uncommon form control), one of these mechanisms must be assigned: (1) built-in catch-all (e.g.,
text + _other_ → TextInput), (2) appsettings.json FieldMigrations config (simple swap, no value change), (3) IFieldMigration code (custom value transform or definition change not in built-in table), or (4) IClassMapping.WithFieldPatch (definition change scoped to one class, combined with ConvertFrom for value transform if needed). If IFieldMigration code is required, there must be a corresponding row in the Code Extensions table. If config is used, it must appear in the appsettings.json fragment.
Step 6: Present and Refine
- Save both files (defaults:
./migration-overview.md and ./migration-detail.md, or user-specified locations).
- Ask if any sections need adjustment.
- Iterate on feedback.
Rules
- Focus on content: The migration plan covers content types, reusable field schemas, fields, and Page Builder migration. Do not include configuration for commerce (customers, orders), online marketing (contact groups, marketing automation, email marketing, personas), user/member migration, or other non-content features. The knowledge base (migration-tool.md) documents these capabilities for awareness, but the plan output should not produce sections for them.
- Be practical: Omit sections that are not relevant. Not all sections apply to every migration.
- Map to implementation: Every item should indicate whether it requires an
appsettings.json change, a code extension, or a manual step.
- Use correct terminology: KX13 terms for source (page types, custom tables, module classes), XbyK terms for target (content types, Content hub, website channels).
- Consider complexity: Flag items requiring significant development (custom class mappings, field migrations, widget migrations) vs. simple configuration, but do not add an
Effort column to output tables.
- Preserve content: Default to preserving all content unless the user explicitly requests exclusion.
- Verify with docs: If a Kentico documentation lookup tool is available, verify uncertain capabilities before making assumptions.
- Stay structured: Always produce output following the Markdown template formats.
- Keep the overview readable: The overview must be scannable by a developer without deep migration tool knowledge. No code blocks, no
appsettings.json fragments, no ConvertFrom details. Use plain-language summaries; if complexity is relevant, include it in the summary text rather than a separate Effort column.
- Keep the detail comprehensive: The detail document must contain everything an AI agent needs to implement the migration — full field tables, transformation logic, configuration JSON, and code extension descriptions.
Gotchas
- Use semicolon-separated strings in any
appsettings.json fragments for ConvertClassesToContentHub and CreateReusableFieldSchemaForClasses. The migration tool's ToolConfiguration class requires these as semicolon-separated strings, not JSON arrays. Example: "ConvertClassesToContentHub": "MedioClinic.Doctor;MedioClinic.CompanyService".
- Prefer built-in widget auto-migration: Built-in KX13 system widgets (
Kentico.Widget.RichText, Kentico.FormWidget) have direct XbyK equivalents and migrate with minimal effort in any migration mode — they work in legacy mode, with API Discovery, or with custom migration. API Discovery gives the cleanest result (native XbyK UI controls). Never consolidate built-in KX13 widgets with custom widgets into a new custom widget — this replaces a minimal-effort migration with unnecessary custom IWidgetMigration code. Instead, let built-in widgets migrate to their XbyK equivalents and handle custom widgets separately. Only write custom widget migration code for widgets that have no built-in XbyK counterpart.
- Audit linked pages: Linked pages in KX13 (pages where
NodeLinkedNodeID IS NOT NULL) are references to original pages — they share content and store no data of their own. By default the migration tool materializes them into separate content items, creating duplicates. Always include a Linked Page Audit in the detail document's Page Relationship Handling section, requiring an explicit strategy (materialize, drop, or store_reference) for every linked page discovered in the source page tree. When the source audit includes a Linked Pages section with NodeLinkedNodeID data, use it to identify originals vs. links — the NodeLinkedNodeID column on the linked page points to the NodeID of the original. Common pattern: originals live in a /Reused-content/ folder and linked pages are placed where content is displayed (e.g., under /Home/). In such cases, Drop() or StoreReferenceInAncestor() is usually preferred over Materialize() to avoid content duplication.
- Distinguish migrated vs. new taxonomies: Taxonomies created from KX13 categories by
--categories are fundamentally different from new taxonomies invented for the target model. Always split taxonomy planning into "Migrated Taxonomies" (from KX13 categories) and "New Taxonomies" (manual creation) in both the overview and detail documents. New taxonomies must always be created manually — pre-migration if needed by field transforms, post-migration if only for editorial classification.
- Use
LinkChildren for parent-child hierarchy preservation: When a Content Hub-converted parent page has direct children that should become content item references, use LinkChildren in ContentItemDirectorBase.Direct() on the parent — do NOT default to "post-migration manual". LinkChildren auto-creates reference fields on the target content type. When intermediate non-content nodes (e.g., CMS.Folder) sit between the target ancestor and the child pages, LinkChildren must be called on the intermediate node or the director must handle the folder traversal. Document child-as-reference patterns in the "Child Pages as Ancestor References" section of the detail document, not as post-migration manual steps. Only use StoreReferenceInAncestor for linked pages (in DirectLinkedNode), not for regular parent-child relationships.
- Keep code extension counts consistent: The code extensions summary count in the overview (e.g., "
IWidgetMigration | 5") must exactly match the number of extension rows of that type in the detail's "Code Extensions to Implement" table. When adding or removing a widget/field transformation, update both the extension description and the count. Never leave a transformation described in a mapping section without a corresponding code extension row, and vice versa.
- One story per widget: Each widget must have a single, coherent migration strategy across all plan sections. If a widget's property structure is migrated via
IWidgetMigration but the underlying KX13 feature has no XbyK equivalent, distinguish clearly: "widget structure migrates automatically" vs. "underlying feature (e.g., newsletter engine) requires manual XbyK setup". Do not list the widget as both "requires IWidgetMigration" and "unsupported" without qualification.
- Ask before assuming on divergences: When the target XbyK content model structurally diverges from the source KX13 model (Content Hub conversions with wrappers, type splits/merges, page types replaced by taxonomies, file fields replaced by centralized asset types, significant widget redesigns), always ask the user which approach to take before generating the plan. Never silently adopt the target model's approach when a simpler migration-tool-aligned alternative exists. Present both options with concrete trade-offs (what extra work the XbyK model requires vs. what the simpler approach defers). The user's choices must be collected in Step 3 and drive all subsequent plan generation.
- Include numeric ClassIDs in existing page type tables:
ContentItemDirectorBase and its LinkChildren / Direct filters operate on ICmsTree.NodeClassID, which is an integer — not a class code name. When the source audit provides ClassID values (from CMS_Class.ClassID), include them inline in each page type's heading or summary row in the Source Content Model section. When the audit does not provide ClassIDs, flag them as TODO in each heading so the implementer knows to look them up.
- Field definition changes require explicit mechanisms: Changing a field's data type (e.g.,
text → longtext) or form component (e.g., URLSelector → Link) requires a field definition change — this is distinct from a field value transform. IClassMapping.SetFrom/ConvertFrom handles field renames and value transforms but does NOT change the field's XML definition (data type, column type, form control). Three mechanisms can change field definitions: (1) Built-in mapping — the migration tool's default FieldMigration entries automatically handle standard data type + form control combinations during --page-types. (2) appsettings.json FieldMigrations config — defines custom source → target mappings for form control swaps with no value transform. (3) IFieldMigration code — handles both definition and value changes; required when the transform needs custom logic or value conversion beyond what config supports. (4) IClassMapping.WithFieldPatch — patches field definitions during --page-types after built-in migration runs; can change DataType, Settings["controlname"], and other FormFieldInfo properties. Use when the definition change is scoped to one class and does not need cross-class matching. When using WithFieldPatch for a data type change, pair it with ConvertFrom if the value also needs conversion. Never describe a data type or form control change in an IClassMapping description without specifying which mechanism (WithFieldPatch, IFieldMigration, or config) accomplishes the definition change.