gitwise-cli 0.31.0__tar.gz → 0.32.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/CHANGELOG.md +10 -0
  2. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/PKG-INFO +1 -1
  3. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/__init__.py +1 -1
  4. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_cli_dispatch.py +119 -78
  5. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_cli_parser.py +8 -3
  6. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_cli_setup_agents.py +4 -0
  7. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_i18n_data.json +4 -0
  8. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/audit.py +9 -8
  9. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/branches.py +7 -7
  10. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/clean.py +15 -11
  11. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/commit.py +13 -11
  12. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/conflicts.py +12 -10
  13. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/context.py +25 -15
  14. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/diff.py +43 -29
  15. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/doctor.py +12 -10
  16. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/health.py +7 -7
  17. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/log.py +93 -79
  18. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/merge.py +14 -13
  19. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/optimize.py +14 -11
  20. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/pick.py +10 -10
  21. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/pr.py +13 -12
  22. gitwise_cli-0.32.0/gitwise/schema.py +110 -0
  23. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup.py +17 -13
  24. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/format.py +8 -0
  25. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/show.py +7 -7
  26. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/snapshot.py +6 -6
  27. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/stash.py +15 -13
  28. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/status.py +83 -35
  29. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/suggest.py +17 -8
  30. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/summarize.py +9 -9
  31. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/sync.py +14 -9
  32. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/tag.py +45 -18
  33. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/undo.py +7 -6
  34. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/update.py +13 -13
  35. gitwise_cli-0.32.0/gitwise/utils/json_envelope.py +76 -0
  36. gitwise_cli-0.32.0/gitwise/utils/types.py +80 -0
  37. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/worktree.py +15 -8
  38. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/pyproject.toml +1 -1
  39. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/schema.json +5 -0
  40. gitwise_cli-0.32.0/share/schemas/v1/output/diff.json +79 -0
  41. gitwise_cli-0.32.0/share/schemas/v1/output/log.json +57 -0
  42. gitwise_cli-0.32.0/share/schemas/v1/output/setup-agents.json +49 -0
  43. gitwise_cli-0.32.0/share/schemas/v1/output/status.json +103 -0
  44. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_audit.py +15 -14
  45. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_branches.py +2 -2
  46. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_clean.py +9 -9
  47. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_conflicts.py +3 -3
  48. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_context.py +7 -6
  49. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_diff.py +22 -10
  50. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_doctor.py +12 -8
  51. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_edge_cases.py +10 -7
  52. gitwise_cli-0.32.0/tests/test_envelope_contract.py +69 -0
  53. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_git.py +6 -6
  54. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_health.py +5 -5
  55. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_i18n.py +1 -1
  56. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_in_progress.py +4 -4
  57. gitwise_cli-0.32.0/tests/test_json_envelope_utils.py +76 -0
  58. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_log.py +47 -9
  59. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_main.py +42 -22
  60. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_merge.py +4 -4
  61. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_optimize.py +10 -8
  62. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_output.py +3 -3
  63. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_pick.py +4 -4
  64. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_pr.py +7 -7
  65. gitwise_cli-0.32.0/tests/test_schema_catalog.py +99 -0
  66. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_setup.py +13 -11
  67. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_stash.py +3 -3
  68. gitwise_cli-0.32.0/tests/test_status.py +116 -0
  69. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_suggest.py +4 -4
  70. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_summarize.py +11 -9
  71. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_sync.py +2 -2
  72. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_tag.py +12 -12
  73. gitwise_cli-0.32.0/tests/test_types.py +59 -0
  74. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_worktree.py +3 -3
  75. gitwise_cli-0.31.0/gitwise/schema.py +0 -54
  76. gitwise_cli-0.31.0/gitwise/utils/json_envelope.py +0 -75
  77. gitwise_cli-0.31.0/tests/test_json_envelope_utils.py +0 -36
  78. gitwise_cli-0.31.0/tests/test_schema_catalog.py +0 -45
  79. gitwise_cli-0.31.0/tests/test_status.py +0 -52
  80. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/.gitignore +0 -0
  81. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/LICENSE +0 -0
  82. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/README.md +0 -0
  83. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/bin/gitwise +0 -0
  84. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/__main__.py +0 -0
  85. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_cli_completions.py +0 -0
  86. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_cli_introspection.py +0 -0
  87. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_paths.py +0 -0
  88. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/_runtime_config.py +0 -0
  89. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/design.py +0 -0
  90. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/git.py +0 -0
  91. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/i18n.py +0 -0
  92. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/output.py +0 -0
  93. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/py.typed +0 -0
  94. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/__init__.py +0 -0
  95. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/__init__.py +0 -0
  96. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/aider.py +0 -0
  97. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/base.py +0 -0
  98. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/codex.py +0 -0
  99. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  100. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/cursor.py +0 -0
  101. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/opencode.py +0 -0
  102. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/pi.py +0 -0
  103. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/exec.py +0 -0
  104. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan.py +0 -0
  105. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  106. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan_skills.py +0 -0
  107. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/__init__.py +0 -0
  108. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/aider.py +0 -0
  109. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/base.py +0 -0
  110. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/claude.py +0 -0
  111. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/codex.py +0 -0
  112. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  113. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/cursor.py +0 -0
  114. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/opencode.py +0 -0
  115. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/pi.py +0 -0
  116. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/state.py +0 -0
  117. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/types.py +0 -0
  118. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/utils/__init__.py +0 -0
  119. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/utils/git_output.py +0 -0
  120. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/utils/in_progress.py +0 -0
  121. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/utils/parsing.py +0 -0
  122. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/gitwise/utils/secret_scan.py +0 -0
  123. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/install.sh +0 -0
  124. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/agents/skills/git-audit/SKILL.md +0 -0
  125. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/agents/skills/git-clean/SKILL.md +0 -0
  126. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/agents/skills/git-optimize/SKILL.md +0 -0
  127. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/aider/CONVENTIONS.md.template +0 -0
  128. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/aider/aider.conf.yml.template +0 -0
  129. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/CLAUDE.md.template +0 -0
  130. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/rules/gitwise.md +0 -0
  131. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/settings.json.template +0 -0
  132. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/skills/git-audit/SKILL.md +0 -0
  133. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/skills/git-clean/SKILL.md +0 -0
  134. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/claude/skills/git-optimize/SKILL.md +0 -0
  135. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/codex/agents/gitwise.toml.template +0 -0
  136. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/continue/rules/gitwise.md.template +0 -0
  137. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/cursor/rules/gitwise.mdc.template +0 -0
  138. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/git-config-modern.txt +0 -0
  139. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/hooks/commit-msg +0 -0
  140. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/hooks/pre-commit +0 -0
  141. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/opencode/agents/gitwise.md.template +0 -0
  142. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/pi/skills/gitwise.md.template +0 -0
  143. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/audit.json +0 -0
  144. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/branches.json +0 -0
  145. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/clean.json +0 -0
  146. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/commands.json +0 -0
  147. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/commit.json +0 -0
  148. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/completions.json +0 -0
  149. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/conflicts.json +0 -0
  150. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/context.json +0 -0
  151. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/diff.json +0 -0
  152. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/doctor.json +0 -0
  153. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/health.json +0 -0
  154. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/log.json +0 -0
  155. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/merge.json +0 -0
  156. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/optimize.json +0 -0
  157. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/pick.json +0 -0
  158. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/pr.json +0 -0
  159. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/setup-agents.json +0 -0
  160. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/setup.json +0 -0
  161. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/show.json +0 -0
  162. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/snapshot.json +0 -0
  163. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/stash.json +0 -0
  164. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/status.json +0 -0
  165. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/suggest.json +0 -0
  166. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/summarize.json +0 -0
  167. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/sync.json +0 -0
  168. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/tag.json +0 -0
  169. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/undo.json +0 -0
  170. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/update.json +0 -0
  171. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/worktree.json +0 -0
  172. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/__init__.py +0 -0
  173. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/conftest.py +0 -0
  174. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_adapters.py +0 -0
  175. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_commit.py +0 -0
  176. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_design.py +0 -0
  177. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_git_output_utils.py +0 -0
  178. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_md_links_script.py +0 -0
  179. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_parsing_utils.py +0 -0
  180. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_roadmap_baseline_script.py +0 -0
  181. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_sa_plan.py +0 -0
  182. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_sa_unit.py +0 -0
  183. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_secret_scan.py +0 -0
  184. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_setup_agents.py +0 -0
  185. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_show.py +0 -0
  186. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_snapshot.py +0 -0
  187. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_sync_changelog_es_script.py +0 -0
  188. {gitwise_cli-0.31.0 → gitwise_cli-0.32.0}/tests/test_undo.py +0 -0
@@ -3,6 +3,16 @@
3
3
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
4
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## v0.32.0 (2026-06-20)
7
+
8
+ ### BREAKING CHANGE
9
+
10
+ - all --json command outputs now nest fields under data with the v3 envelope {v,ok,command,data,hints,errors}; status.files are FileEntry objects with a new data.conflicted bucket (UU/AA/DD no longer counted in staged/unstaged); log.parents and log.stats are arrays (was space-joined string and raw --stat blob); doctor/audit override top-level ok to reflect computed health. Consumers parsing the old flat v2 shape must read command-specific fields from data.
11
+
12
+ ### Feat
13
+
14
+ - v3 JSON envelope -- nested data, FileEntry, output schemas (Sprint 3) (#70)
15
+
6
16
  ## v0.31.0 (2026-06-19)
7
17
 
8
18
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.31.0
3
+ Version: 0.32.0
4
4
  Summary: Python CLI for optimizing git workflows and Claude Code integration
5
5
  Project-URL: Homepage, https://github.com/drzioner/gitwise
6
6
  Project-URL: Repository, https://github.com/drzioner/gitwise
@@ -1,6 +1,6 @@
1
1
  """gitwise -- CLI for optimizing git workflows and coding-agent integration."""
2
2
 
3
- __version__ = "0.31.0"
3
+ __version__ = "0.32.0"
4
4
 
5
5
 
6
6
  def get_version() -> str:
@@ -4,29 +4,29 @@ import argparse
4
4
  import sys
5
5
  from collections.abc import Callable
6
6
 
7
- from . import __version__
8
- from ._cli_completions import build_completions_script
9
- from ._cli_introspection import (
7
+ from gitwise import __version__
8
+ from gitwise._cli_completions import build_completions_script
9
+ from gitwise._cli_introspection import (
10
10
  canonical_command_name,
11
11
  commands_metadata,
12
12
  resolve_command_parser,
13
13
  )
14
- from ._cli_parser import build_parser
15
- from .i18n import t
16
- from .output import print_json
17
- from .utils.json_envelope import error_envelope
14
+ from gitwise._cli_parser import build_parser
15
+ from gitwise.i18n import t
16
+ from gitwise.output import print_json
17
+ from gitwise.utils.json_envelope import error_envelope, ok_envelope
18
18
 
19
19
 
20
20
  def _run_update(args: argparse.Namespace) -> int:
21
21
  """Dispatch to ``update`` subcommand."""
22
- from .update import run_update
22
+ from gitwise.update import run_update
23
23
 
24
24
  return run_update(dry_run=args.dry_run, as_json=args.json)
25
25
 
26
26
 
27
27
  def _run_doctor(args: argparse.Namespace) -> int:
28
28
  """Dispatch to ``doctor`` subcommand."""
29
- from .doctor import run_doctor
29
+ from gitwise.doctor import run_doctor
30
30
 
31
31
  return run_doctor(as_json=args.json)
32
32
 
@@ -34,14 +34,25 @@ def _run_doctor(args: argparse.Namespace) -> int:
34
34
  def _run_setup_agents(args: argparse.Namespace) -> int:
35
35
  """Dispatch to ``setup-agents`` subcommand, handling provider listing."""
36
36
  if getattr(args, "list_providers", False) or getattr(args, "list_adapters", False):
37
- from .i18n import t as _t
38
- from .setup_agents.providers import list_providers
37
+ from gitwise.i18n import t as _t
38
+ from gitwise.setup_agents.providers import list_providers
39
39
 
40
40
  adapter_list = list_providers()
41
41
  if args.json:
42
- print_json({"providers": adapter_list, "adapters": adapter_list})
42
+ print_json(
43
+ {
44
+ "v": 3,
45
+ "v_compat": [1, 2, 3],
46
+ "command": "setup-agents",
47
+ "hints": [],
48
+ "errors": [],
49
+ "ok": True,
50
+ "providers": adapter_list,
51
+ "adapters": adapter_list,
52
+ }
53
+ )
43
54
  else:
44
- from .output import info
55
+ from gitwise.output import info
45
56
 
46
57
  info(_t("providers_available", list=", ".join(adapter_list)))
47
58
  return 0
@@ -52,7 +63,7 @@ def _run_setup_agents(args: argparse.Namespace) -> int:
52
63
  adapters_legacy_used = True
53
64
  providers = args.adapters if providers is None else providers + args.adapters
54
65
 
55
- from ._cli_setup_agents import run_setup_agents
66
+ from gitwise._cli_setup_agents import run_setup_agents
56
67
 
57
68
  return run_setup_agents(
58
69
  local=args.local,
@@ -73,7 +84,7 @@ def _run_setup_agents(args: argparse.Namespace) -> int:
73
84
 
74
85
  def _run_setup(args: argparse.Namespace) -> int:
75
86
  """Dispatch to ``setup`` subcommand."""
76
- from .setup import run_setup
87
+ from gitwise.setup import run_setup
77
88
 
78
89
  return run_setup(
79
90
  dry_run=args.dry_run,
@@ -85,28 +96,28 @@ def _run_setup(args: argparse.Namespace) -> int:
85
96
 
86
97
  def _run_audit(args: argparse.Namespace) -> int:
87
98
  """Dispatch to ``audit`` subcommand."""
88
- from .audit import run_audit
99
+ from gitwise.audit import run_audit
89
100
 
90
101
  return run_audit(quick=args.quick, as_json=args.json)
91
102
 
92
103
 
93
104
  def _run_summarize(args: argparse.Namespace) -> int:
94
105
  """Dispatch to ``summarize`` subcommand."""
95
- from .summarize import run_summarize
106
+ from gitwise.summarize import run_summarize
96
107
 
97
108
  return run_summarize(as_json=args.json, diff=args.diff, max_commits=args.max_commits)
98
109
 
99
110
 
100
111
  def _run_snapshot(args: argparse.Namespace) -> int:
101
112
  """Dispatch to ``snapshot`` subcommand."""
102
- from .snapshot import run_snapshot
113
+ from gitwise.snapshot import run_snapshot
103
114
 
104
115
  return run_snapshot(as_json=args.json)
105
116
 
106
117
 
107
118
  def _run_clean(args: argparse.Namespace) -> int:
108
119
  """Dispatch to ``clean`` subcommand."""
109
- from .clean import run_clean
120
+ from gitwise.clean import run_clean
110
121
 
111
122
  return run_clean(
112
123
  branches=args.branches,
@@ -119,14 +130,14 @@ def _run_clean(args: argparse.Namespace) -> int:
119
130
 
120
131
  def _run_optimize(args: argparse.Namespace) -> int:
121
132
  """Dispatch to ``optimize`` subcommand."""
122
- from .optimize import run_optimize
133
+ from gitwise.optimize import run_optimize
123
134
 
124
135
  return run_optimize(dry_run=args.dry_run, yes=args.yes, as_json=args.json)
125
136
 
126
137
 
127
138
  def _run_worktree(args: argparse.Namespace) -> int:
128
139
  """Dispatch to ``worktree`` subcommand."""
129
- from .worktree import run_worktree
140
+ from gitwise.worktree import run_worktree
130
141
 
131
142
  return run_worktree(
132
143
  args.action, getattr(args, "branch", None), dry_run=args.dry_run, as_json=args.json
@@ -165,8 +176,8 @@ def _recover_diff_pathspec_boundary() -> tuple[str | None, list[str] | None]:
165
176
 
166
177
  def _run_diff(args: argparse.Namespace) -> int:
167
178
  """Dispatch to ``diff`` subcommand."""
168
- from .diff import run_diff
169
- from .output import error as error_out
179
+ from gitwise.diff import run_diff
180
+ from gitwise.output import error as error_out
170
181
 
171
182
  refspec = args.refspec
172
183
  paths = args.paths
@@ -177,7 +188,7 @@ def _run_diff(args: argparse.Namespace) -> int:
177
188
  recovered_refspec, recovered_paths = _recover_diff_pathspec_boundary()
178
189
  except ValueError as exc:
179
190
  if args.json:
180
- print_json(error_envelope(error=str(exc), code="too_many_refs"))
191
+ print_json(error_envelope("diff", error=str(exc), code="too_many_refs"))
181
192
  else:
182
193
  error_out(str(exc))
183
194
  return 1
@@ -200,7 +211,7 @@ def _run_diff(args: argparse.Namespace) -> int:
200
211
 
201
212
  def _run_log(args: argparse.Namespace) -> int:
202
213
  """Dispatch to ``log`` subcommand."""
203
- from .log import run_log
214
+ from gitwise.log import run_log
204
215
 
205
216
  return run_log(
206
217
  as_json=args.json,
@@ -217,14 +228,14 @@ def _run_log(args: argparse.Namespace) -> int:
217
228
 
218
229
  def _run_show(args: argparse.Namespace) -> int:
219
230
  """Dispatch to ``show`` subcommand."""
220
- from .show import run_show
231
+ from gitwise.show import run_show
221
232
 
222
233
  return run_show(ref=args.ref, stat=args.stat, as_json=args.json)
223
234
 
224
235
 
225
236
  def _run_commit(args: argparse.Namespace) -> int:
226
237
  """Dispatch to ``commit`` subcommand."""
227
- from .commit import run_commit
238
+ from gitwise.commit import run_commit
228
239
 
229
240
  return run_commit(
230
241
  message=args.message,
@@ -240,14 +251,14 @@ def _run_commit(args: argparse.Namespace) -> int:
240
251
 
241
252
  def _run_branches(args: argparse.Namespace) -> int:
242
253
  """Dispatch to ``branches`` subcommand."""
243
- from .branches import run_branches
254
+ from gitwise.branches import run_branches
244
255
 
245
256
  return run_branches(stale=args.stale, remote=args.remote, sort=args.sort, as_json=args.json)
246
257
 
247
258
 
248
259
  def _run_sync(args: argparse.Namespace) -> int:
249
260
  """Dispatch to ``sync`` subcommand."""
250
- from .sync import run_sync
261
+ from gitwise.sync import run_sync
251
262
 
252
263
  return run_sync(
253
264
  pull=args.pull,
@@ -260,14 +271,14 @@ def _run_sync(args: argparse.Namespace) -> int:
260
271
 
261
272
  def _run_pr(args: argparse.Namespace) -> int:
262
273
  """Dispatch to ``pr`` subcommand."""
263
- from .pr import run_pr
274
+ from gitwise.pr import run_pr
264
275
 
265
276
  return run_pr(action=args.action, selector=args.selector, as_json=args.json)
266
277
 
267
278
 
268
279
  def _run_undo(args: argparse.Namespace) -> int:
269
280
  """Dispatch to ``undo`` subcommand."""
270
- from .undo import run_undo
281
+ from gitwise.undo import run_undo
271
282
 
272
283
  return run_undo(
273
284
  ref=args.ref,
@@ -281,21 +292,21 @@ def _run_undo(args: argparse.Namespace) -> int:
281
292
 
282
293
  def _run_context(args: argparse.Namespace) -> int:
283
294
  """Dispatch to ``context`` subcommand."""
284
- from .context import run_context
295
+ from gitwise.context import run_context
285
296
 
286
297
  return run_context(as_json=args.json)
287
298
 
288
299
 
289
300
  def _run_health(args: argparse.Namespace) -> int:
290
301
  """Dispatch to ``health`` subcommand."""
291
- from .health import run_health
302
+ from gitwise.health import run_health
292
303
 
293
304
  return run_health(as_json=args.json)
294
305
 
295
306
 
296
307
  def _run_stash(args: argparse.Namespace) -> int:
297
308
  """Dispatch to ``stash`` subcommand."""
298
- from .stash import run_stash
309
+ from gitwise.stash import run_stash
299
310
 
300
311
  return run_stash(
301
312
  action=args.action,
@@ -309,7 +320,7 @@ def _run_stash(args: argparse.Namespace) -> int:
309
320
 
310
321
  def _run_tag(args: argparse.Namespace) -> int:
311
322
  """Dispatch to ``tag`` subcommand."""
312
- from .tag import run_tag
323
+ from gitwise.tag import run_tag
313
324
 
314
325
  return run_tag(
315
326
  action=args.action,
@@ -324,7 +335,7 @@ def _run_tag(args: argparse.Namespace) -> int:
324
335
 
325
336
  def _run_merge(args: argparse.Namespace) -> int:
326
337
  """Dispatch to ``merge`` subcommand."""
327
- from .merge import run_merge
338
+ from gitwise.merge import run_merge
328
339
 
329
340
  return run_merge(
330
341
  args.branch,
@@ -340,21 +351,21 @@ def _run_merge(args: argparse.Namespace) -> int:
340
351
 
341
352
  def _run_conflicts(args: argparse.Namespace) -> int:
342
353
  """Dispatch to ``conflicts`` subcommand."""
343
- from .conflicts import run_conflicts
354
+ from gitwise.conflicts import run_conflicts
344
355
 
345
356
  return run_conflicts(ours=args.ours, theirs=args.theirs, as_json=args.json)
346
357
 
347
358
 
348
359
  def _run_suggest(args: argparse.Namespace) -> int:
349
360
  """Dispatch to ``suggest`` subcommand."""
350
- from .suggest import run_suggest
361
+ from gitwise.suggest import run_suggest
351
362
 
352
363
  return run_suggest(as_json=args.json)
353
364
 
354
365
 
355
366
  def _run_pick(args: argparse.Namespace) -> int:
356
367
  """Dispatch to ``pick`` / ``cherry-pick`` subcommand."""
357
- from .pick import run_pick
368
+ from gitwise.pick import run_pick
358
369
 
359
370
  return run_pick(
360
371
  args.refs,
@@ -368,7 +379,7 @@ def _run_pick(args: argparse.Namespace) -> int:
368
379
 
369
380
  def _run_status(args: argparse.Namespace) -> int:
370
381
  """Dispatch to ``status`` subcommand."""
371
- from .status import run_status
382
+ from gitwise.status import run_status
372
383
 
373
384
  return run_status(as_json=args.json)
374
385
 
@@ -384,46 +395,49 @@ def _run_completions(args: argparse.Namespace) -> int:
384
395
  try:
385
396
  script = build_completions_script(shell=shell, prog=prog)
386
397
  except ModuleNotFoundError:
387
- from .output import error as _error
398
+ from gitwise.output import error as _error
388
399
 
389
400
  hint = t("missing_dependency_hint")
390
401
  message = t("missing_dependency_completions_shtab")
391
402
  if args.json:
392
- print_json(error_envelope(error=message, code="missing_dependency", hint=hint))
403
+ print_json(
404
+ error_envelope("completions", error=message, code="missing_dependency", hint=hint)
405
+ )
393
406
  else:
394
407
  _error(message, hint=hint)
395
408
  return 1
396
409
  except RuntimeError as e:
397
410
  message = str(e)
398
411
  if args.json:
399
- print_json(error_envelope(error=message, code="runtime_error"))
412
+ print_json(error_envelope("completions", error=message, code="runtime_error"))
400
413
  else:
401
- from .output import error as _error
414
+ from gitwise.output import error as _error
402
415
 
403
416
  _error(message)
404
417
  return 1
405
418
  except ValueError:
406
419
  message = t("completions_unsupported_shell", shell=shell)
407
420
  if args.json:
408
- print_json(error_envelope(error=message, code="unsupported_shell"))
421
+ print_json(error_envelope("completions", error=message, code="unsupported_shell"))
409
422
  else:
410
- from .output import error as _error
423
+ from gitwise.output import error as _error
411
424
 
412
425
  _error(message)
413
426
  return 1
414
427
 
415
428
  if args.json:
416
429
  print_json(
417
- {
418
- "v": 2,
419
- "ok": True,
420
- "kind": "completions",
421
- "schema": "gitwise/completions/v1",
422
- "version": __version__,
423
- "shell": shell,
424
- "prog": prog,
425
- "script": script,
426
- }
430
+ ok_envelope(
431
+ "completions",
432
+ data={
433
+ "kind": "completions",
434
+ "schema": "gitwise/completions/v1",
435
+ "version": __version__,
436
+ "shell": shell,
437
+ "prog": prog,
438
+ "script": script,
439
+ },
440
+ )
427
441
  )
428
442
  return 0
429
443
 
@@ -435,14 +449,15 @@ def _run_commands(args: argparse.Namespace) -> int:
435
449
  """List all registered subcommands with aliases."""
436
450
  parser = build_parser()
437
451
  commands = commands_metadata(parser)
438
- payload = {
439
- "v": 2,
440
- "ok": True,
441
- "kind": "commands",
442
- "schema": "gitwise/commands/v1",
443
- "version": __version__,
444
- "commands": commands,
445
- }
452
+ payload = ok_envelope(
453
+ "commands",
454
+ data={
455
+ "kind": "commands",
456
+ "schema": "gitwise/commands/v1",
457
+ "version": __version__,
458
+ "commands": commands,
459
+ },
460
+ )
446
461
 
447
462
  if args.json:
448
463
  print_json(payload)
@@ -465,7 +480,7 @@ def _run_schema(args: argparse.Namespace) -> int:
465
480
 
466
481
  Returns 1 when the command is unknown or its schema file is missing.
467
482
  """
468
- from .schema import load_command_input_schema
483
+ from gitwise.schema import load_command_input_schema
469
484
 
470
485
  parser = build_parser()
471
486
  command_parser = resolve_command_parser(parser=parser, name=args.name)
@@ -475,6 +490,7 @@ def _run_schema(args: argparse.Namespace) -> int:
475
490
  if args.json:
476
491
  print_json(
477
492
  error_envelope(
493
+ "schema",
478
494
  error=message,
479
495
  code="unknown_command",
480
496
  hint=hint,
@@ -483,12 +499,35 @@ def _run_schema(args: argparse.Namespace) -> int:
483
499
  )
484
500
  )
485
501
  else:
486
- from .output import error as _error
502
+ from gitwise.output import error as _error
487
503
 
488
504
  _error(message, hint=hint)
489
505
  return 1
490
506
 
491
507
  name = canonical_command_name(command_parser)
508
+
509
+ if getattr(args, "output", False):
510
+ from gitwise.schema import generic_output_schema, load_command_output_schema
511
+
512
+ output_schema = load_command_output_schema(command=name, version=args.version)
513
+ if output_schema is None:
514
+ output_schema = generic_output_schema(command=name, version=args.version)
515
+ print_json(
516
+ ok_envelope(
517
+ "schema",
518
+ data={
519
+ "kind": "schema",
520
+ "schema": "gitwise/schema/v1",
521
+ "version": __version__,
522
+ "schema_version": args.version,
523
+ "command": name,
524
+ "schema_kind": "cli_output",
525
+ "json_schema": output_schema,
526
+ },
527
+ )
528
+ )
529
+ return 0
530
+
492
531
  schema = load_command_input_schema(command=name, version=args.version)
493
532
  if schema is None:
494
533
  message = t("schema_file_missing", command=name, version=args.version)
@@ -496,6 +535,7 @@ def _run_schema(args: argparse.Namespace) -> int:
496
535
  if args.json:
497
536
  print_json(
498
537
  error_envelope(
538
+ "schema",
499
539
  error=message,
500
540
  code="schema_not_found",
501
541
  hint=hint,
@@ -504,22 +544,23 @@ def _run_schema(args: argparse.Namespace) -> int:
504
544
  )
505
545
  )
506
546
  else:
507
- from .output import error as _error
547
+ from gitwise.output import error as _error
508
548
 
509
549
  _error(message, hint=hint)
510
550
  return 1
511
551
 
512
- payload = {
513
- "v": 2,
514
- "ok": True,
515
- "kind": "schema",
516
- "schema": "gitwise/schema/v1",
517
- "version": __version__,
518
- "schema_version": args.version,
519
- "command": name,
520
- "schema_kind": "cli_input",
521
- "json_schema": schema,
522
- }
552
+ payload = ok_envelope(
553
+ "schema",
554
+ data={
555
+ "kind": "schema",
556
+ "schema": "gitwise/schema/v1",
557
+ "version": __version__,
558
+ "schema_version": args.version,
559
+ "command": name,
560
+ "schema_kind": "cli_input",
561
+ "json_schema": schema,
562
+ },
563
+ )
523
564
 
524
565
  print_json(payload)
525
566
  return 0
@@ -2,9 +2,9 @@
2
2
 
3
3
  import argparse
4
4
 
5
- from . import __version__
6
- from .design import GitwiseRichHelpFormatter
7
- from .i18n import t
5
+ from gitwise import __version__
6
+ from gitwise.design import GitwiseRichHelpFormatter
7
+ from gitwise.i18n import t
8
8
 
9
9
 
10
10
  def _root_help_epilog() -> str:
@@ -361,6 +361,11 @@ def build_parser() -> argparse.ArgumentParser:
361
361
  default="v1",
362
362
  help="schema catalog version (default: v1)",
363
363
  )
364
+ p.add_argument(
365
+ "--output",
366
+ action="store_true",
367
+ help="show the command's --json output schema (default: input schema)",
368
+ )
364
369
 
365
370
  p = sub.add_parser(
366
371
  "completions",
@@ -403,6 +403,10 @@ def run_setup_agents(
403
403
  if as_json:
404
404
  print_json(
405
405
  {
406
+ "v": 3,
407
+ "v_compat": [1, 2, 3],
408
+ "command": "setup-agents",
409
+ "hints": ["gitwise setup-agents --local --no-symlinks"],
406
410
  "ok": False,
407
411
  "error": "windows_global_unsupported",
408
412
  "message": t("setup_agents_windows_global_unsupported"),
@@ -1583,6 +1583,10 @@
1583
1583
  "es": "{count} archivo(s) en área de preparación",
1584
1584
  "en": "{count} file(s) staged"
1585
1585
  },
1586
+ "status_conflicted_label": {
1587
+ "es": "en conflicto",
1588
+ "en": "conflicted"
1589
+ },
1586
1590
  "status_staged_label": {
1587
1591
  "es": "preparados",
1588
1592
  "en": "staged"
@@ -7,7 +7,7 @@ from datetime import datetime, timezone
7
7
  from pathlib import Path
8
8
  from typing import Any
9
9
 
10
- from .git import (
10
+ from gitwise.git import (
11
11
  gpg_status,
12
12
  has_commit_graph,
13
13
  has_remote,
@@ -15,9 +15,9 @@ from .git import (
15
15
  require_root,
16
16
  stale_branches,
17
17
  )
18
- from .git import run as git_run
19
- from .i18n import t
20
- from .output import (
18
+ from gitwise.git import run as git_run
19
+ from gitwise.i18n import t
20
+ from gitwise.output import (
21
21
  debug,
22
22
  ok,
23
23
  print_blank,
@@ -28,6 +28,7 @@ from .output import (
28
28
  print_json,
29
29
  status,
30
30
  )
31
+ from gitwise.utils.json_envelope import ok_envelope
31
32
 
32
33
  _STALE_DAYS = 30
33
34
  _LARGE_BLOB_MIN_BYTES = 1_000_000 # 1MB
@@ -295,7 +296,7 @@ def run_audit(*, quick: bool = False, as_json: bool = False) -> int:
295
296
  }
296
297
  )
297
298
 
298
- from .health import compute_health
299
+ from gitwise.health import compute_health
299
300
 
300
301
  health = compute_health(
301
302
  cwd,
@@ -309,8 +310,6 @@ def run_audit(*, quick: bool = False, as_json: bool = False) -> int:
309
310
  has_issues = any(f["severity"] in ("critical", "high", "medium") for f in findings)
310
311
 
311
312
  result: dict[str, Any] = {
312
- "v": 2,
313
- "ok": not has_issues,
314
313
  "quick": quick,
315
314
  "findings": findings,
316
315
  "summary": {
@@ -325,7 +324,9 @@ def run_audit(*, quick: bool = False, as_json: bool = False) -> int:
325
324
  }
326
325
 
327
326
  if as_json:
328
- print_json(result)
327
+ env = ok_envelope("audit", data=result)
328
+ env["ok"] = not has_issues
329
+ print_json(env)
329
330
  return 0 if not has_issues else 1
330
331
 
331
332
  if not findings:
@@ -3,11 +3,11 @@
3
3
  from pathlib import Path
4
4
  from typing import TypedDict
5
5
 
6
- from .git import require_root, stale_branches, worktree_branches
7
- from .git import run as git_run
8
- from .i18n import t
9
- from .output import error, info, print_dim, print_json, print_table, status
10
- from .utils.json_envelope import ok_envelope
6
+ from gitwise.git import require_root, stale_branches, worktree_branches
7
+ from gitwise.git import run as git_run
8
+ from gitwise.i18n import t
9
+ from gitwise.output import error, info, print_dim, print_json, print_table, status
10
+ from gitwise.utils.json_envelope import ok_envelope
11
11
 
12
12
 
13
13
  class BranchEntry(TypedDict):
@@ -87,7 +87,7 @@ def _print_stale_branches(*, names: list[str], as_json: bool) -> int:
87
87
  info(t("no_stale_branches"))
88
88
  return 0
89
89
  if as_json:
90
- print_json(ok_envelope(stale_branches=names, count=len(names)))
90
+ print_json(ok_envelope("branches", stale_branches=names, count=len(names)))
91
91
  return 0
92
92
  for branch_name in names:
93
93
  print_dim(branch_name)
@@ -205,7 +205,7 @@ def run_branches(
205
205
  return 0
206
206
 
207
207
  if as_json:
208
- print_json(ok_envelope(branches=branches, count=len(branches)))
208
+ print_json(ok_envelope("branches", branches=branches, count=len(branches)))
209
209
  return 0
210
210
  _print_branch_table(branches)
211
211