Skip to content

feat(migrate): [5/7] Interactive migration wizard#564

Closed
nkanu17 wants to merge 7 commits intofeat/migrate-batchfrom
feat/migrate-wizard
Closed

feat(migrate): [5/7] Interactive migration wizard#564
nkanu17 wants to merge 7 commits intofeat/migrate-batchfrom
feat/migrate-wizard

Conversation

@nkanu17
Copy link
Copy Markdown
Collaborator

@nkanu17 nkanu17 commented Apr 1, 2026

Summary

Adds an interactive, terminal-based migration wizard that guides users through building a migration plan step by step. The wizard introspects the live index, presents the current schema, and walks through field operations (add, remove, rename, modify) with algorithm-aware validation.

Usage

# Start the wizard for an existing index
rvl migrate wizard --index my_index

# Continue editing an existing patch
rvl migrate wizard --index my_index --patch schema_patch.yaml

# Custom output paths
rvl migrate wizard --index my_index --plan-out my_plan.yaml --patch-out my_patch.yaml

What is included

  • Wizard module (redisvl/migration/wizard.py): MigrationWizard class with:
    • Index selection (interactive list if no index specified)
    • Schema display with current field details
    • Field operations: add field, remove field, rename field, modify field attributes
    • Vector-specific operations: change algorithm, distance metric, quantization type, tuning parameters
    • Index-level operations: rename index, change key prefix
    • Live preview of the migration plan after each change
    • Save/resume support via schema patch files
  • Init updates (redisvl/migration/__init__.py): Exports for MigrationWizard.
  • Unit tests (tests/unit/test_migration_wizard.py): Tests for wizard field operations, validation, and edge cases.

Details

The wizard uses a menu-driven interface with numbered choices:

  1. Presents a main menu of available operations
  2. Validates each change against the target algorithm constraints (e.g., HNSW-specific params, SVS-VAMANA-specific params)
  3. Shows a diff summary after each operation
  4. Allows undo of the last operation
  5. Generates both a schema patch (for reuse) and a migration plan (for apply)

PR Stack

PR Branch Description
#560 feat/migrate-core Core planner, validator, sync executor, and basic CLI
#561 feat/migrate-executor Quantization reliability layer
#562 feat/migrate-async Async planner, executor, and validator
#563 feat/migrate-batch Batch migration with multi-index support
#564 (this) feat/migrate-wizard Interactive migration wizard
#565 feat/migrate-cli-docs Full CLI commands and documentation
#566 feat/migrate-benchmarks Performance benchmarks

Copilot AI review requested due to automatic review settings April 1, 2026 22:38
@jit-ci
Copy link
Copy Markdown

jit-ci bot commented Apr 1, 2026

🛡️ Jit Security Scan Results

CRITICAL HIGH MEDIUM

✅ No security findings were detected in this PR


Security scan by Jit

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b94e57ae6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 1, 2026

@codex review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an interactive CLI “migration wizard” for building SchemaPatch changes step-by-step (add/update/remove/rename fields, index name, prefix) and generating a MigrationPlan via the existing migration planner, plus extensive unit tests for vector algorithm/datatype/compression input handling.

Changes:

  • Introduces redisvl.migration.wizard.MigrationWizard to interactively stage schema changes and output a plan/patch/merged target schema.
  • Adds a large unit test suite validating wizard behavior for vector algorithm changes, datatype constraints, distance metrics, and adversarial inputs.
  • Exports MigrationWizard from redisvl.migration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
redisvl/migration/wizard.py New interactive wizard for constructing schema patches and plans with vector-aware prompts.
tests/unit/test_migration_wizard.py New unit tests covering interactive input flows, especially vector configuration edge cases.
redisvl/migration/__init__.py Re-exports MigrationWizard from the migration package.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b94e57ae6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 1, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b94e57ae6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

nkanu17 added a commit that referenced this pull request Apr 2, 2026
- Filter staged additions from update/rename candidate lists
- Cancel staged-add on remove instead of appending to remove_fields
- Add _filter_staged_adds helper method
- Reflect update_fields in working schema (_apply_staged_changes)
- Prevent no-op vector algorithm update when user enters current value
@nkanu17 nkanu17 force-pushed the feat/migrate-batch branch from e052930 to 634cfa1 Compare April 2, 2026 00:30
@nkanu17 nkanu17 force-pushed the feat/migrate-wizard branch from b94e57a to 541db34 Compare April 2, 2026 00:30
@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 541db34af2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

nkanu17 added a commit that referenced this pull request Apr 2, 2026
- Filter staged additions from update/rename candidate lists
- Cancel staged-add on remove instead of appending to remove_fields
- Add _filter_staged_adds helper method
- Reflect update_fields in working schema (_apply_staged_changes)
- Prevent no-op vector algorithm update when user enters current value
@nkanu17 nkanu17 force-pushed the feat/migrate-batch branch from 634cfa1 to cecfd9d Compare April 2, 2026 03:58
nkanu17 added a commit that referenced this pull request Apr 2, 2026
- Remove queued updates/renames when a field is deleted
- Apply index-level changes (name, prefix) in staged preview schema
- Merge duplicate updates for the same field instead of appending
@nkanu17 nkanu17 force-pushed the feat/migrate-wizard branch from 541db34 to 7eea293 Compare April 2, 2026 03:58
@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

@codex review

1 similar comment
@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7eea293e59

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI review requested due to automatic review settings April 2, 2026 15:09
@nkanu17 nkanu17 force-pushed the feat/migrate-batch branch from 9d0329b to 0f42737 Compare April 2, 2026 15:09
nkanu17 added a commit that referenced this pull request Apr 2, 2026
- Prevent rename target from colliding with staged field additions
nkanu17 added a commit that referenced this pull request Apr 2, 2026
- Show 'y or n' when allow_blank=False, 'y, n, or skip' when allow_blank=True
@nkanu17 nkanu17 force-pushed the feat/migrate-wizard branch from d01542e to f8679ab Compare April 2, 2026 15:09
@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f8679abf14

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +249 to +253
changes.update_fields = [
u for u in changes.update_fields if u.name != field_name
]
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Drop stale rename/update entries when removing renamed fields

When a user removes a field after it has been renamed, this branch only removes queued renames by old_name and queued updates by exact current name. If the removed field is the rename target (for example title -> headline, then remove headline), the rename operation is left in the patch, so the executor will still rewrite every document field even though the field is ultimately removed from the target schema; in some rename+update orderings this also leaves an update pointing to a now-missing field and can make plan creation fail. The remove path should clear dependent renames/updates for both sides of staged rename chains.

Useful? React with 👍 / 👎.

Comment on lines +752 to +756
if compression:
attrs["compression"] = compression

# Prompt for REDUCE if LeanVec compression is selected
if compression.startswith("LeanVec"):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Clear stale reduce when changing SVS compression type

Switching an existing SVS field from LeanVec compression to a non-LeanVec option only sets compression and never clears an existing reduce value. Because merge_patch overlays attrs on top of the source field, the old reduce persists, and schema validation then rejects combinations like compression=LVQ8 with reduce set. This causes an interactive wizard flow to generate a patch that fails during plan creation for valid user intent (changing compression type).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +147 to +158
# Apply removes
removed_names = set(changes.remove_fields)
working["fields"] = [
f for f in working["fields"] if f["name"] not in removed_names
]

# Apply renames
rename_map = {r.old_name: r.new_name for r in changes.rename_fields}
for field in working["fields"]:
if field["name"] in rename_map:
field["name"] = rename_map[field["name"]]

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the working-schema preview, staged removes are applied before staged renames. This can make the wizard’s subsequent prompts/preview diverge from how MigrationPlanner.merge_patch applies changes (renames are applied first there), especially when a user renames a field and then removes it (or vice versa). Consider applying renames before removes here, or normalizing remove_fields through the rename map so the interactive state matches the eventual merged schema.

Suggested change
# Apply removes
removed_names = set(changes.remove_fields)
working["fields"] = [
f for f in working["fields"] if f["name"] not in removed_names
]
# Apply renames
rename_map = {r.old_name: r.new_name for r in changes.rename_fields}
for field in working["fields"]:
if field["name"] in rename_map:
field["name"] = rename_map[field["name"]]
# Apply renames first so working schema matches MigrationPlanner.merge_patch
rename_map = {r.old_name: r.new_name for r in changes.rename_fields}
for field in working["fields"]:
if field["name"] in rename_map:
field["name"] = rename_map[field["name"]]
# Apply removes after renames
removed_names = set(changes.remove_fields)
working["fields"] = [
f for f in working["fields"] if f["name"] not in removed_names
]

Copilot uses AI. Check for mistakes.
Comment on lines +159 to +167
# Apply updates (reflect attribute changes in working schema)
update_map = {u.name: u for u in changes.update_fields}
for field in working["fields"]:
if field["name"] in update_map:
upd = update_map[field["name"]]
if upd.attrs:
field.setdefault("attrs", {}).update(upd.attrs)
if upd.type:
field["type"] = upd.type
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Staged updates are applied to the working schema by matching update_map keys to the current field name. If a user stages an update and later stages a rename (or loads a patch with both), the rename will change the field’s name but the update entry will still be keyed by the old name, so the working schema stops reflecting the staged update. This can mislead users and affect later selections. Suggest resolving updates through the rename_map (or rewriting update_fields entries when a rename is added) so updates continue to apply after renames.

Copilot uses AI. Check for mistakes.
Comment on lines +248 to +253
# Also remove any queued updates or renames for this field
changes.update_fields = [
u for u in changes.update_fields if u.name != field_name
]
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When removing a field, queued updates and renames are only cleared by matching update.name == field_name and rename.old_name == field_name. If the field was previously renamed, users will select the new name, leaving behind updates targeting the old name and/or renames that still reference the removed field; this can later cause create_plan_from_patch/merge_patch to raise (update refers to a non-existent field). Consider clearing updates/renames by resolving both old/new names via the current rename map (and also handling rename.new_name matches).

Suggested change
# Also remove any queued updates or renames for this field
changes.update_fields = [
u for u in changes.update_fields if u.name != field_name
]
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
# Also remove any queued updates or renames for this field,
# including any aliases introduced via staged renames.
related_names = {field_name}
updated = True
# Resolve all names connected by the current rename map
while updated:
updated = False
for r in changes.rename_fields:
if r.old_name in related_names or r.new_name in related_names:
before_size = len(related_names)
related_names.update({r.old_name, r.new_name})
if len(related_names) != before_size:
updated = True
# Drop any updates targeting any alias of this field
changes.update_fields = [
u for u in changes.update_fields if u.name not in related_names
]
# Drop any renames that reference any alias of this field
changes.rename_fields = [
r
for r in changes.rename_fields
if r.old_name not in related_names
and r.new_name not in related_names

Copilot uses AI. Check for mistakes.
"a field with that name is already staged for addition."
)
else:
changes.rename_fields.append(field_rename)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Field renames are appended without checking for an existing rename for the same old_name (or for chained/conflicting renames). Staging multiple renames for the same source field will cause merge_patch to fail (second rename can’t find old_name anymore). Consider de-duplicating/replacing existing entries (or preventing multiple renames per original field) when adding a new FieldRename.

Suggested change
changes.rename_fields.append(field_rename)
# Replace any existing rename for the same source field
replaced = False
for i, existing_rename in enumerate(changes.rename_fields):
if existing_rename.old_name == field_rename.old_name:
changes.rename_fields[i] = field_rename
replaced = True
break
if not replaced:
changes.rename_fields.append(field_rename)

Copilot uses AI. Check for mistakes.
Comment on lines +235 to +270
elif action == "3":
field_name = self._prompt_remove_field(working_schema)
if field_name:
# If removing a staged-add, cancel the add instead of
# appending to remove_fields
staged_add_names = {f["name"] for f in changes.add_fields}
if field_name in staged_add_names:
changes.add_fields = [
f for f in changes.add_fields if f["name"] != field_name
]
print(f"Cancelled staged addition of '{field_name}'.")
else:
changes.remove_fields.append(field_name)
# Also remove any queued updates or renames for this field
changes.update_fields = [
u for u in changes.update_fields if u.name != field_name
]
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
]
elif action == "4":
# Filter out staged additions from rename candidates
staged_add_names = {f["name"] for f in changes.add_fields}
rename_schema = self._filter_staged_adds(
working_schema, staged_add_names
)
field_rename = self._prompt_rename_field(rename_schema)
if field_rename:
# Check rename target doesn't collide with staged additions
if field_rename.new_name in staged_add_names:
print(
f"Cannot rename to '{field_rename.new_name}': "
"a field with that name is already staged for addition."
)
else:
changes.rename_fields.append(field_rename)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wizard has complex interactions between rename/update/remove ordering (e.g., update a field, then rename it; or rename then remove). The current logic is sensitive to those sequences and can leave stale update/rename entries. Adding unit tests that cover these multi-step flows would help prevent regressions and catch merge_patch failures early.

Copilot uses AI. Check for mistakes.
nkanu17 added 7 commits April 2, 2026 11:28
…ep field operations and algorithm-aware validation

Interactive CLI wizard for building migration plans step by step.
Supports adding, removing, renaming, and updating fields with
algorithm-aware validation including SVS-VAMANA datatype enforcement,
HNSW parameter tuning, and compression/LeanVec configuration.

Includes wizard unit tests.
- Filter staged additions from update/rename candidate lists
- Cancel staged-add on remove instead of appending to remove_fields
- Add _filter_staged_adds helper method
- Reflect update_fields in working schema (_apply_staged_changes)
- Prevent no-op vector algorithm update when user enters current value
- Remove queued updates/renames when a field is deleted
- Apply index-level changes (name, prefix) in staged preview schema
- Merge duplicate updates for the same field instead of appending
- Prevent rename target from colliding with staged field additions
- Show 'y or n' when allow_blank=False, 'y, n, or skip' when allow_blank=True
@nkanu17 nkanu17 force-pushed the feat/migrate-batch branch from 0f42737 to 7a9f38f Compare April 2, 2026 15:30
@nkanu17 nkanu17 force-pushed the feat/migrate-wizard branch from f8679ab to 4086c0c Compare April 2, 2026 15:30
@nkanu17 nkanu17 changed the title feat(migrator): [5/7] Interactive migration wizard with step-by-step field operations and algorithm-aware validation feat(migrate): [5/7] Interactive migration wizard Apr 2, 2026
@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

@codex review

@nkanu17
Copy link
Copy Markdown
Collaborator Author

nkanu17 commented Apr 2, 2026

Closing in favor of restructured PR stack (Option A ordering).

@nkanu17 nkanu17 closed this Apr 2, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4086c0c0e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +252 to +254
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Drop stale renames when removing a renamed field

When a field is removed, the cleanup only drops pending renames where old_name matches the removed name. If a user renames a -> b and then removes b, that rename remains queued, so execution can still perform document-wide field renames even though the target field is removed from the final schema. For hash indexes this means unnecessary full-keyspace writes and leaves unindexed orphaned data under b; the remove path should also clear renames whose new_name is being removed.

Useful? React with 👍 / 👎.

Comment on lines +147 to +151
# Apply removes
removed_names = set(changes.remove_fields)
working["fields"] = [
f for f in working["fields"] if f["name"] not in removed_names
]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply staged renames before staged removes

The staged-schema preview applies removals before renames, so a queued remove_fields entry that references a renamed target (e.g. remove b after a -> b) is not reflected in the working schema. This lets the wizard continue offering that field for updates/renames, and users can build patches that later fail in planning with Cannot update field ... does not exist once planner merge applies rename+remove in its own order. The staged transformation order should match planner semantics.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

]
changes.rename_fields = [
r for r in changes.rename_fields if r.old_name != field_name
]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removal cleanup misses pre-rename operations, causing planner crash

High Severity

When removing a field that was previously renamed (e.g., "a" renamed to "b", then "b" removed), the cleanup filters changes.update_fields by u.name != field_name and changes.rename_fields by r.old_name != field_name. Since field_name is the post-rename name ("b"), but existing updates reference the pre-rename name ("a") and the rename has old_name="a", neither is cleaned up. The stale FieldUpdate(name="a") and FieldRename(old_name="a", new_name="b") remain in the patch. When the planner's merge_patch processes this, it renames "a"→"b", removes "b", then tries to resolve the update for "a" through the rename map to "b" — which no longer exists — raising a ValueError.

Fix in Cursor Fix in Web

if upd.attrs:
field.setdefault("attrs", {}).update(upd.attrs)
if upd.type:
field["type"] = upd.type
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working schema ignores updates referencing pre-rename field names

Medium Severity

In _apply_staged_changes, after renames are applied (changing field names in the working copy), the update resolution builds update_map keyed by u.name — which may still reference the pre-rename name. Since the field in working["fields"] now has its post-rename name, the lookup field["name"] in update_map fails to match. This means staged attribute updates are silently dropped from the working schema whenever the same field was also renamed, causing the wizard to display an inaccurate preview of the schema state.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants