gabriel / muse public
feat patch muse#83 feat/snapshot-content-id-migration #4 / 4
AI Agent gabriel · 10 days ago · Jul 7, 2026 · Diff

feat(muse#83): Phase 1 -- migrate_snapshot_content_ids

Detects and corrects unified-store snapshots whose declared snapshot_id does not reproduce their own manifest -- the class of corruption found in musehub#134's investigation that muse.core.migrate's existing snapshot/ commit ID recomputation cannot touch (it only reads the legacy pre- unified-object-store layout).

Standalone module (muse/core/snapshot_content_migrate.py), deliberately not folded into muse code migrate's default pass list -- see the module docstring and docs/issues/snapshot-content-id-migration-plan.md for why.

6 tests, all green: correct snapshots produce zero changes (SC_01), mismatched snapshots are detected and corrected non-destructively (SC_02), dry-run computes without writing (SC_03), the legacy layout is never read by this function (SC_04), directories are included in recomputation (SC_05), a missing objects dir is a clean no-op (SC_06).

sha256:bda202d7c00307949ce90fda73fc9bd0e29255918d90861a6dbb91038775e760 sha
+47 symbols
sha256:9918bf465031d23c8b08bf46c23f627f13a6dbb97343cbb32d7997891044d75c snapshot
+47
symbols added
0
dead code introduced
Semantic Changes 47 symbols
~ muse/core/snapshot_content_migrate.py .py 28 symbols added
+ CommitContentMigrateResult class class CommitContentMigrateResult L161–168
+ SnapshotContentIdMigrationResult class class SnapshotContentIdMigrationResult L299–310
+ SnapshotContentMigrateResult class class SnapshotContentMigrateResult L69–75
+ _IdMap variable variable _IdMap L65–65
+ TYPE_CHECKING import import TYPE_CHECKING L45–45
+ _collect_all_commits import import _collect_all_commits L48–48
+ _committed_at_iso import import _committed_at_iso L48–48
+ _migrate_reflogs import import _migrate_reflogs L48–48
+ _migrate_refs import import _migrate_refs L48–48
+ _migrate_remote_refs import import _migrate_remote_refs L48–48
+ _topological_sort import import _topological_sort L48–48
+ annotations import import annotations L39–39
+ dataclass class import dataclass L44–44
+ encode_public_key import import encode_public_key L58–58
+ field import import field L44–44
+ hash_commit import import hash_commit L47–47
+ hash_snapshot import import hash_snapshot L47–47
+ json import import json L41–41
+ logging import import logging L42–42
+ object_path import import object_path L56–56
+ objects_dir import import objects_dir L57–57
+ pathlib import import pathlib L43–43
+ provenance_payload import import provenance_payload L58–58
+ sign_commit_ed25519 import import sign_commit_ed25519 L58–58
+ logger variable variable logger L63–63
+ migrate_commit_ids_cascade function function migrate_commit_ids_cascade L171–295
+ migrate_snapshot_content_and_cascade function function migrate_snapshot_content_and_cascade L313–344
+ migrate_snapshot_content_ids function function migrate_snapshot_content_ids L78–157
+ _read_unified_snapshot function function _read_unified_snapshot L60–64
+ _write_unified_snapshot function function _write_unified_snapshot L36–57
+ annotations import import annotations L12–12
+ hash_snapshot import import hash_snapshot L19–19
+ json import import json L14–14
+ migrate_snapshot_content_ids import import migrate_snapshot_content_ids L22–22
+ muse_dir import import muse_dir L21–21
+ object_path import import object_path L20–20
+ objects_dir import import objects_dir L21–21
+ pathlib import import pathlib L15–15
+ pytest import import pytest L17–17
+ snapshots_dir import import snapshots_dir L21–21
+ repo function function repo L31–33
+ test_sc_01_correct_snapshot_produces_no_id_map_entry_and_no_write function function test_sc_01_correct_snapshot_produces_no_id_map_entry_and_no_write L72–86
+ test_sc_02_mismatched_snapshot_detected_and_corrected function function test_sc_02_mismatched_snapshot_detected_and_corrected L95–114
+ test_sc_03_dry_run_writes_nothing function function test_sc_03_dry_run_writes_nothing L122–132
+ test_sc_04_legacy_layout_snapshots_are_ignored function function test_sc_04_legacy_layout_snapshots_are_ignored L140–159
+ test_sc_05_directories_are_included_in_recomputation function function test_sc_05_directories_are_included_in_recomputation L167–177
+ test_sc_06_missing_objects_dir_is_a_noop function function test_sc_06_missing_objects_dir_is_a_noop L185–188

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:bda202d7c00307949ce90fda73fc9bd0e29255918d90861a6dbb91038775e760 --body "your comment"