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

feat(code-add): supercharge JSON output — --json/-j alias, exit_code, duration_ms

muse code add and muse code reset now: - Accept --json / -j as shorthand for --format json (consistent with all other muse commands) - Emit exit_code and duration_ms in every JSON output path, including error branches (no matching files, wrong domain) - Use _CodeAddJson and _CodeResetJson TypedDicts for type-safe construction - Document exit_code and duration_ms in both handler docstrings - Suppress _collect_paths stderr in JSON mode via quiet=True so error JSON is the only output on stdout

tests/test_code_add_supercharge.py: 55 new tests across 7 classes — TestJsonAlias (10), TestDurationMs (10), TestExitCode (11), TestTypedDicts (8), TestDocstrings (4), TestErrorJson (5), TestAnsiSanitizationJson (4), TestPerformance (3).

tests/test_cmd_code_add.py: fix test_VI5 to pop duration_ms before comparing dry-run outputs (same pattern as workspace/worktree).

sha256:40e8ab54d836e0e15c84bfb9646bdba0ec708b42046c1e00c35020fbb89d8eb2 sha
+77 ~8 symbols
sha256:793b74d9975d6334eb39c36ef2ff0fe7daa54cb9a4160821a32a457d972a0938 snapshot
+77
symbols added
~8
symbols modified
0
dead code introduced
Semantic Changes 85 symbols
~ tests/test_code_add_supercharge.py .py 72 symbols added
+ TestAnsiSanitizationJson class class TestAnsiSanitizationJson L381–407
+ test_add_json_dry_run_no_ansi method method test_add_json_dry_run_no_ansi L404–407
+ test_add_json_file_path_has_no_ansi method method test_add_json_file_path_has_no_ansi L384–388
+ test_add_json_multiple_files_no_ansi method method test_add_json_multiple_files_no_ansi L390–395
+ test_reset_json_file_path_has_no_ansi method method test_reset_json_file_path_has_no_ansi L397–402
+ TestDocstrings class class TestDocstrings L319–336
+ test_add_docstring_mentions_duration_ms method method test_add_docstring_mentions_duration_ms L326–328
+ test_add_docstring_mentions_exit_code method method test_add_docstring_mentions_exit_code L322–324
+ test_reset_docstring_mentions_duration_ms method method test_reset_docstring_mentions_duration_ms L334–336
+ test_reset_docstring_mentions_exit_code method method test_reset_docstring_mentions_exit_code L330–332
+ TestDurationMs class class TestDurationMs L148–200
+ test_add_all_has_duration_ms method method test_add_all_has_duration_ms L165–168
+ test_add_dry_run_has_duration_ms method method test_add_dry_run_has_duration_ms L160–163
+ test_add_nothing_to_stage_has_duration_ms method method test_add_nothing_to_stage_has_duration_ms L156–158
+ test_add_success_has_duration_ms method method test_add_success_has_duration_ms L151–154
+ test_add_update_has_duration_ms method method test_add_update_has_duration_ms L170–173
+ test_duration_ms_is_non_negative method method test_duration_ms_is_non_negative L191–194
+ test_duration_ms_is_numeric method method test_duration_ms_is_numeric L196–200
+ test_reset_dry_run_has_duration_ms method method test_reset_dry_run_has_duration_ms L185–189
+ test_reset_nothing_staged_has_duration_ms method method test_reset_nothing_staged_has_duration_ms L181–183
+ test_reset_success_has_duration_ms method method test_reset_success_has_duration_ms L175–179
+ TestErrorJson class class TestErrorJson L344–373
+ test_add_error_exit_code_mirrors_process method method test_add_error_exit_code_mirrors_process L365–368
+ test_add_error_exit_code_nonzero_in_json method method test_add_error_exit_code_nonzero_in_json L359–363
+ test_add_error_json_has_staged_zero method method test_add_error_json_has_staged_zero L370–373
+ test_add_no_matching_files_json_has_duration_ms method method test_add_no_matching_files_json_has_duration_ms L353–357
+ test_add_no_matching_files_json_has_exit_code method method test_add_no_matching_files_json_has_exit_code L347–351
+ TestExitCode class class TestExitCode L208–264
+ test_add_all_exit_code_zero method method test_add_all_exit_code_zero L261–264
+ test_add_dry_run_has_exit_code method method test_add_dry_run_has_exit_code L220–223
+ test_add_exit_code_mirrors_process_exit method method test_add_exit_code_mirrors_process_exit L244–248
+ test_add_exit_code_zero_on_success method method test_add_exit_code_zero_on_success L235–238
+ test_add_nothing_has_exit_code method method test_add_nothing_has_exit_code L216–218
+ test_add_success_has_exit_code method method test_add_success_has_exit_code L211–214
+ test_exit_code_is_int method method test_exit_code_is_int L257–259
+ test_reset_exit_code_mirrors_process_exit method method test_reset_exit_code_mirrors_process_exit L250–255
+ test_reset_exit_code_zero_on_success method method test_reset_exit_code_zero_on_success L240–242
+ test_reset_nothing_has_exit_code method method test_reset_nothing_has_exit_code L231–233
+ test_reset_success_has_exit_code method method test_reset_success_has_exit_code L225–229
+ TestJsonAlias class class TestJsonAlias L57–140
+ test_add_all_flag_with_json method method test_add_all_flag_with_json L135–140
+ test_add_dot_with_json_flag method method test_add_dot_with_json_flag L121–126
+ test_add_j_and_format_json_produce_same_keys method method test_add_j_and_format_json_produce_same_keys L97–106
+ test_add_j_flag_accepted method method test_add_j_flag_accepted L66–70
+ test_add_json_and_format_json_produce_same_keys method method test_add_json_and_format_json_produce_same_keys L86–95
+ test_add_json_flag_accepted method method test_add_json_flag_accepted L60–64
+ test_add_update_flag_with_json method method test_add_update_flag_with_json L128–133
+ test_reset_j_flag_accepted method method test_reset_j_flag_accepted L79–84
+ test_reset_json_and_format_json_produce_same_keys method method test_reset_json_and_format_json_produce_same_keys L108–119
+ test_reset_json_flag_accepted method method test_reset_json_flag_accepted L72–77
+ TestPerformance class class TestPerformance L415–436
+ test_add_all_duration_under_1000ms method method test_add_all_duration_under_1000ms L424–429
+ test_add_single_file_duration_under_1000ms method method test_add_single_file_duration_under_1000ms L418–422
+ test_reset_duration_under_1000ms method method test_reset_duration_under_1000ms L431–436
+ TestTypedDicts class class TestTypedDicts L272–311
+ test_code_add_json_has_added_modified_deleted method method test_code_add_json_has_added_modified_deleted L285–289
+ test_code_add_json_has_dry_run method method test_code_add_json_has_dry_run L291–293
+ test_code_add_json_has_files_annotation method method test_code_add_json_has_files_annotation L281–283
+ test_code_add_json_typeddict_exists method method test_code_add_json_typeddict_exists L275–279
+ test_code_reset_json_has_dry_run method method test_code_reset_json_has_dry_run L309–311
+ test_code_reset_json_has_files_annotation method method test_code_reset_json_has_files_annotation L301–303
+ test_code_reset_json_has_not_staged method method test_code_reset_json_has_not_staged L305–307
+ test_code_reset_json_typeddict_exists method method test_code_reset_json_typeddict_exists L295–299
+ _env function function _env L32–33
+ _run function function _run L36–37
+ CliRunner import import CliRunner L22–22
+ annotations import import annotations L15–15
+ json import import json L17–17
+ pathlib import import pathlib L18–18
+ pytest import import pytest L20–20
+ repo function function repo L41–49
+ runner variable variable runner L24–24
~ muse/cli/commands/code_stage.py .py 5 symbols added, 6 symbols modified
+ _CodeAddFileEntry class class _CodeAddFileEntry L95–99
+ _CodeAddJson class class _CodeAddJson L102–112
+ _CodeResetJson class class _CodeResetJson L115–123
+ TypedDict import import TypedDict L44–44
+ start_timer import import start_timer L52–52
← 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:40e8ab54d836e0e15c84bfb9646bdba0ec708b42046c1e00c35020fbb89d8eb2 --body "your comment"