gabriel / muse public
feat BREAKING verify dev
AI Agent gabriel · 160 days ago · Apr 18, 2026 · Diff

feat(verify): shallow graft + promisor remote architecture

- muse/core/shallow.py: new module — read/write/add/remove/is_shallow - muse/core/object_availability.py: PRESENT/PROMISED/MISSING object state model - muse/core/verify.py: BFS stops at shallow boundary; _collect_ancestor_snapshots prevents orphan sweep from flagging beyond-boundary objects; _check_object helper routes through ObjectState; strict=True treats PROMISED as failures - muse/cli/commands/verify.py: --strict flag, new JSON fields (shallow_commits, promised_objects, is_shallow, promisor_remotes), updated _print_text - muse/cli/config.py: RemoteEntry.promisor field; parse + serialize in TOML - tests: 30 + 19 + 35 new tests; 195 passing

sha256:e18f40828e720efbd23d4198b6d263c94e533411fefa37d0f8e474e9c86fb854 sha
+186 ~13 −2 symbols
sha256:34f2c51e205c7844f0c1080761197b7bb548271c86de7c88c035f7a9f36da06d snapshot
+186
symbols added
~13
symbols modified
−2
symbols removed
0
dead code introduced
Semantic Changes 201 symbols
~ muse/core/object_availability.py .py 7 symbols added
+ ObjectState class class ObjectState L57–67
+ Enum import import Enum L52–52
+ annotations import import annotations L49–49
+ object_path import import object_path L54–54
+ pathlib import import pathlib L51–51
+ load_promisor_remotes function function load_promisor_remotes L95–126
+ object_state function function object_state L70–92
~ muse/core/shallow.py .py 8 symbols added
+ add_shallow function function add_shallow L82–86
+ annotations import import annotations L41–41
+ pathlib import import pathlib L43–43
+ is_shallow function function is_shallow L96–100
+ read_shallow function function read_shallow L51–66
+ remove_shallow function function remove_shallow L89–93
+ shallow_path function function shallow_path L46–48
+ write_shallow function function write_shallow L69–79
~ tests/test_cmd_verify_shallow.py .py 69 symbols added
+ TestCLIShallow class class TestCLIShallow L390–452
+ test_is_shallow_true_in_json_when_shallow_file method method test_is_shallow_true_in_json_when_shallow_file L437–444
+ test_json_has_is_shallow method method test_json_has_is_shallow L403–407
+ test_json_has_promised_objects method method test_json_has_promised_objects L391–395
+ test_json_has_promisor_remotes method method test_json_has_promisor_remotes L409–413
+ test_json_has_shallow_commits method method test_json_has_shallow_commits L397–401
+ test_promisor_remotes_listed_in_json method method test_promisor_remotes_listed_in_json L446–452
+ test_strict_fails_on_promised_via_cli method method test_strict_fails_on_promised_via_cli L422–435
+ test_strict_flag_exists method method test_strict_flag_exists L415–420
+ TestIntegration class class TestIntegration L459–537
+ test_clean_repo_no_remotes_all_ok method method test_clean_repo_no_remotes_all_ok L460–467
+ test_concurrent_reads_stable method method test_concurrent_reads_stable L507–537
+ test_orphan_snapshot_with_missing_object_and_promisor method method test_orphan_snapshot_with_missing_object_and_promisor L492–505
+ test_shallow_repo_with_promisor_all_ok method method test_shallow_repo_with_promisor_all_ok L469–490
+ TestPromisorSemantics class class TestPromisorSemantics L193–272
+ test_missing_object_with_promisor_not_a_failure method method test_missing_object_with_promisor_not_a_failure L194–205
+ test_missing_object_without_promisor_is_failure method method test_missing_object_without_promisor_is_failure L207–214
+ test_mixed_present_and_promised method method test_mixed_present_and_promised L262–272
+ test_present_objects_not_counted_as_promised method method test_present_objects_not_counted_as_promised L230–238
+ test_promised_objects_counted_correctly method method test_promised_objects_counted_correctly L216–228
+ test_promisor_false_opt_out_causes_failure method method test_promisor_false_opt_out_causes_failure L240–249
+ test_promisor_remotes_listed_in_result method method test_promisor_remotes_listed_in_result L251–260
+ TestShallowGraft class class TestShallowGraft L327–383
+ test_graft_objects_themselves_are_checked method method test_graft_objects_themselves_are_checked L366–373
+ test_is_shallow_true_when_shallow_file_exists method method test_is_shallow_true_when_shallow_file_exists L328–335
+ test_multiple_grafts method method test_multiple_grafts L375–383
+ test_parents_beyond_graft_not_checked method method test_parents_beyond_graft_not_checked L344–364
+ test_shallow_commits_counted method method test_shallow_commits_counted L337–342
+ TestStrictMode class class TestStrictMode L279–320
+ test_strict_does_not_change_result_for_present_objects method method test_strict_does_not_change_result_for_present_objects L289–298
+ test_strict_fail_fast method method test_strict_fail_fast L311–320
+ test_strict_fails_on_promised_object method method test_strict_fails_on_promised_object L280–287
+ test_strict_promised_objects_still_zero_in_strict method method test_strict_promised_objects_still_zero_in_strict L300–309
+ TestVerifyResultShape class class TestVerifyResultShape L151–186
+ test_is_shallow_false_without_shallow_file method method test_is_shallow_false_without_shallow_file L178–181
+ test_is_shallow_field_present method method test_is_shallow_field_present L162–165
+ test_promised_objects_field_present method method test_promised_objects_field_present L152–155
+ test_promised_objects_zero_for_clean_repo method method test_promised_objects_zero_for_clean_repo L172–176
+ test_promisor_remotes_empty_without_config method method test_promisor_remotes_empty_without_config L183–186
+ test_promisor_remotes_field_present method method test_promisor_remotes_field_present L167–170
+ test_shallow_commits_field_present method method test_shallow_commits_field_present L157–160
+ _REPO_ID variable variable _REPO_ID L55–55
+ _env function function _env L138–139
+ _init_repo function function _init_repo L66–86
+ _invoke function function _invoke L142–144
+ _make_commit function function _make_commit L89–135
+ _sha function function _sha L62–63
+ CliRunner import import CliRunner L45–45
+ CommitRecord import import CommitRecord L51–51
+ InvokeResult import import InvokeResult L45–45
+ SnapshotRecord import import SnapshotRecord L51–51
+ add_shallow import import add_shallow L49–49
+ annotations import import annotations L36–36
+ compute_commit_id import import compute_commit_id L50–50
+ compute_snapshot_id import import compute_snapshot_id L50–50
+ datetime import import datetime L38–38
+ hashlib import import hashlib L39–39
+ json import import json L40–40
+ long_id import import long_id L47–47
+ object_path import import object_path L48–48
+ pathlib import import pathlib L41–41
+ pytest import import pytest L44–44
+ run_verify import import run_verify L52–52
+ threading import import threading L42–42
+ write_commit import import write_commit L51–51
+ write_object import import write_object L48–48
+ write_shallow import import write_shallow L49–49
+ write_snapshot import import write_snapshot L51–51
+ runner variable variable runner L54–54
+ TestLoadPromisorRemotes class class TestLoadPromisorRemotes L157–205
+ test_all_remotes_are_promisors_by_default method method test_all_remotes_are_promisors_by_default L163–170
+ test_empty_when_no_config method method test_empty_when_no_config L158–161
+ test_explicit_promisor_false_excluded method method test_explicit_promisor_false_excluded L178–182
+ test_explicit_promisor_true_included method method test_explicit_promisor_true_included L172–176
+ test_mixed_promisors method method test_mixed_promisors L184–191
+ test_no_promisor_when_all_opted_out method method test_no_promisor_when_all_opted_out L201–205
+ test_returns_list_of_strings method method test_returns_list_of_strings L193–199
+ TestObjectStateEnum class class TestObjectStateEnum L73–84
+ test_has_missing method method test_has_missing L80–81
+ test_has_present method method test_has_present L74–75
+ test_has_promised method method test_has_promised L77–78
+ test_is_string_enum method method test_is_string_enum L83–84
+ TestObjectStateMissing class class TestObjectStateMissing L141–150
+ test_missing_not_promised method method test_missing_not_promised L147–150
+ test_missing_when_absent_no_remotes method method test_missing_when_absent_no_remotes L142–145
+ TestObjectStatePresent class class TestObjectStatePresent L91–113
+ test_present_takes_priority_over_promisor method method test_present_takes_priority_over_promisor L107–113
+ test_present_when_file_exists_no_remotes method method test_present_when_file_exists_no_remotes L92–97
+ test_present_when_file_exists_with_promisor method method test_present_when_file_exists_with_promisor L99–105
+ TestObjectStatePromised class class TestObjectStatePromised L120–134
+ test_promised_not_present method method test_promised_not_present L131–134
+ test_promised_when_absent_with_multiple_promisors method method test_promised_when_absent_with_multiple_promisors L126–129
+ test_promised_when_absent_with_one_promisor method method test_promised_when_absent_with_one_promisor L121–124
+ _OBJ_CONTENT variable variable _OBJ_CONTENT L65–65
+ _OBJ_ID variable variable _OBJ_ID L66–66
+ _init_repo function function _init_repo L39–47
+ _sha function function _sha L35–36
+ _write_remotes function function _write_remotes L50–62
+ ObjectState import import ObjectState L27–27
+ annotations import import annotations L17–17
+ hashlib import import hashlib L24–24
+ json import import json L19–19
+ load_promisor_remotes import import load_promisor_remotes L27–27
+ long_id import import long_id L26–26
+ object_state import import object_state L27–27
+ pathlib import import pathlib L20–20
+ pytest import import pytest L22–22
+ write_object import import write_object L28–28
~ tests/test_core_shallow.py .py 51 symbols added
+ TestAddShallow class class TestAddShallow L162–184
+ test_add_is_idempotent method method test_add_is_idempotent L174–178
+ test_add_when_no_file_exists method method test_add_when_no_file_exists L180–184
+ test_adds_to_empty method method test_adds_to_empty L163–166
+ test_adds_to_existing method method test_adds_to_existing L168–172
+ TestIsShallow class class TestIsShallow L220–244
+ test_false_after_removing_all method method test_false_after_removing_all L240–244
+ test_false_when_empty_file method method test_false_when_empty_file L225–228
+ test_false_when_no_file method method test_false_when_no_file L221–223
+ test_true_when_has_entry method method test_true_when_has_entry L230–233
+ test_true_with_multiple_entries method method test_true_with_multiple_entries L235–238
+ TestReadShallow class class TestReadShallow L68–113
+ test_deduplicates method method test_deduplicates L110–113
+ test_ignores_blank_lines method method test_ignores_blank_lines L89–92
+ test_ignores_comment_lines method method test_ignores_comment_lines L99–102
+ test_reads_multiple_commits method method test_reads_multiple_commits L84–87
+ test_reads_single_commit method method test_reads_single_commit L79–82
+ test_returns_empty_frozenset_for_empty_file method method test_returns_empty_frozenset_for_empty_file L74–77
+ test_returns_empty_frozenset_when_no_file method method test_returns_empty_frozenset_when_no_file L69–72
+ test_returns_frozenset_not_set method method test_returns_frozenset_not_set L104–108
+ test_strips_whitespace method method test_strips_whitespace L94–97
+ TestRemoveShallow class class TestRemoveShallow L191–213
+ test_remove_from_empty_is_noop method method test_remove_from_empty_is_noop L204–207
+ test_remove_last_entry_leaves_empty method method test_remove_last_entry_leaves_empty L209–213
+ test_remove_nonexistent_is_noop method method test_remove_nonexistent_is_noop L198–202
+ test_removes_existing_entry method method test_removes_existing_entry L192–196
+ TestShallowPath class class TestShallowPath L54–61
+ test_does_not_create_file method method test_does_not_create_file L59–61
+ test_returns_path_under_muse method method test_returns_path_under_muse L55–57
+ TestWriteShallow class class TestWriteShallow L120–155
+ test_creates_muse_dir_if_absent method method test_creates_muse_dir_if_absent L152–155
+ test_overwrites_existing method method test_overwrites_existing L146–150
+ test_round_trips method method test_round_trips L140–144
+ test_writes_empty_set_creates_empty_file method method test_writes_empty_set_creates_empty_file L121–126
+ test_writes_multiple_commits_sorted method method test_writes_multiple_commits_sorted L134–138
+ test_writes_single_commit method method test_writes_single_commit L128–132
+ _CID_A variable variable _CID_A L45–45
+ _CID_B variable variable _CID_B L46–46
+ _CID_C variable variable _CID_C L47–47
+ _init_repo function function _init_repo L36–42
+ add_shallow import import add_shallow L21–21
+ annotations import import annotations L14–14
+ is_shallow import import is_shallow L21–21
+ json import import json L16–16
+ long_id import import long_id L29–29
+ pathlib import import pathlib L17–17
+ pytest import import pytest L19–19
+ read_shallow import import read_shallow L21–21
+ remove_shallow import import remove_shallow L21–21
+ shallow_path import import shallow_path L21–21
+ write_shallow import import write_shallow L21–21
~ muse/cli/config.py .py 3 symbols modified
~ muse/core/verify.py .py 8 symbols added, 5 symbols modified
+ _check_object function function _check_object L185–231
+ _collect_ancestor_snapshots function function _collect_ancestor_snapshots L234–268
+ CommitRecord import import CommitRecord L62–62
+ ObjectState import import ObjectState L58–58
+ is_shallow import import is_shallow L61–61
+ load_promisor_remotes import import load_promisor_remotes L58–58
+ object_state import import object_state L58–58
+ read_shallow import import read_shallow L61–61
~ tests/test_cmd_verify.py .py 4 symbols added, 2 symbols removed, 1 symbol modified
− test_zero_byte_object_flagged_without_check_objects method method test_zero_byte_object_flagged_without_check_objects L179–206
− test_zero_byte_object_not_double_reported method method test_zero_byte_object_not_double_reported L208–233
+ test_genuinely_empty_file_passes_hash_check method method test_genuinely_empty_file_passes_hash_check L236–255
+ test_truncated_object_caught_by_hash_check method method test_truncated_object_caught_by_hash_check L180–208
+ test_truncated_object_passes_existence_check method method test_truncated_object_passes_existence_check L210–234
+ test_truncated_object_reported_exactly_once method method test_truncated_object_reported_exactly_once L257–282
← Older Oldest on dev
All commits
Newer → Latest on dev

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