gabriel / muse public
feat patch dev
AI Agent gabriel · 159 days ago · Apr 19, 2026 · Diff

feat: supercharge muse workspace — envelopes, duration_ms, exit_code, branch_mismatch

- Add duration_ms and exit_code to all six subcommand JSON outputs - Switch list/status from bare arrays to {members, exit_code, duration_ms} envelopes - Add branch_mismatch: bool to _WorkspaceMemberJson (True when actual_branch != tracking branch) - Add _WorkspaceListJson and _WorkspaceStatusJson TypedDicts for the new envelopes - Update run_workspace_sync docstring to document all JSON envelope fields - Update 19 existing hardening tests to match the new schema - Add tests/test_workspace_supercharge.py: 57 tests across 8 classes covering duration_ms (8), exit_code (11), list envelope (6), status envelope (5), branch_mismatch (7), sync exit_code (3), TypedDicts (9), docstrings (5), performance (3)

sha256:658b6bf029fb0dc278aabffed27caef184e1ff4759b7404ba7c4d611495cc206 sha
+88 ~41 symbols
sha256:dfb31a5ea0e46e064c1c5a966322a0f0f9122b16a4ad77ee5ef346a215f51a41 snapshot
+88
symbols added
~41
symbols modified
0
dead code introduced
Semantic Changes 129 symbols
~ tests/test_workspace_supercharge.py .py 85 symbols added
+ TestBranchMismatch class class TestBranchMismatch L341–382
+ test_branch_mismatch_false_when_not_present method method test_branch_mismatch_false_when_not_present L358–362
+ test_branch_mismatch_false_when_on_tracking_branch method method test_branch_mismatch_false_when_on_tracking_branch L348–351
+ test_branch_mismatch_field_in_member_to_json method method test_branch_mismatch_field_in_member_to_json L343–346
+ test_branch_mismatch_in_list_json method method test_branch_mismatch_in_list_json L369–375
+ test_branch_mismatch_in_status_json method method test_branch_mismatch_in_status_json L377–382
+ test_branch_mismatch_is_bool method method test_branch_mismatch_is_bool L364–367
+ test_branch_mismatch_true_when_on_different_branch method method test_branch_mismatch_true_when_on_different_branch L353–356
+ TestDocstrings class class TestDocstrings L454–470
+ test_sync_docstring_mentions_dry_run method method test_sync_docstring_mentions_dry_run L459–460
+ test_sync_docstring_mentions_duration_ms method method test_sync_docstring_mentions_duration_ms L469–470
+ test_sync_docstring_mentions_exit_code method method test_sync_docstring_mentions_exit_code L466–467
+ test_sync_docstring_mentions_json_fields method method test_sync_docstring_mentions_json_fields L462–464
+ test_sync_docstring_mentions_workers method method test_sync_docstring_mentions_workers L456–457
+ TestDurationMs class class TestDurationMs L93–154
+ test_add_json_has_duration_ms method method test_add_json_has_duration_ms L95–100
+ test_duration_ms_is_float method method test_duration_ms_is_float L142–147
+ test_duration_ms_is_non_negative method method test_duration_ms_is_non_negative L149–154
+ test_list_json_has_duration_ms method method test_list_json_has_duration_ms L118–124
+ test_remove_json_has_duration_ms method method test_remove_json_has_duration_ms L110–116
+ test_status_json_has_duration_ms method method test_status_json_has_duration_ms L126–132
+ test_sync_json_has_duration_ms method method test_sync_json_has_duration_ms L134–140
+ test_update_json_has_duration_ms method method test_update_json_has_duration_ms L102–108
+ TestExitCode class class TestExitCode L162–240
+ test_add_exit_code_one_on_duplicate method method test_add_exit_code_one_on_duplicate L214–220
+ test_add_exit_code_zero_on_success method method test_add_exit_code_zero_on_success L208–212
+ test_add_json_has_exit_code method method test_add_json_has_exit_code L164–169
+ test_exit_code_is_int method method test_exit_code_is_int L228–232
+ test_exit_code_mirrors_process_exit method method test_exit_code_mirrors_process_exit L234–240
+ test_list_exit_code_zero_empty method method test_list_exit_code_zero_empty L222–226
+ test_list_json_has_exit_code method method test_list_json_has_exit_code L187–192
+ test_remove_json_has_exit_code method method test_remove_json_has_exit_code L179–185
+ test_status_json_has_exit_code method method test_status_json_has_exit_code L194–199
+ test_sync_json_has_exit_code method method test_sync_json_has_exit_code L201–206
+ test_update_json_has_exit_code method method test_update_json_has_exit_code L171–177
+ TestListEnvelope class class TestListEnvelope L248–293
+ test_list_json_empty_envelope method method test_list_json_empty_envelope L278–284
+ test_list_json_has_members_key method method test_list_json_has_members_key L256–261
+ test_list_json_is_dict_not_array method method test_list_json_is_dict_not_array L250–254
+ test_list_json_member_fields_intact method method test_list_json_member_fields_intact L286–293
+ test_list_json_members_count_matches_registered method method test_list_json_members_count_matches_registered L270–276
+ test_list_json_members_is_array method method test_list_json_members_is_array L263–268
+ TestPerformance class class TestPerformance L478–503
+ test_add_duration_ms_under_500 method method test_add_duration_ms_under_500 L498–503
+ test_list_10_members_duration_ms_under_2000 method method test_list_10_members_duration_ms_under_2000 L480–487
+ test_status_10_members_duration_ms_under_2000 method method test_status_10_members_duration_ms_under_2000 L489–496
+ TestStatusEnvelope class class TestStatusEnvelope L296–333
+ test_status_json_empty_envelope method method test_status_json_empty_envelope L327–333
+ test_status_json_has_members_key method method test_status_json_has_members_key L304–309
+ test_status_json_is_dict_not_array method method test_status_json_is_dict_not_array L298–302
+ test_status_json_members_is_array method method test_status_json_members_is_array L311–316
+ test_status_named_json_is_dict method method test_status_named_json_is_dict L318–325
+ TestSyncExitCode class class TestSyncExitCode L390–411
+ test_sync_dry_run_exit_code_zero method method test_sync_dry_run_exit_code_zero L392–398
+ test_sync_empty_manifest_exit_code_zero method method test_sync_empty_manifest_exit_code_zero L400–405
+ test_sync_exit_code_is_int method method test_sync_exit_code_is_int L407–411
+ TestTypedDicts class class TestTypedDicts L419–446
+ test_workspace_add_json_has_duration_ms_annotation method method test_workspace_add_json_has_duration_ms_annotation L421–422
+ test_workspace_add_json_has_exit_code_annotation method method test_workspace_add_json_has_exit_code_annotation L424–425
+ test_workspace_member_json_has_branch_mismatch_annotation method method test_workspace_member_json_has_branch_mismatch_annotation L445–446
+ test_workspace_remove_json_has_duration_ms_annotation method method test_workspace_remove_json_has_duration_ms_annotation L433–434
+ test_workspace_remove_json_has_exit_code_annotation method method test_workspace_remove_json_has_exit_code_annotation L436–437
+ test_workspace_sync_json_has_duration_ms_annotation method method test_workspace_sync_json_has_duration_ms_annotation L439–440
+ test_workspace_sync_json_has_exit_code_annotation method method test_workspace_sync_json_has_exit_code_annotation L442–443
+ test_workspace_update_json_has_duration_ms_annotation method method test_workspace_update_json_has_duration_ms_annotation L427–428
+ test_workspace_update_json_has_exit_code_annotation method method test_workspace_update_json_has_exit_code_annotation L430–431
+ _add function function _add L64–65
+ _cli function function _cli L54–61
+ _fake_member function function _fake_member L68–85
+ _make_repo function function _make_repo L44–51
+ WorkspaceMemberStatus import import WorkspaceMemberStatus L33–33
+ _WorkspaceAddJson import import _WorkspaceAddJson L24–24
+ _WorkspaceMemberJson import import _WorkspaceMemberJson L24–24
+ _WorkspaceRemoveJson import import _WorkspaceRemoveJson L24–24
+ _WorkspaceSyncJson import import _WorkspaceSyncJson L24–24
+ _WorkspaceUpdateJson import import _WorkspaceUpdateJson L24–24
+ _member_to_json import import _member_to_json L24–24
+ add_workspace_member import import add_workspace_member L33–33
+ annotations import import annotations L15–15
+ json import import json L17–17
+ pathlib import import pathlib L18–18
+ pytest import import pytest L22–22
+ run_workspace_sync import import run_workspace_sync L24–24
+ subprocess import import subprocess L19–19
+ sys import import sys L20–20
~ muse/cli/commands/workspace.py .py 3 symbols added, 12 symbols modified
← 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:658b6bf029fb0dc278aabffed27caef184e1ff4759b7404ba7c4d611495cc206 --body "your comment"