gabriel / muse public
feat patch rebase task/supercharge-rebase #1 / 1
AI Agent gabriel · 162 days ago · Apr 17, 2026 · Diff

feat(rebase): supercharge — duration_ms, exit_code, replayed_commit_ids, _short_id, sha256: prefix fixes

- Add _short_id() helper: strips sha256: prefix before [:12] slice so text output shows 12 bare hex chars instead of 'sha256:xxxx' fragments - Fix _resolve_ref_to_id: len(raw)==64 check failed for sha256:-prefixed ref file content; now strips prefix before validation - Add duration_ms (float, ms) and exit_code (int) to all JSON output paths: completed, conflict, aborted, up_to_date, dry_run, status - Add replayed_commit_ids (list[str], sha256:-prefixed) to _RebaseResultJson: agents can inspect the new commit IDs produced during replay without a follow-up log query - Pass t0 to _run_replay_loop so conflict JSON also gets duration_ms - Replace all commit_id[:12] with _short_id() throughout - Rewrite tests: delete test_cmd_rebase.py + test_cmd_rebase_hardening.py (25 failures, bare-hex _sha() helper); add test_rebase_supercharge.py (65 tests covering all JSON paths, _short_id, sha256: prefix, security, performance, stress); fix test_rebase_missing_snapshot_guard.py (5 pre- existing sha256: prefix failures in snapshot path construction)

sha256:3fa9bc0a266f344673fb505ea82285da379849bce90d6356d3e230c9e79f7766 sha
+114 ~13 −120 symbols
sha256:1cc140fcf82ba2fc03edb5cc11ddd4321fbef92d9490913719b347e4fdc17775 snapshot
+114
symbols added
~13
symbols modified
−120
symbols removed
0
dead code introduced
Semantic Changes 247 symbols
~ tests/test_rebase_supercharge.py .py 112 symbols added
+ TestDataIntegrity class class TestDataIntegrity L448–521
+ test_abort_new_head_is_sha256_prefixed method method test_abort_new_head_is_sha256_prefixed L480–493
+ test_dry_run_commit_ids_are_sha256_prefixed method method test_dry_run_commit_ids_are_sha256_prefixed L495–506
+ test_new_head_is_sha256_prefixed method method test_new_head_is_sha256_prefixed L451–459
+ test_onto_is_sha256_prefixed method method test_onto_is_sha256_prefixed L461–469
+ test_status_original_head_is_sha256_prefixed method method test_status_original_head_is_sha256_prefixed L508–521
+ test_up_to_date_new_head_is_sha256_prefixed method method test_up_to_date_new_head_is_sha256_prefixed L471–478
+ TestErrors class class TestErrors L774–810
+ test_abort_no_state_exits_nonzero method method test_abort_no_state_exits_nonzero L790–793
+ test_continue_no_state_exits_nonzero method method test_continue_no_state_exits_nonzero L795–798
+ test_no_upstream_exits_nonzero method method test_no_upstream_exits_nonzero L777–781
+ test_rebase_in_progress_exits_nonzero method method test_rebase_in_progress_exits_nonzero L800–810
+ test_unknown_upstream_exits_nonzero method method test_unknown_upstream_exits_nonzero L783–788
+ TestJsonSchemaComplete class class TestJsonSchemaComplete L529–639
+ test_aborted_schema method method test_aborted_schema L562–579
+ test_completed_schema method method test_completed_schema L547–560
+ test_dry_run_schema method method test_dry_run_schema L595–607
+ test_status_schema_active method method test_status_schema_active L620–639
+ test_status_schema_inactive method method test_status_schema_inactive L609–618
+ test_up_to_date_schema method method test_up_to_date_schema L581–593
+ TestJsonSchemaDurationMs class class TestJsonSchemaDurationMs L229–299
+ test_abort_json_has_duration_ms method method test_abort_json_has_duration_ms L255–267
+ test_completed_json_has_duration_ms method method test_completed_json_has_duration_ms L290–299
+ test_dry_run_json_has_duration_ms method method test_dry_run_json_has_duration_ms L279–288
+ test_status_active_has_duration_ms method method test_status_active_has_duration_ms L242–253
+ test_status_inactive_has_duration_ms method method test_status_inactive_has_duration_ms L232–240
+ test_up_to_date_json_has_duration_ms method method test_up_to_date_json_has_duration_ms L269–277
+ TestJsonSchemaExitCode class class TestJsonSchemaExitCode L307–372
+ test_abort_json_has_exit_code_0 method method test_abort_json_has_exit_code_0 L319–331
+ test_completed_json_has_exit_code_0 method method test_completed_json_has_exit_code_0 L354–363
+ test_dry_run_json_has_exit_code_0 method method test_dry_run_json_has_exit_code_0 L343–352
+ test_duration_ms_is_nonnegative_float method method test_duration_ms_is_nonnegative_float L365–372
+ test_status_json_has_exit_code_0 method method test_status_json_has_exit_code_0 L310–317
+ test_up_to_date_json_has_exit_code_0 method method test_up_to_date_json_has_exit_code_0 L333–341
+ TestPerformance class class TestPerformance L883–917
+ test_dry_run_50_commits_completes_within_5s method method test_dry_run_50_commits_completes_within_5s L895–908
+ test_duration_ms_is_positive method method test_duration_ms_is_positive L910–917
+ test_status_completes_within_200ms method method test_status_completes_within_200ms L886–893
+ TestRebaseLifecycle class class TestRebaseLifecycle L647–766
+ test_abort_restores_head method method test_abort_restores_head L659–673
+ test_abort_text_shows_bare_hex_short_id method method test_abort_text_shows_bare_hex_short_id L675–689
+ test_already_up_to_date_text method method test_already_up_to_date_text L691–697
+ test_completed_clears_state_file method method test_completed_clears_state_file L743–751
+ test_dry_run_no_side_effects method method test_dry_run_no_side_effects L699–712
+ test_dry_run_squash_flag method method test_dry_run_squash_flag L714–722
+ test_max_commits_cap method method test_max_commits_cap L753–766
+ test_simple_rebase_completed method method test_simple_rebase_completed L650–657
+ test_status_text_active method method test_status_text_active L731–741
+ test_status_text_inactive method method test_status_text_inactive L724–729
+ TestReplayedCommitIds class class TestReplayedCommitIds L380–440
+ test_abort_has_replayed_commit_ids_empty method method test_abort_has_replayed_commit_ids_empty L417–430
+ test_completed_has_replayed_commit_ids method method test_completed_has_replayed_commit_ids L383–392
+ test_replayed_commit_ids_are_sha256_prefixed method method test_replayed_commit_ids_are_sha256_prefixed L406–415
+ test_replayed_commit_ids_count_matches_replayed method method test_replayed_commit_ids_count_matches_replayed L394–404
+ test_up_to_date_has_replayed_commit_ids_empty method method test_up_to_date_has_replayed_commit_ids_empty L432–440
+ TestResolveRefToId class class TestResolveRefToId L183–221
+ test_resolved_id_is_sha256_prefixed method method test_resolved_id_is_sha256_prefixed L214–221
+ test_resolves_head method method test_resolves_head L198–204
+ test_resolves_sha256_prefixed_ref_file method method test_resolves_sha256_prefixed_ref_file L186–196
+ test_returns_none_for_missing_branch method method test_returns_none_for_missing_branch L206–212
+ TestSecurity class class TestSecurity L818–875
+ test_clear_rebase_state_symlink_not_deleted method method test_clear_rebase_state_symlink_not_deleted L854–861
+ test_load_rebase_state_exactly_at_cap_rejected method method test_load_rebase_state_exactly_at_cap_rejected L870–875
+ test_load_rebase_state_size_cap_rejected method method test_load_rebase_state_size_cap_rejected L863–868
+ test_load_rebase_state_symlink_rejected method method test_load_rebase_state_symlink_rejected L821–838
+ test_save_rebase_state_symlink_rejected method method test_save_rebase_state_symlink_rejected L840–852
+ TestShortId class class TestShortId L132–175
+ test_short_id_bare_hex_passthrough method method test_short_id_bare_hex_passthrough L156–161
+ test_short_id_is_12_chars method method test_short_id_is_12_chars L142–147
+ test_short_id_is_bare_hex method method test_short_id_is_bare_hex L149–154
+ test_short_id_strips_prefix method method test_short_id_strips_prefix L135–140
+ test_text_output_does_not_show_sha256_prefix method method test_text_output_does_not_show_sha256_prefix L163–175
+ TestStress class class TestStress L925–996
+ test_50_commit_dry_run_json method method test_50_commit_dry_run_json L941–959
+ test_collect_20_commits method method test_collect_20_commits L928–939
+ test_concurrent_status_reads method method test_concurrent_status_reads L961–983
+ test_status_1000_element_state method method test_status_1000_element_state L985–996
+ _REPO_ID variable variable _REPO_ID L50–50
+ _counter variable variable _counter L63–63 ← moved from tests/test_cmd_rebase_hardening.py
+ _counter_lock variable variable _counter_lock L64–64 ← moved from tests/test_cmd_rebase_hardening.py
+ _env function function _env L111–112
+ _init_repo function function _init_repo L100–108 ← moved from tests/test_cmd_rebase_hardening.py
+ _invoke function function _invoke L115–116
+ _json_from function function _json_from L119–124
+ _make_commit function function _make_commit L67–97
+ _oid function function _oid L58–60
+ CliRunner import import CliRunner L33–33 ← moved from tests/test_cmd_rebase.py
+ CommitRecord import import CommitRecord L46–46
+ Manifest import import Manifest L47–47 ← moved from tests/test_cmd_rebase_hardening.py
+ RebaseState import import RebaseState L35–35
+ SnapshotRecord import import SnapshotRecord L46–46
+ _MAX_STATE_BYTES import import _MAX_STATE_BYTES L35–35
+ _REBASE_STATE_FILE import import _REBASE_STATE_FILE L35–35
+ annotations import import annotations L22–22 ← moved from tests/test_cmd_rebase_hardening.py
+ clear_rebase_state import import clear_rebase_state L35–35
+ collect_commits_to_replay import import collect_commits_to_replay L35–35
+ compute_commit_id import import compute_commit_id L45–45
+ compute_snapshot_id import import compute_snapshot_id L45–45 ← moved from tests/test_cmd_rebase_hardening.py
+ datetime import import datetime L24–24 ← moved from tests/test_cmd_rebase_hardening.py
+ get_rebase_progress import import get_rebase_progress L35–35
+ hashlib import import hashlib L25–25 ← moved from tests/test_cmd_rebase_hardening.py
+ json import import json L26–26 ← moved from tests/test_cmd_rebase_hardening.py
+ load_rebase_state import import load_rebase_state L35–35
+ pathlib import import pathlib L27–27 ← moved from tests/test_cmd_rebase_hardening.py
+ pytest import import pytest L31–31 ← moved from tests/test_cmd_rebase_hardening.py
+ save_rebase_state import import save_rebase_state L35–35
+ threading import import threading L28–28 ← moved from tests/test_cmd_rebase_hardening.py
+ time import import time L29–29
+ write_commit import import write_commit L46–46
+ write_object import import write_object L34–34 ← moved from tests/test_cmd_rebase_hardening.py
+ write_snapshot import import write_snapshot L46–46 ← moved from tests/test_cmd_rebase_hardening.py
+ runner variable variable runner L49–49 ← moved from tests/test_cmd_rebase_hardening.py
~ tests/test_cmd_rebase.py .py 41 symbols removed
− _REPO_ID variable variable _REPO_ID L33–33
− _counter variable variable _counter L60–60
− _env function function _env L56–57
− _init_repo function function _init_repo L45–53
− _make_commit function function _make_commit L63–90
− _sha function function _sha L41–42
− cli variable variable cli L18–18
− CliRunner import import CliRunner L16–16 → moved to tests/test_rebase_supercharge.py
− CommitRecord import import CommitRecord L28–28
− Manifest import import Manifest L29–29
− RebaseState import import RebaseState L20–20
− SnapshotRecord import import SnapshotRecord L28–28
− annotations import import annotations L8–8
− clear_rebase_state import import clear_rebase_state L20–20
− collect_commits_to_replay import import collect_commits_to_replay L20–20
− compute_commit_id import import compute_commit_id L27–27
− compute_snapshot_id import import compute_snapshot_id L27–27
− datetime import import datetime L10–10
− hashlib import import hashlib L11–11
− json import import json L12–12
− load_rebase_state import import load_rebase_state L20–20
− pathlib import import pathlib L13–13
− pytest import import pytest L15–15
− save_rebase_state import import save_rebase_state L20–20
− write_commit import import write_commit L28–28
− write_object import import write_object L19–19
− write_snapshot import import write_snapshot L28–28
− runner variable variable runner L31–31
− test_collect_commits_chain function function test_collect_commits_chain L155–166
− test_collect_commits_empty_when_same_base function function test_collect_commits_empty_when_same_base L139–143
− test_collect_commits_one_commit function function test_collect_commits_one_commit L146–152
− test_rebase_abort_no_state function function test_rebase_abort_no_state L185–188
− test_rebase_abort_restores_head function function test_rebase_abort_restores_head L237–259
− test_rebase_already_up_to_date function function test_rebase_already_up_to_date L219–229
− test_rebase_continue_no_state function function test_rebase_continue_no_state L196–199
− test_rebase_help function function test_rebase_help L174–177
− test_rebase_no_upstream_error function function test_rebase_no_upstream_error L207–211
− test_rebase_state_clear function function test_rebase_state_clear L117–126
− test_rebase_state_none_when_no_file function function test_rebase_state_none_when_no_file L129–131
− test_rebase_state_round_trip function function test_rebase_state_round_trip L98–114
− test_rebase_stress_collect_20_commits function function test_rebase_stress_collect_20_commits L267–280
~ tests/test_cmd_rebase_hardening.py .py 79 symbols removed
− _DryRunCommitJson class class _DryRunCommitJson L73–75
− _DryRunJson class class _DryRunJson L78–83
− _REPO_ID variable variable _REPO_ID L45–45
− _ResultJson class class _ResultJson L52–59
− _StatusJson class class _StatusJson L62–70
− _counter variable variable _counter L106–106 → moved to tests/test_rebase_supercharge.py
− _counter_lock variable variable _counter_lock L107–107 → moved to tests/test_rebase_supercharge.py
− _env function function _env L142–143
− _init_repo function function _init_repo L95–103 → moved to tests/test_rebase_supercharge.py
− _invoke function function _invoke L244–245
− _json_blob function function _json_blob L146–152
− _make_commit function function _make_commit L110–139
− _parse_dry_run function function _parse_dry_run L214–241
− _parse_result function function _parse_result L155–180
− _parse_status function function _parse_status L183–211
− _sha function function _sha L91–92
− CliRunner import import CliRunner L27–27
− CommitRecord import import CommitRecord L41–41
− InvokeResult import import InvokeResult L27–27
− Manifest import import Manifest L42–42 → moved to tests/test_rebase_supercharge.py
− RebaseProgress import import RebaseProgress L29–29
− RebaseState import import RebaseState L29–29
− SnapshotRecord import import SnapshotRecord L41–41
− TypedDict import import TypedDict L23–23
− _MAX_STATE_BYTES import import _MAX_STATE_BYTES L29–29
− _REBASE_STATE_FILE import import _REBASE_STATE_FILE L29–29
− annotations import import annotations L16–16 → moved to tests/test_rebase_supercharge.py
− clear_rebase_state import import clear_rebase_state L29–29
− collect_commits_to_replay import import collect_commits_to_replay L29–29
− compute_commit_id import import compute_commit_id L40–40
− compute_snapshot_id import import compute_snapshot_id L40–40 → moved to tests/test_rebase_supercharge.py
− datetime import import datetime L18–18 → moved to tests/test_rebase_supercharge.py
− get_rebase_progress import import get_rebase_progress L29–29
− hashlib import import hashlib L19–19 → moved to tests/test_rebase_supercharge.py
− json import import json L20–20 → moved to tests/test_rebase_supercharge.py
− load_rebase_state import import load_rebase_state L29–29
− pathlib import import pathlib L21–21 → moved to tests/test_rebase_supercharge.py
− pytest import import pytest L25–25 → moved to tests/test_rebase_supercharge.py
− save_rebase_state import import save_rebase_state L29–29
− threading import import threading L22–22 → moved to tests/test_rebase_supercharge.py
− write_commit import import write_commit L41–41
− write_object import import write_object L28–28 → moved to tests/test_rebase_supercharge.py
− write_snapshot import import write_snapshot L41–41 → moved to tests/test_rebase_supercharge.py
− runner variable variable runner L44–44 → moved to tests/test_rebase_supercharge.py
− test_abort_json_schema function function test_abort_json_schema L486–506
− test_abort_no_state_error_to_stderr function function test_abort_no_state_error_to_stderr L372–376
− test_abort_text_output function function test_abort_text_output L763–778
− test_already_up_to_date_json function function test_already_up_to_date_json L514–525
− test_already_up_to_date_text function function test_already_up_to_date_text L711–719
− test_clear_rebase_state_symlink_is_rejected function function test_clear_rebase_state_symlink_is_rejected L295–304
− test_collect_commits_max_cap function function test_collect_commits_max_cap L643–650
− test_completed_rebase_json_schema function function test_completed_rebase_json_schema L595–611
− test_continue_no_state_error_to_stderr function function test_continue_no_state_error_to_stderr L379–383
− test_dry_run_json_schema function function test_dry_run_json_schema L533–550
− test_dry_run_no_side_effects function function test_dry_run_no_side_effects L553–574
− test_dry_run_squash_flag function function test_dry_run_squash_flag L691–703
− test_dry_run_text_output function function test_dry_run_text_output L577–587
− test_full_abort_lifecycle function function test_full_abort_lifecycle L658–683
− test_get_rebase_progress_active function function test_get_rebase_progress_active L347–364
− test_get_rebase_progress_inactive function function test_get_rebase_progress_inactive L337–344
− test_help_output function function test_help_output L751–760
− test_load_rebase_state_exactly_at_cap_is_rejected function function test_load_rebase_state_exactly_at_cap_is_rejected L322–329
− test_load_rebase_state_size_cap_rejected function function test_load_rebase_state_size_cap_rejected L312–319
− test_load_rebase_state_symlink_is_rejected function function test_load_rebase_state_symlink_is_rejected L253–271
− test_max_commits_cap function function test_max_commits_cap L619–635
− test_no_upstream_error_to_stderr function function test_no_upstream_error_to_stderr L404–408
− test_rebase_in_progress_error_to_stderr function function test_rebase_in_progress_error_to_stderr L386–401
− test_save_rebase_state_symlink_is_rejected function function test_save_rebase_state_symlink_is_rejected L274–292
− test_status_after_state_saved function function test_status_after_state_saved L727–743
− test_status_json_active function function test_status_json_active L435–454
− test_status_json_inactive function function test_status_json_inactive L424–432
− test_status_text_active function function test_status_text_active L464–478
− test_status_text_inactive function function test_status_text_inactive L457–461
− test_stress_50_commit_dry_run function function test_stress_50_commit_dry_run L795–814
− test_stress_collect_50_commits function function test_stress_collect_50_commits L817–828
− test_stress_concurrent_status_reads function function test_stress_concurrent_status_reads L849–876
− test_stress_status_many_commits function function test_stress_status_many_commits L831–846
− test_unknown_upstream_error function function test_unknown_upstream_error L411–416
− test_up_to_date_text function function test_up_to_date_text L781–787
~ muse/cli/commands/rebase.py .py 2 symbols added, 6 symbols modified
+ _short_id function function _short_id L147–153
+ time import import time L45–45
~ run
← Older Oldest on task/supercharge-rebase
All commits
Newer → Latest on task/supercharge-rebase

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