|
| 1 | +# Recovery: legacy wing names split after the normalization change |
| 2 | + |
| 3 | +**Companion to #1675.** `normalize_wing_name` now strips leading and trailing |
| 4 | +separators, so a path-encoded project dir like `-home-user-proj` derives the |
| 5 | +wing `home_user_proj` instead of `_home_user_proj`. Palaces mined before that |
| 6 | +change filed drawers under the old, separator-padded name. New mining and diary |
| 7 | +writes land on the new name, so the two no longer meet — the history is |
| 8 | +**split**, not lost. `mempalace migrate-wings` re-unites them. |
| 9 | + |
| 10 | +## Symptom |
| 11 | + |
| 12 | +After upgrading, a project that used to surface its memories returns less than |
| 13 | +expected, and `mempalace status` shows two wings for one project — e.g. both |
| 14 | +`_home_user_proj` (old drawers) and `home_user_proj` (newly mined). MCP writes |
| 15 | +to the padded wing may also have been rejected, since `sanitize_name` does not |
| 16 | +accept a leading underscore. |
| 17 | + |
| 18 | +## Recovery |
| 19 | + |
| 20 | +Preview first — this never modifies anything: |
| 21 | + |
| 22 | +```bash |
| 23 | +mempalace migrate-wings --dry-run |
| 24 | +mempalace migrate-wings --dry-run --palace /path/to/palace |
| 25 | +``` |
| 26 | + |
| 27 | +The plan lists each rename and flags collisions that will **merge** into an |
| 28 | +existing wing: |
| 29 | + |
| 30 | +``` |
| 31 | + Wing-name migration plan: |
| 32 | + '_home_user_proj' -> 'home_user_proj': 1284 drawer(s), 96 closet(s) (MERGE into existing wing) |
| 33 | +``` |
| 34 | + |
| 35 | +Apply it: |
| 36 | + |
| 37 | +```bash |
| 38 | +mempalace migrate-wings # prompts for confirmation |
| 39 | +mempalace migrate-wings --yes # no prompt |
| 40 | +``` |
| 41 | + |
| 42 | +## What it does |
| 43 | + |
| 44 | +- Re-keys the `wing` **metadata field** on drawers and closets to the normalized |
| 45 | + form, merging collisions into the existing wing. |
| 46 | +- Re-keys the `topics_by_wing` registry (merging topic lists on collision). |
| 47 | + |
| 48 | +## What it leaves alone |
| 49 | + |
| 50 | +- **Drawer/closet IDs** are untouched. The wing in an ID (`drawer_<wing>_…`) is |
| 51 | + an opaque prefix that is never decoded back into a wing, so leaving it keeps |
| 52 | + closet `→drawer_id` pointers valid and lets future mining still skip |
| 53 | + already-mined files (no duplicates). The verbatim drawer content is never |
| 54 | + read or rewritten. |
| 55 | +- **Tunnels** already normalize wing names at read time, so they resolve under |
| 56 | + the new name without a rewrite. |
| 57 | + |
| 58 | +## Notes |
| 59 | + |
| 60 | +- **Idempotent.** A second run reports "nothing to migrate" and changes nothing. |
| 61 | +- **Backend-agnostic.** Works on any configured storage backend. |
| 62 | +- Run it once per palace after upgrading. New palaces are born with normalized |
| 63 | + wing names and never need it. |
0 commit comments