Skip to content

Commit b05782a

Browse files
github-actions[bot]Update Docs WorkflowCopilotzircote
authored
docs: Add migrate_filenames module to library reference
- Document migrate_all, migrate_file, is_migration_complete functions - Add migration behavior explanation (rename/merge/idempotent) - Include practical examples for bulk migration workflows - Update table of contents and module index - Add import cheat sheet entry Addresses documentation gap: lib/migrate_filenames.py was undocumented Co-authored-by: Update Docs Workflow <update-docs@github-actions> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Robert Allen <zircote@gmail.com>
1 parent d08a6d8 commit b05782a

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

docs/library-reference.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Comprehensive reference for the mnemonic Python library modules.
99
- [paths](#paths) - Path resolution and filesystem layout
1010
- [config](#config) - Configuration management
1111
- [memory_reader](#memory_reader) - Memory file parsing
12+
- [migrate_filenames](#migrate_filenames) - Memory file migration utilities
1213
- [search](#search) - Memory search and ranking
1314
- [relationships](#relationships) - Relationship types and linking
1415
- [ontology](#ontology) - Custom ontology support
@@ -156,6 +157,112 @@ Dictionary with keys:
156157

157158
---
158159

160+
### migrate_filenames
161+
162+
**File**: `lib/migrate_filenames.py`
163+
164+
Migration utilities for transitioning memory files from `{uuid}-{slug}.memory.md` to `{slug}.memory.md` naming convention. Handles collision detection, content merging, and idempotent execution.
165+
166+
**Key Functions**:
167+
168+
````python
169+
from lib.migrate_filenames import migrate_all, is_migration_complete, migrate_file
170+
from pathlib import Path
171+
172+
# Check if migration already completed
173+
memory_root = Path.home() / ".claude" / "mnemonic"
174+
if not is_migration_complete(memory_root):
175+
# Perform dry run first
176+
results = migrate_all(memory_root, dry_run=True)
177+
print(f"Would migrate {len(results)} files")
178+
179+
# Execute migration
180+
results = migrate_all(memory_root, dry_run=False)
181+
for result in results:
182+
print(f"{result.action}: {result.original.name}{result.target.name}")
183+
````
184+
185+
**Migration Behavior**:
186+
- **Rename**: `{uuid}-decision.memory.md``decision.memory.md` (preserves git history)
187+
- **Merge**: If `decision.memory.md` already exists, merges content from UUID-prefixed file
188+
- **Idempotent**: Marks completion with `.migration_slug_only_complete` marker file
189+
190+
**API Reference**:
191+
192+
#### `migrate_all(mnemonic_root: Path, dry_run: bool = False) -> list[MigrationResult]`
193+
Migrate all UUID-prefixed memory files in directory tree.
194+
195+
**Parameters**:
196+
- `mnemonic_root`: Root directory to scan recursively
197+
- `dry_run`: If True, return results without modifying files
198+
199+
**Returns**: List of `MigrationResult` objects with fields:
200+
- `original` (Path): Source file path
201+
- `target` (Path): Destination file path
202+
- `action` (str): One of "renamed", "merged", "skipped"
203+
- `merged_with` (Optional[Path]): Target file if merged
204+
205+
**Behavior**:
206+
- Skips if `.migration_slug_only_complete` marker exists
207+
- Uses `git mv` when possible to preserve history
208+
- Merges content on collision (appends under "Merged Content" heading)
209+
- Creates marker file on completion
210+
211+
#### `migrate_file(file_path: Path, dry_run: bool = False) -> MigrationResult`
212+
Migrate a single memory file.
213+
214+
**Parameters**:
215+
- `file_path`: Path to memory file
216+
- `dry_run`: If True, return result without modifying files
217+
218+
**Returns**: `MigrationResult` object
219+
220+
**Collision Handling**:
221+
When target file exists, merges content by:
222+
1. Keeping existing frontmatter (preserves original ID, dates)
223+
2. Appending incoming body under separator
224+
3. Adding provenance note with incoming UUID
225+
226+
#### `is_migration_complete(mnemonic_root: Path) -> bool`
227+
Check if migration has been run.
228+
229+
**Returns**: True if `.migration_slug_only_complete` marker exists
230+
231+
#### `mark_migration_complete(mnemonic_root: Path) -> None`
232+
Create marker file to prevent re-running migration.
233+
234+
**Use Cases**:
235+
- **Batch Migration**: Run once during setup to clean up legacy filenames
236+
- **Continuous Integration**: Check `is_migration_complete()` before operations
237+
- **Manual Recovery**: Use `migrate_file()` for selective migration after conflicts
238+
239+
**Example - Bulk Migration**:
240+
241+
````python
242+
from lib.migrate_filenames import migrate_all, migration_summary
243+
from pathlib import Path
244+
245+
memory_root = Path("~/.claude/mnemonic").expanduser()
246+
247+
# Execute with logging
248+
results = migrate_all(memory_root, dry_run=False)
249+
summary = migration_summary(results)
250+
251+
print(f"Migration complete:")
252+
print(f" Renamed: {summary['renamed']} files")
253+
print(f" Merged: {summary['merged']} files")
254+
print(f" Skipped: {summary['skipped']} files")
255+
````
256+
257+
**Design Notes**:
258+
- Atomic writes via `.tmp` files to prevent corruption
259+
- Git-aware (uses `git mv` when possible)
260+
- Collision-safe (merges rather than overwrites)
261+
- Idempotent by default (marker file prevents re-runs)
262+
- CLI support: `python -m lib.migrate_filenames --dry-run`
263+
264+
---
265+
159266
### search
160267

161268
**File**: `lib/search.py`
@@ -633,6 +740,7 @@ def test_memory_operations(test_resolver):
633740
| `paths.py` | Path resolution | `get_memory_dir()`, `get_search_paths()` |
634741
| `config.py` | Configuration | `get_memory_root()`, `MnemonicConfig.load()` |
635742
| `memory_reader.py` | Parsing | `get_memory_metadata()`, `get_memory_summary()` |
743+
| `migrate_filenames.py` | File migration | `migrate_all()`, `migrate_file()`, `is_migration_complete()` |
636744
| `search.py` | Search/ranking | `search_memories()`, `find_related_memories_scored()` |
637745
| `relationships.py` | Linking | `add_bidirectional_relationship()`, `get_inverse()` |
638746
| `ontology.py` | Validation | `load_ontology_data()`, `validate_memory_against_ontology()` |
@@ -649,6 +757,9 @@ from lib.config import get_memory_root
649757
# Memory reading
650758
from lib.memory_reader import get_memory_metadata, get_memory_summary
651759

760+
# Migration
761+
from lib.migrate_filenames import migrate_all, is_migration_complete
762+
652763
# Search
653764
from lib.search import search_memories, find_related_memories_scored
654765

0 commit comments

Comments
 (0)