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

feat: reimagine format-patch + apply-patch as content-addressed, domain-aware, Cohen-labeled Muse patch objects

Replaces the git-style unified diff export with a fully reimagined patch system built for the agent-first era:

- patch_id = sha256(canonical JSON) — any tampering detected before disk write - Cohen action labels on every op: inserted/deleted/modified/moved/renamed - Self-contained .mpatch files embed blobs (base64) for portable transport - applicability block: requires_snapshot, independent_dimensions, conflict_free - elapsed_seconds + exit_code in all JSON output paths - apply-patch: --dry-run, --check, --force; seeds object store from blobs - Full test coverage: unit, integration, data-integrity, security, performance

sha256:6f88cab176942a3760d870b1685b821dd69920040abfae3c002cc71170fe1fcc sha
+188 ~46 −30 symbols
sha256:9005ab95c738a3feb3b337373dc5db278b371a52651785b01ce92a2d05696bd5 snapshot
+188
symbols added
~46
symbols modified
−30
symbols removed
0
dead code introduced
Semantic Changes 264 symbols
~ muse/cli/commands/apply_patch.py .py 22 symbols added
+ ExitCode import import ExitCode L67–67
+ PatchRecord import import PatchRecord L69–69
+ _json import import _json L61–61
+ annotations import import annotations L57–57
+ argparse import import argparse L59–59
+ base64 import import base64 L60–60
+ compute_patch_id import import compute_patch_id L69–69
+ deserialize_patch import import deserialize_patch L69–69
+ get_head_snapshot_id import import get_head_snapshot_id L71–71
+ logging import import logging L62–62
+ pathlib import import pathlib L63–63
+ read_current_branch import import read_current_branch L71–71
+ read_repo_id import import read_repo_id L70–70
+ require_repo import import require_repo L70–70
+ restore_object import import restore_object L68–68
+ sanitize_display import import sanitize_display L75–75
+ sys import import sys L64–64
+ time import import time L65–65
+ write_object import import write_object L68–68
+ logger variable variable logger L77–77
+ register function function register L85–124
+ run function function run L132–284
~ muse/core/patch_record.py .py 14 symbols added
+ PatchRecord class class PatchRecord L67–197
+ _EXCLUDED_FROM_ID variable variable _EXCLUDED_FROM_ID L207–207
+ _record_to_dict function function _record_to_dict L303–331
+ _require_str function function _require_str L339–341
+ _str function function _str L334–336
+ compute_patch_id function function compute_patch_id L210–231
+ deserialize_patch function function deserialize_patch L251–295
+ Any import import Any L58–58
+ annotations import import annotations L53–53
+ dataclass class import dataclass L57–57
+ field import import field L57–57
+ hashlib import import hashlib L55–55
+ json import import json L56–56
+ serialize_patch function function serialize_patch L239–248
~ tests/test_cmd_apply_patch.py .py 46 symbols added
+ TestCheck class class TestCheck L311–344
+ test_check_does_not_write_files method method test_check_does_not_write_files L323–332
+ test_check_exits_zero_when_applicable method method test_check_exits_zero_when_applicable L312–321
+ test_check_json_has_applicable_field method method test_check_json_has_applicable_field L334–344
+ TestDryRun class class TestDryRun L271–303
+ test_dry_run_does_not_write_files method method test_dry_run_does_not_write_files L283–292
+ test_dry_run_exits_zero method method test_dry_run_exits_zero L272–281
+ test_dry_run_json_has_dry_run_true method method test_dry_run_json_has_dry_run_true L294–303
+ TestFileRestoration class class TestFileRestoration L222–263
+ test_added_file_exists_after_apply method method test_added_file_exists_after_apply L223–232
+ test_added_file_has_correct_content method method test_added_file_has_correct_content L234–243
+ test_deleted_file_removed_after_apply method method test_deleted_file_removed_after_apply L245–263
+ TestIntegrity class class TestIntegrity L352–383
+ test_corrupt_json_exits_nonzero method method test_corrupt_json_exits_nonzero L376–383
+ test_missing_patch_file_exits_nonzero method method test_missing_patch_file_exits_nonzero L369–374
+ test_tampered_patch_id_rejected method method test_tampered_patch_id_rejected L353–367
+ TestJsonSchema class class TestJsonSchema L100–214
+ test_elapsed_seconds_is_float method method test_elapsed_seconds_is_float L161–173
+ test_exit_code_is_int_not_bool method method test_exit_code_is_int_not_bool L135–146
+ test_exits_zero_on_success method method test_exits_zero_on_success L101–120
+ test_json_has_elapsed_seconds method method test_json_has_elapsed_seconds L148–159
+ test_json_has_exit_code_zero method method test_json_has_exit_code_zero L122–133
+ test_json_has_files_applied method method test_json_has_files_applied L202–214
+ test_json_has_patch_id method method test_json_has_patch_id L188–200
+ test_json_output_is_compact method method test_json_output_is_compact L175–186
+ _ap function function _ap L86–88
+ _commit function function _commit L50–71
+ _init_repo function function _init_repo L32–38
+ _json function function _json L91–92
+ _make_patch function function _make_patch L74–83
+ _write_object function function _write_object L41–47
+ CliRunner import import CliRunner L19–19
+ CommitRecord import import CommitRecord L21–21
+ InvokeResult import import InvokeResult L19–19
+ SnapshotRecord import import SnapshotRecord L21–21
+ annotations import import annotations L11–11
+ compute_commit_id import import compute_commit_id L20–20
+ compute_snapshot_id import import compute_snapshot_id L20–20
+ datetime import import datetime L13–13
+ json import import json L14–14
+ pathlib import import pathlib L15–15
+ pytest import import pytest L17–17
+ write_commit import import write_commit L21–21
+ write_object import import write_object L22–22
+ write_snapshot import import write_snapshot L21–21
+ runner variable variable runner L24–24
~ tests/test_core_patch_record.py .py 36 symbols added
+ TestComputePatchId class class TestComputePatchId L63–203
+ test_changes_with_different_content method method test_changes_with_different_content L140–170
+ test_deterministic_across_calls method method test_deterministic_across_calls L102–138
+ test_patch_id_excludes_signature_field method method test_patch_id_excludes_signature_field L172–203
+ test_returns_sha256_prefixed_string method method test_returns_sha256_prefixed_string L64–100
+ TestPatchRecord class class TestPatchRecord L293–398
+ test_applicability_has_requires_snapshot method method test_applicability_has_requires_snapshot L365–398
+ test_has_required_fields method method test_has_required_fields L294–324
+ test_ops_with_action_label method method test_ops_with_action_label L326–363
+ TestSerializeDeserialize class class TestSerializeDeserialize L211–285
+ _make_record method method _make_record L212–246
+ test_deserialize_rejects_garbage method method test_deserialize_rejects_garbage L278–280
+ test_deserialize_rejects_missing_patch_id method method test_deserialize_rejects_missing_patch_id L282–285
+ test_deserialize_round_trip method method test_deserialize_round_trip L253–263
+ test_patch_id_preserved_through_round_trip method method test_patch_id_preserved_through_round_trip L272–276
+ test_serialize_returns_bytes method method test_serialize_returns_bytes L248–251
+ test_serialized_is_valid_json method method test_serialized_is_valid_json L265–270
+ _init_repo function function _init_repo L36–42
+ _make_object function function _make_object L45–51
+ _ts function function _ts L54–55
+ CommitRecord import import CommitRecord L25–25
+ PatchRecord import import PatchRecord L18–18
+ SnapshotRecord import import SnapshotRecord L25–25
+ annotations import import annotations L10–10
+ compute_patch_id import import compute_patch_id L18–18
+ compute_snapshot_id import import compute_snapshot_id L24–24
+ datetime import import datetime L28–28
+ deserialize_patch import import deserialize_patch L18–18
+ hashlib import import hashlib L12–12 ← moved from tests/test_cmd_format_patch.py
+ json import import json L13–13
+ pathlib import import pathlib L14–14
+ pytest import import pytest L16–16
+ serialize_patch import import serialize_patch L18–18
+ write_commit import import write_commit L25–25
+ write_object import import write_object L26–26
+ write_snapshot import import write_snapshot L25–25
~ muse/cli/commands/format_patch.py .py 14 symbols added, 4 symbols removed, 9 symbols modified
− _format_patch_content function function _format_patch_content L122–195
− _resolve_commit_range function function _resolve_commit_range L198–263
− contain_path import import contain_path L82–82
− difflib import import difflib L65–65
+ _FORMAT_VERSION variable variable _FORMAT_VERSION L122–122
+ _action_label function function _action_label L131–151
+ _breaking_changes function function _breaking_changes L242–258
+ _build_file_level_ops function function _build_file_level_ops L154–215
+ _record_to_json_dict function function _record_to_json_dict L529–558
+ _resolve_commit function function _resolve_commit L282–326
+ _sem_ver_bump function function _sem_ver_bump L218–239
+ PatchRecord import import PatchRecord L106–106
+ base64 import import base64 L95–95
+ compute_patch_id import import compute_patch_id L106–106
+ get_head_snapshot_id import import get_head_snapshot_id L108–108
+ read_domain import import read_domain L118–118
+ serialize_patch import import serialize_patch L106–106
+ time import import time L102–102
~ run
~ tests/test_cmd_format_patch.py .py 55 symbols added, 26 symbols removed, 2 symbols modified
− _REPO_ID variable variable _REPO_ID L31–31
− _commit_files function function _commit_files L59–98
− _counter variable variable _counter L32–32
− _env function function _env L55–56
− _invoke function function _invoke L101–103
− _sha function function _sha L40–41
− Manifest import import Manifest L27–27
− hashlib import import hashlib L16–16 → moved to tests/test_core_patch_record.py
− os import import os L18–18
− test_format_patch_10_commits_range function function test_format_patch_10_commits_range L340–355
− test_format_patch_content_has_required_headers function function test_format_patch_content_has_required_headers L151–169
− test_format_patch_content_includes_diff_lines function function test_format_patch_content_includes_diff_lines L172–189
− test_format_patch_empty_repo_exits_nonzero function function test_format_patch_empty_repo_exits_nonzero L287–290
− test_format_patch_file_has_diff_content function function test_format_patch_file_has_diff_content L233–242
− test_format_patch_file_has_muse_commit_id_header function function test_format_patch_file_has_muse_commit_id_header L220–230
− test_format_patch_initial_commit_no_parent function function test_format_patch_initial_commit_no_parent L298–309
− test_format_patch_json_schema function function test_format_patch_json_schema L265–279
− test_format_patch_malicious_subject_safe_filename function function test_format_patch_malicious_subject_safe_filename L317–332
− test_format_patch_single_commit_creates_file function function test_format_patch_single_commit_creates_file L197–206
− test_format_patch_single_commit_numbered_filename function function test_format_patch_single_commit_numbered_filename L209–217
− test_format_patch_stdout_contains_patch_content function function test_format_patch_stdout_contains_patch_content L250–257
− test_make_patch_filename_high_number function function test_make_patch_filename_high_number L118–121
− test_make_patch_filename_max_length function function test_make_patch_filename_max_length L139–143
− test_make_patch_filename_numbered function function test_make_patch_filename_numbered L111–115
− test_make_patch_filename_sanitizes_subject function function test_make_patch_filename_sanitizes_subject L124–129
− test_make_patch_filename_strips_control_chars function function test_make_patch_filename_strips_control_chars L132–136
+ TestCohenActionLabels class class TestCohenActionLabels L326–366
+ test_action_label_values_are_valid method method test_action_label_values_are_valid L360–366
+ test_all_ops_have_action_label method method test_all_ops_have_action_label L351–358
+ test_deleted_label_on_removed_file method method test_deleted_label_on_removed_file L334–340
+ test_inserted_label_on_added_file method method test_inserted_label_on_added_file L327–332
+ test_modified_label_on_changed_file method method test_modified_label_on_changed_file L342–349
+ TestErrorPaths class class TestErrorPaths L446–457
+ test_bad_ref_exits_nonzero method method test_bad_ref_exits_nonzero L452–457
+ test_empty_repo_exits_nonzero method method test_empty_repo_exits_nonzero L447–450
+ TestFileChanges class class TestFileChanges L248–318
+ test_applicability_requires_snapshot_matches_from_snapshot method method test_applicability_requires_snapshot_matches_from_snapshot L299–306
+ test_count_equals_len_refs method method test_count_equals_len_refs L308–318
+ test_empty_diff_all_lists_empty method method test_empty_diff_all_lists_empty L271–279
+ test_from_manifest_is_dict method method test_from_manifest_is_dict L287–291
+ test_initial_commit_files_in_files_added method method test_initial_commit_files_in_files_ L249–253
+ test_modified_file_in_files_modified method method test_modified_file_in_files_ L255–261
+ test_removed_file_in_files_deleted method method test_removed_file_in_files_deleted L263–269
+ test_required_objects_is_list method method test_required_objects_is_list L281–285
+ test_to_manifest_is_dict method method test_to_manifest_is_dict L293–297
+ TestJsonSchema class class TestJsonSchema L89–240
+ test_applicability_has_conflict_free method method test_applicability_has_conflict_free L221–226
+ test_applicability_has_independent_dimensions method method test_applicability_has_independent_dimensions L228–233
+ test_applicability_has_requires_snapshot method method test_applicability_has_requires_snapshot L214–219
+ test_domain_matches_repo method method test_domain_matches_repo L148–153
+ test_elapsed_seconds_is_float method method test_elapsed_seconds_is_float L167–173
+ test_elapsed_seconds_present method method test_elapsed_seconds_present L161–165
+ test_elapsed_seconds_six_decimal_places method method test_elapsed_seconds_six_decimal_places L175–180
+ test_exit_code_is_int_not_bool method method test_exit_code_is_int_not_bool L188–192
+ test_exit_code_zero_in_json method method test_exit_code_zero_in_json L182–186
+ test_exits_zero_on_success method method test_exits_zero_on_success L90–95
+ test_format_version_is_1_0 method method test_format_version_is_1_0 L155–159
+ test_has_from_commit_id method method test_has_from_commit_id L131–138
+ test_has_from_snapshot_id method method test_has_from_snapshot_id L116–121
+ test_has_patch_id method method test_has_patch_id L97–101
+ test_has_to_commit_id method method test_has_to_commit_id L140–146
+ test_has_to_snapshot_id method method test_has_to_snapshot_id L123–129
+ test_ops_is_list method method test_ops_is_list L208–212
+ test_output_is_compact_single_line method method test_output_is_compact_single_line L235–240
+ test_patch_id_full_length method method test_patch_id_full_length L109–114
+ test_patch_id_sha256_prefix method method test_patch_id_sha256_prefix L103–107
+ test_sem_ver_bump_present method method test_sem_ver_bump_present L194–200
+ test_summary_is_string method method test_summary_is_string L202–206
+ TestOutputDir class class TestOutputDir L374–412
+ test_mpatch_file_is_valid_json method method test_mpatch_file_is_valid_json L385–395
+ test_mpatch_filename_includes_subject method method test_mpatch_filename_includes_subject L397–405
+ test_nonexistent_output_dir_fails method method test_nonexistent_output_dir_fails L407–412
+ test_writes_mpatch_file method method test_writes_mpatch_file L375–383
+ TestPatchIdStability class class TestPatchIdStability L420–438
+ test_different_commits_different_patch_ids method method test_different_commits_different_patch_ids L429–438
+ test_same_commit_same_patch_id method method test_same_commit_same_patch_id L421–427
+ _commit function function _commit L51–72
+ _fp function function _fp L75–77
+ _json function function _json L80–81
+ _write_object function function _write_object L42–48
+ InvokeResult import import InvokeResult L20–20
← Older Oldest on task/supercharge-patch
All commits
Newer → Latest on task/supercharge-patch

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