gabriel / muse public
feat BREAKING task/protected-branches #1 / 1
AI Agent gabriel · 136 days ago · Apr 25, 2026 · Diff

feat: config-driven protected branch enforcement

Add [protected_branches] config section with fnmatch glob support. Both -d and -D are blocked; JSON error shape: {error, branch, message}.

sha256:0126045405d03ea8b70d2572152fe64c509496d874fa2e96a188685fdf178e61 sha
+42 ~7 symbols
sha256:6a034ed1ca13d6984c79c84e85b52b04c8633c1e50eaeeabdb2fdc4519e36782 snapshot
+42
symbols added
~7
symbols modified
0
dead code introduced
Semantic Changes 49 symbols
~ tests/test_protected_branches.py .py 37 symbols added
+ TestGetProtectedBranches class class TestGetProtectedBranches L145–177
+ test_glob_pattern_preserved method method test_glob_pattern_preserved L171–177
+ test_reads_list_from_config method method test_reads_list_from_config L146–152
+ test_returns_empty_when_branches_key_absent method method test_returns_empty_when_branches_key_absent L161–169
+ test_returns_empty_when_section_absent method method test_returns_empty_when_section_absent L154–159
+ TestIsBranchProtected class class TestIsBranchProtected L113–137
+ _fn method method _fn L114–116
+ test_case_sensitive method method test_case_sensitive L133–134
+ test_double_star_glob method method test_double_star_glob L136–137
+ test_empty_patterns_never_protects method method test_empty_patterns_never_protects L130–131
+ test_exact_match method method test_exact_match L118–119
+ test_glob_match method method test_glob_match L121–122
+ test_glob_no_match method method test_glob_no_match L124–125
+ test_no_match method method test_no_match L127–128
+ TestProtectedBranchDeletion class class TestProtectedBranchDeletion L185–271
+ test_delete_protected_branch_exits_nonzero method method test_delete_protected_branch_exits_nonzero L186–194
+ test_delete_unprotected_branch_succeeds method method test_delete_unprotected_branch_succeeds L205–212
+ test_empty_protected_list_does_not_block method method test_empty_protected_list_does_not_block L253–260
+ test_error_mentions_protected method method test_error_mentions_protected L224–230
+ test_force_delete_protected_branch_also_blocked method method test_force_delete_protected_branch_also_blocked L196–203
+ test_glob_protected_branch_blocked method method test_glob_protected_branch_blocked L214–222
+ test_json_error_has_error_and_message method method test_json_error_has_error_and_message L232–242
+ test_no_protected_config_deletes_normally method method test_no_protected_config_deletes_normally L244–251
+ test_protected_branch_still_exists_after_blocked_delete method method test_protected_branch_still_exists_after_blocked_delete L262–271
+ _branch function function _branch L66–67
+ _commit function function _commit L70–71
+ _invoke function function _invoke L56–63
+ _write_protected function function _write_protected L74–95
+ cli variable variable cli L47–47
+ CliRunner import import CliRunner L44–44
+ annotations import import annotations L37–37
+ config_toml_path import import config_toml_path L45–45
+ json import import json L39–39
+ pathlib import import pathlib L40–40
+ pytest import import pytest L42–42
+ repo function function repo L99–105
+ runner variable variable runner L48–48
~ muse/cli/commands/branch.py .py 2 symbols added, 5 symbols modified
+ get_protected_branches import import get_protected_branches L62–62
+ is_branch_protected import import is_branch_protected L62–62
~ run
~ muse/cli/config.py .py 3 symbols added, 2 symbols modified
+ get_protected_branches function function get_protected_branches L920–929
+ fnmatch import import fnmatch L42–42
+ is_branch_protected function function is_branch_protected L932–942
← Older Oldest on task/protected-branches
All commits
Newer → Latest on task/protected-branches

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