gabriel / muse public
feat BREAKING task/commit-id-v2-migrate #1 / 1
AI Agent gabriel · 149 days ago · Apr 24, 2026 · Diff

feat: implement muse code migrate for commit-id-v2 DAG replay

Replaces the old git→Muse bridge with the v2 commit ID rewriter: - muse/core/migrate.py: DAG BFS collect, topological sort, v2 ID recompute, bare-sig normalisation, legacy object path migration - muse/cli/commands/migrate.py: CLI wrapper with --dry-run and --json - tests/test_code_migrate.py: 30 tests covering preflight, dry-run, single commit, linear chain, merge commit, branch heads, sig normalisation, idempotency, object path migration, legacy fields - tests/test_migrate.py: deleted (git-bridge; bridge will be muse code bridge)

sha256:dea16257146f6afbf50ae3b52dd15e4eacd236ff1e7338c70c53ee6912075f9a sha
+109 ~2 −135 symbols
sha256:4913a79b99e7c17a9c5d7eadec396adf7ea8bea421e878089e73ed56847721fc snapshot
+109
symbols added
~2
symbols modified
−135
symbols removed
0
dead code introduced
Semantic Changes 246 symbols
~ muse/core/migrate.py .py 26 symbols added
+ MigrateResult class class MigrateResult L50–55
+ _SEP variable variable _SEP L41–41
+ _collect_all_commits function function _collect_all_commits L80–100
+ _migrate_objects function function _migrate_objects L221–257
+ _normalise_sig function function _normalise_sig L68–77
+ _read_raw_commit function function _read_raw_commit L63–65
+ _rewrite_commit function function _rewrite_commit L134–218
+ _topological_sort function function _topological_sort L103–131
+ CommitRecord import import CommitRecord L31–31
+ annotations import import annotations L18–18
+ base64 import import base64 L20–20
+ collections import import collections L21–21
+ commit_path import import commit_path L31–31
+ compute_commit_id import import compute_commit_id L30–30
+ dataclass class import dataclass L24–24
+ field import import field L24–24
+ get_all_branch_heads import import get_all_branch_heads L31–31
+ logging import import logging L22–22
+ msgpack import import msgpack L26–26
+ pathlib import import pathlib L23–23
+ read_repo_id import import read_repo_id L29–29
+ split_id import import split_id L28–28
+ write_branch_ref import import write_branch_ref L31–31
+ write_commit import import write_commit L31–31
+ logger variable variable logger L39–39
+ migrate function function migrate L265–330
~ tests/test_code_migrate.py .py 79 symbols added
+ TestBranchHeads class class TestBranchHeads L534–567
+ test_all_branch_heads_updated method method test_all_branch_heads_updated L535–550
+ test_branch_heads_point_to_v2_ids method method test_branch_heads_point_to_v2_ids L552–567
+ TestDryRun class class TestDryRun L267–315
+ test_dry_run_makes_no_writes method method test_dry_run_makes_no_writes L268–279
+ test_dry_run_reports_old_to_new_mapping method method test_dry_run_reports_old_to_new_mapping L281–300
+ test_dry_run_reports_summary_counts method method test_dry_run_reports_summary_counts L302–315
+ TestFixture class class TestFixture L215–234
+ test_v1_commit_id_differs_from_v2 method method test_v1_commit_id_differs_from_v2 L216–226
+ test_v1_raw_write_is_unreadable_by_read_commit method method test_v1_raw_write_is_unreadable_by_read_commit L228–234
+ TestIdempotent class class TestIdempotent L644–664
+ test_running_twice_same_state method method test_running_twice_same_state L645–664
+ TestJsonOutput class class TestJsonOutput L814–841
+ test_json_dry_run_flag_is_true method method test_json_dry_run_flag_is_true L826–834
+ test_json_live_run_dry_run_is_false method method test_json_live_run_dry_run_is_false L836–841
+ test_json_output_has_required_keys method method test_json_output_has_required_keys L815–824
+ TestLegacyFields class class TestLegacyFields L757–806
+ test_format_version_in_raw_dict_ignored method method test_format_version_in_raw_dict_ignored L758–772
+ test_old_branch_key_in_raw_dict_handled method method test_old_branch_key_in_raw_dict_handled L774–806
+ TestLinearChain class class TestLinearChain L370–423
+ _build_chain method method _build_chain L371–382
+ test_chain_all_readable_after_migrate method method test_chain_all_readable_after_migrate L384–397
+ test_chain_old_ids_all_deleted method method test_chain_old_ids_all_deleted L399–406
+ test_chain_parent_ids_consistent method method test_chain_parent_ids_consistent L408–423
+ TestMergeCommit class class TestMergeCommit L431–526
+ test_merge_commit_both_parents_cascaded method method test_merge_commit_both_parents_cascaded L432–496
+ test_merge_commit_old_file_deleted method method test_merge_commit_old_file_deleted L498–526
+ TestObjectPathMigration class class TestObjectPathMigration L672–749
+ _write_legacy_blob method method _write_legacy_blob L673–681
+ test_blob_already_at_canonical_not_duplicated method method test_blob_already_at_canonical_not_duplicated L718–734
+ test_dry_run_reports_blobs_to_migrate method method test_dry_run_reports_blobs_to_migrate L736–749
+ test_legacy_blob_moved_to_canonical_path method method test_legacy_blob_moved_to_canonical_path L683–699
+ test_legacy_dir_removed_when_empty method method test_legacy_dir_removed_when_empty L701–716
+ TestPreflight class class TestPreflight L242–259
+ test_aborts_when_merge_state_exists method method test_aborts_when_merge_state_exists L243–251
+ test_aborts_when_rebase_in_progress method method test_aborts_when_rebase_in_progress L253–259
+ TestSignatureNormalisation class class TestSignatureNormalisation L575–636
+ _fake_pubkey method method _fake_pubkey L576–578
+ _fake_sig_bytes method method _fake_sig_bytes L580–581
+ test_already_prefixed_sig_unchanged method method test_already_prefixed_sig_unchanged L605–623
+ test_bare_base64_sig_normalised method method test_bare_base64_sig_normalised L583–603
+ test_empty_sig_not_modified method method test_empty_sig_not_ L625–636
+ TestSingleRootCommit class class TestSingleRootCommit L323–362
+ test_already_v2_commit_unchanged method method test_already_v2_commit_unchanged L352–362
+ test_old_commit_file_deleted method method test_old_commit_file_deleted L341–350
+ test_rewrites_v1_commit_with_v2_id method method test_rewrites_v1_commit_with_v2_id L324–339
+ _AT variable variable _AT L49–49
+ _AT_ISO variable variable _AT_ISO L50–50
+ _AUTHOR variable variable _AUTHOR L48–48
+ _REPO_ID variable variable _REPO_ID L47–47
+ _env function function _env L71–72
+ _init_repo function function _init_repo L58–68
+ _invoke function function _invoke L200–207
+ _set_ref function function _set_ref L194–197
+ _snap function function _snap L75–82
+ _v1_commit_id function function _v1_commit_id L120–136
+ _v2_commit function function _v2_commit L85–117
+ _write_v1_commit_raw function function _write_v1_commit_raw L139–191
+ cli variable variable cli L44–44
+ CliRunner import import CliRunner L31–31 ← moved from tests/test_migrate.py
+ CommitRecord import import CommitRecord L34–34
+ MsgpackDict import import MsgpackDict L32–32
+ SnapshotRecord import import SnapshotRecord L34–34
+ annotations import import annotations L21–21 ← moved from tests/test_migrate.py
+ blob_id import import blob_id L32–32
+ commit_path import import commit_path L34–34
+ compute_commit_id import import compute_commit_id L33–33
+ compute_snapshot_id import import compute_snapshot_id L33–33
+ datetime import import datetime L23–23 ← moved from muse/cli/commands/migrate.py
+ get_all_branch_heads import import get_all_branch_heads L34–34
+ hashlib import import hashlib L24–24 ← moved from muse/cli/commands/migrate.py
+ json import import json L25–25 ← moved from tests/test_migrate.py
+ msgpack import import msgpack L28–28
+ pathlib import import pathlib L26–26 ← moved from muse/cli/commands/migrate.py
+ pytest import import pytest L29–29 ← moved from tests/test_migrate.py
+ read_commit import import read_commit L34–34
+ write_commit import import write_commit L34–34
+ write_snapshot import import write_snapshot L34–34
+ runner variable variable runner L45–45 ← moved from tests/test_migrate.py
~ tests/test_migrate.py .py 78 symbols removed
TestCatFileRegression class class TestCatFileRegression L630–647
test_catfile_raises_on_pipe_failure method method test_catfile_raises_on_pipe_failure L631–647
TestManifestDirectories class class TestManifestDirectories L157–193
test_deep_nesting method method test_deep_nesting L190–193
test_dirs_are_sorted method method test_dirs_are_sorted L173–180
test_empty_manifest_gives_empty_list method method test_empty_manifest_gives_empty_list L158–160
test_nested_file_gives_parent_dirs method method test_nested_file_gives_parent_dirs L167–171
test_root_level_files_give_no_dirs method method test_root_level_files_give_no_dirs L162–165
test_shared_parents_deduplicated method method test_shared_parents_deduplicated L182–188
TestMigrateDryRun class class TestMigrateDryRun L313–335
test_dry_run_json_marks_dry_run_true method method test_dry_run_json_marks_dry_run_true L325–335
test_dry_run_writes_nothing method method test_dry_run_writes_nothing L314–323
TestMigrateErrors class class TestMigrateErrors L435–452
test_no_init_flag_skips_muse_init method method test_no_init_flag_skips_muse_init L444–452
test_not_a_git_repo_exits_1 method method test_not_a_git_repo_exits_1 L436–442
TestMigrateIntegrity class class TestMigrateIntegrity L495–622
test_all_manifest_oids_exist_in_object_store method method test_all_manifest_oids_exist_in_object_store L498–517
test_binary_file_objects_written_correctly method method test_binary_file_objects_written_correctly L552–569
test_every_commit_references_existing_snapshot method method test_every_commit_references_existing_snapshot L534–550
test_no_empty_objects_written method method test_no_empty_objects_written L586–596
test_object_count_matches_unique_file_versions method method test_object_count_matches_unique_file_versions L571–584
test_silent_drop_warns_on_unreadable_blob method method test_silent_drop_warns_on_unreadable_blob L598–622
test_stored_object_sha256_matches_filename method method test_stored_object_sha256_matches_filename L519–532
TestMigrateJson class class TestMigrateJson L338–404
test_json_all_lines_are_valid_json method method test_json_all_lines_are_valid_json L383–393
test_json_dry_run_done_event_has_dry_run_true method method test_json_dry_run_done_event_has_dry_run_true L395–404
test_json_emits_branch_start_and_done method method test_json_emits_branch_start_and_done L355–365
test_json_emits_done_event method method test_json_emits_done_event L339–353
test_json_emits_progress_events method method test_json_emits_progress_events L367–381
TestMigrateMultiBranch class class TestMigrateMultiBranch L407–432
test_all_flag_migrates_multiple_branches method method test_all_flag_migrates_multiple_branches L408–419
test_branch_flag_selects_specific_branch method method test_branch_flag_selects_specific_branch L421–432
TestMigrateSingleBranch class class TestMigrateSingleBranch L217–310
test_commit_count_matches method method test_commit_count_matches L228–237
test_deleted_file_not_in_final_snapshot method method test_deleted_file_not_in_final_snapshot L267–277
test_excluded_files_not_in_object_store method method test_excluded_files_not_in_object_store L291–300
test_extra_exclude_pattern method method test_extra_exclude_pattern L302–310
test_file_modification_tracked method method test_file_modification_tracked L254–265
test_object_content_round_trips method method test_object_content_round_trips L239–252
test_renamed_file_in_final_snapshot method method test_renamed_file_in_final_snapshot L279–289
test_single_commit_writes_muse_repo method method test_single_commit_writes_muse_repo L218–226
TestRegisterFlags class class TestRegisterFlags L650–680
test_default_no_json method method test_default_no_json L669–680
test_json_long_flag method method test_json_long_flag L660–667
test_json_short_flag method method test_json_short_flag L651–658
TestShouldExclude class class TestShouldExclude L99–149
test_default_ds_store_excluded method method test_default_ds_store_excluded L118–120
test_default_git_dir_excluded method method test_default_git_dir_excluded L102–104
test_default_muse_dir_excluded method method test_default_muse_dir_excluded L106–108
test_default_pyc_suffix_excluded method method test_default_pyc_suffix_excluded L114–116
test_default_pycache_excluded method method test_default_pycache_excluded L110–112
test_extra_prefix_excluded method method test_extra_prefix_excluded L126–128
test_extra_suffix_excluded method method test_extra_suffix_excluded L130–132
test_node_modules_excluded method method test_node_modules_excluded L134–136
test_normal_py_file_not_excluded method method test_normal_py_file_not_excluded L122–124
test_prefix_dir_itself_excluded method method test_prefix_dir_itself_excluded L146–149
test_root_level_normal_file_not_excluded method method test_root_level_normal_file_not_excluded L142–144
test_venv_excluded method method test_venv_excluded L138–140
_all_commits function function _all_commits L478–492
_all_snapshots function function _all_snapshots L460–475
_commit function function _commit L58–66
_git function function _git L38–46
_latest_manifest function function _latest_manifest L80–91
_make_git_repo function function _make_git_repo L49–55
_migrate function function _migrate L69–77
git_repo function function git_repo L202–206
CliRunner import import CliRunner L29–29 → moved to tests/test_code_migrate.py
Mapping import import Mapping L18–18
annotations import import annotations L17–17 → moved to tests/test_code_migrate.py
hashlib import import hashlib L20–20
json import import json L21–21 → moved to tests/test_code_migrate.py
long_id import import long_id L27–27
pathlib import import pathlib L22–22
pytest import import pytest L25–25 → moved to tests/test_code_migrate.py
read_snapshot import import read_snapshot L28–28
subprocess import import subprocess L23–23
muse_target function function muse_target L210–214
runner variable variable runner L31–31 → moved to tests/test_code_migrate.py
~ muse/cli/commands/migrate.py .py 4 symbols added, 57 symbols removed, 2 symbols modified
Manifest variable variable Manifest L85–85
_BranchStatJson class class _BranchStatJson L93–98
_CatFile class class _CatFile L204–248
__enter__ method method __enter__ L244–245
__exit__ method method __exit__ L247–248
__init__ method method __init__ L212–224
close method method close L239–242
read method method read L226–237
_DEFAULT_EXCLUDE_PREFIXES variable variable _DEFAULT_EXCLUDE_PREFIXES L140–152
_DEFAULT_EXCLUDE_SUFFIXES variable variable _DEFAULT_EXCLUDE_SUFFIXES L154–163
_Delta class class _Delta L188–192
_DeltaMap variable variable _DeltaMap L195–195
_FIELD_SEP variable variable _FIELD_SEP L280–280
_GitMeta variable variable _GitMeta L196–196
_GitMetaCache variable variable _GitMetaCache L197–197
_MigrateBranchDoneJson class class _MigrateBranchDoneJson L117–123
_MigrateBranchStartJson class class _MigrateBranchStartJson L109–114
_MigrateDoneJson class class _MigrateDoneJson L126–133
_MigrateProgressJson class class _MigrateProgressJson L101–106
_RECORD_SEP variable variable _RECORD_SEP L281–281
_batch_commit_log function function _batch_commit_log L284–363
_batch_diff_tree function function _batch_diff_tree L366–436
_ensure_branch_exists function function _ensure_branch_exists L481–485
_get_branch_head function function _get_branch_head L477–478
_git function function _git L255–263
_git_is_repo function function _git_is_repo L271–276
_git_local_branches function function _git_local_branches L266–268
_load_repo_id function function _load_repo_id L488–491
_manifest_directories function function _manifest_directories L444–459
_refs_dir function function _refs_dir L467–468
_replay_branch function function _replay_branch L569–675
_replay_commit function function _replay_commit L499–566
_set_branch_head function function _set_branch_head L471–474
_should_exclude function function _should_exclude L166–179
CommitRecord import import CommitRecord L74–74
EnvelopeJson import import EnvelopeJson L68–68
SnapshotRecord import import SnapshotRecord L74–74
TypedDict import import TypedDict L65–65
append_reflog import import append_reflog L70–70
blob_id import import blob_id L67–67
compute_commit_id import import compute_commit_id L72–72
compute_snapshot_id import import compute_snapshot_id L72–72
dataclasses class import dataclasses L56–56
datetime import import datetime L57–57 → moved to tests/test_code_migrate.py
hashlib import import hashlib L58–58 → moved to tests/test_code_migrate.py
load_json_file import import load_json_file L67–67
make_envelope import import make_envelope L68–68
os import import os L61–61
pathlib import import pathlib L62–62 → moved to tests/test_code_migrate.py
read_ref import import read_ref L71–71
short_id import import short_id L67–67
start_timer import import start_timer L73–73
subprocess import import subprocess L63–63
write_commit import import write_commit L74–74
write_head_branch import import write_head_branch L74–74
write_object import import write_object L69–69
write_snapshot import import write_snapshot L74–74
+ ExitCode import import ExitCode L46–46
+ migrate import import migrate L47–47
+ require_repo import import require_repo L48–48
+ time import import time L44–44
~ run
← Older Oldest on task/commit-id-v2-migrate
All commits
Newer → Latest on task/commit-id-v2-migrate

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:dea16257146f6afbf50ae3b52dd15e4eacd236ff1e7338c70c53ee6912075f9a --body "your comment"