gitwise-cli 0.33.1__tar.gz → 0.34.1__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 (210) hide show
  1. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/CHANGELOG.md +56 -0
  2. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/PKG-INFO +1 -1
  3. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/__init__.py +1 -1
  4. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/__main__.py +18 -9
  5. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_cli_dispatch.py +50 -7
  6. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_cli_introspection.py +25 -5
  7. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_cli_parser.py +103 -6
  8. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_i18n_data.json +72 -0
  9. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/audit.py +1 -6
  10. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/branches.py +36 -12
  11. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/clean.py +18 -8
  12. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/commit.py +66 -31
  13. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/conflicts.py +61 -16
  14. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/context.py +1 -3
  15. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/diff.py +84 -17
  16. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/git.py +118 -8
  17. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/health.py +27 -10
  18. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/log.py +31 -4
  19. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/merge.py +1 -3
  20. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/optimize.py +7 -3
  21. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/output.py +24 -1
  22. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/pick.py +2 -4
  23. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/pr.py +145 -25
  24. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup.py +1 -3
  25. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/show.py +50 -24
  26. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/snapshot.py +1 -3
  27. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/stash.py +129 -12
  28. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/status.py +13 -5
  29. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/suggest.py +4 -4
  30. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/summarize.py +1 -3
  31. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/sync.py +56 -60
  32. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/tag.py +3 -5
  33. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/undo.py +1 -3
  34. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/update.py +12 -2
  35. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/secret_scan.py +18 -0
  36. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/worktree.py +91 -6
  37. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/install.sh +38 -1
  38. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/pyproject.toml +1 -1
  39. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/branches.json +7 -0
  40. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/conflicts.json +12 -0
  41. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/diff.json +7 -0
  42. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/log.json +8 -0
  43. gitwise_cli-0.34.1/share/schemas/v1/input/pr.json +101 -0
  44. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/setup-agents.json +6 -6
  45. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/show.json +7 -0
  46. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/stash.json +23 -0
  47. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/worktree.json +7 -1
  48. gitwise_cli-0.34.1/share/schemas/v1/output/audit.json +115 -0
  49. gitwise_cli-0.34.1/share/schemas/v1/output/branches.json +75 -0
  50. gitwise_cli-0.34.1/share/schemas/v1/output/clean.json +58 -0
  51. gitwise_cli-0.34.1/share/schemas/v1/output/commands.json +46 -0
  52. gitwise_cli-0.34.1/share/schemas/v1/output/commit.json +74 -0
  53. gitwise_cli-0.34.1/share/schemas/v1/output/conflicts.json +88 -0
  54. gitwise_cli-0.34.1/share/schemas/v1/output/context.json +58 -0
  55. gitwise_cli-0.34.1/share/schemas/v1/output/doctor.json +58 -0
  56. gitwise_cli-0.34.1/share/schemas/v1/output/health.json +118 -0
  57. gitwise_cli-0.34.1/share/schemas/v1/output/merge.json +91 -0
  58. gitwise_cli-0.34.1/share/schemas/v1/output/optimize.json +50 -0
  59. gitwise_cli-0.34.1/share/schemas/v1/output/pick.json +77 -0
  60. gitwise_cli-0.34.1/share/schemas/v1/output/pr.json +103 -0
  61. gitwise_cli-0.34.1/share/schemas/v1/output/setup.json +68 -0
  62. gitwise_cli-0.34.1/share/schemas/v1/output/snapshot.json +62 -0
  63. gitwise_cli-0.34.1/share/schemas/v1/output/stash.json +101 -0
  64. gitwise_cli-0.34.1/share/schemas/v1/output/suggest.json +80 -0
  65. gitwise_cli-0.34.1/share/schemas/v1/output/summarize.json +41 -0
  66. gitwise_cli-0.34.1/share/schemas/v1/output/sync.json +58 -0
  67. gitwise_cli-0.34.1/share/schemas/v1/output/tag.json +81 -0
  68. gitwise_cli-0.34.1/share/schemas/v1/output/undo.json +74 -0
  69. gitwise_cli-0.34.1/share/schemas/v1/output/update.json +71 -0
  70. gitwise_cli-0.34.1/share/schemas/v1/output/worktree.json +95 -0
  71. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_branches.py +8 -0
  72. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_clean.py +15 -0
  73. gitwise_cli-0.34.1/tests/test_commands.py +38 -0
  74. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_commit.py +44 -2
  75. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_conflicts.py +36 -0
  76. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_diff.py +24 -0
  77. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_git.py +78 -4
  78. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_log.py +8 -0
  79. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_main.py +101 -58
  80. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_pr.py +77 -9
  81. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_secret_scan.py +12 -1
  82. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_show.py +19 -0
  83. gitwise_cli-0.34.1/tests/test_stash.py +178 -0
  84. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_status.py +1 -1
  85. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_worktree.py +44 -0
  86. gitwise_cli-0.33.1/share/schemas/v1/input/pr.json +0 -51
  87. gitwise_cli-0.33.1/tests/test_stash.py +0 -81
  88. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/.gitignore +0 -0
  89. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/LICENSE +0 -0
  90. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/README.md +0 -0
  91. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/bin/gitwise +0 -0
  92. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/bin/gw +0 -0
  93. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_cli_completions.py +0 -0
  94. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_cli_setup_agents.py +0 -0
  95. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_paths.py +0 -0
  96. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/_runtime_config.py +0 -0
  97. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/design.py +0 -0
  98. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/doctor.py +0 -0
  99. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/i18n.py +0 -0
  100. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/py.typed +0 -0
  101. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/schema.py +0 -0
  102. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/__init__.py +0 -0
  103. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/__init__.py +0 -0
  104. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/aider.py +0 -0
  105. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/base.py +0 -0
  106. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/codex.py +0 -0
  107. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  108. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/cursor.py +0 -0
  109. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/opencode.py +0 -0
  110. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/adapters/pi.py +0 -0
  111. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/exec.py +0 -0
  112. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/format.py +0 -0
  113. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/plan.py +0 -0
  114. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  115. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/plan_skills.py +0 -0
  116. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/__init__.py +0 -0
  117. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/aider.py +0 -0
  118. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/base.py +0 -0
  119. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/claude.py +0 -0
  120. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/codex.py +0 -0
  121. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  122. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/cursor.py +0 -0
  123. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/opencode.py +0 -0
  124. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/providers/pi.py +0 -0
  125. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/state.py +0 -0
  126. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/setup_agents/types.py +0 -0
  127. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/__init__.py +0 -0
  128. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/git_output.py +0 -0
  129. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/in_progress.py +0 -0
  130. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/json_envelope.py +0 -0
  131. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/parsing.py +0 -0
  132. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/gitwise/utils/types.py +0 -0
  133. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/agents/skills/git-audit/SKILL.md +0 -0
  134. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/agents/skills/git-clean/SKILL.md +0 -0
  135. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/agents/skills/git-optimize/SKILL.md +0 -0
  136. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/aider/CONVENTIONS.md.template +0 -0
  137. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/aider/aider.conf.yml.template +0 -0
  138. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/CLAUDE.md.template +0 -0
  139. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/rules/gitwise.md +0 -0
  140. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/settings.json.template +0 -0
  141. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/skills/git-audit/SKILL.md +0 -0
  142. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/skills/git-clean/SKILL.md +0 -0
  143. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/claude/skills/git-optimize/SKILL.md +0 -0
  144. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/codex/agents/gitwise.toml.template +0 -0
  145. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/continue/rules/gitwise.md.template +0 -0
  146. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/cursor/rules/gitwise.mdc.template +0 -0
  147. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/git-config-modern.txt +0 -0
  148. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/hooks/commit-msg +0 -0
  149. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/hooks/pre-commit +0 -0
  150. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/opencode/agents/gitwise.md.template +0 -0
  151. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/pi/skills/gitwise.md.template +0 -0
  152. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/audit.json +0 -0
  153. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/clean.json +0 -0
  154. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/commands.json +0 -0
  155. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/commit.json +0 -0
  156. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/completions.json +0 -0
  157. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/context.json +0 -0
  158. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/doctor.json +0 -0
  159. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/health.json +0 -0
  160. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/merge.json +0 -0
  161. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/optimize.json +0 -0
  162. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/pick.json +0 -0
  163. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/schema.json +0 -0
  164. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/setup.json +0 -0
  165. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/snapshot.json +0 -0
  166. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/status.json +0 -0
  167. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/suggest.json +0 -0
  168. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/summarize.json +0 -0
  169. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/sync.json +0 -0
  170. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/tag.json +0 -0
  171. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/undo.json +0 -0
  172. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/input/update.json +0 -0
  173. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/output/diff.json +0 -0
  174. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/output/log.json +0 -0
  175. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/output/setup-agents.json +0 -0
  176. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/share/schemas/v1/output/status.json +0 -0
  177. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/__init__.py +0 -0
  178. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/conftest.py +0 -0
  179. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_adapters.py +0 -0
  180. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_audit.py +0 -0
  181. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_context.py +0 -0
  182. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_design.py +0 -0
  183. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_doctor.py +0 -0
  184. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_edge_cases.py +0 -0
  185. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_envelope_contract.py +0 -0
  186. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_git_output_utils.py +0 -0
  187. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_health.py +0 -0
  188. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_i18n.py +0 -0
  189. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_in_progress.py +0 -0
  190. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_json_envelope_utils.py +0 -0
  191. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_md_links_script.py +0 -0
  192. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_merge.py +0 -0
  193. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_optimize.py +0 -0
  194. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_output.py +0 -0
  195. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_parsing_utils.py +0 -0
  196. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_pick.py +0 -0
  197. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_roadmap_baseline_script.py +0 -0
  198. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_sa_plan.py +0 -0
  199. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_sa_unit.py +0 -0
  200. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_schema_catalog.py +0 -0
  201. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_setup.py +0 -0
  202. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_setup_agents.py +0 -0
  203. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_snapshot.py +0 -0
  204. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_suggest.py +0 -0
  205. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_summarize.py +0 -0
  206. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_sync.py +0 -0
  207. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_sync_changelog_es_script.py +0 -0
  208. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_tag.py +0 -0
  209. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_types.py +0 -0
  210. {gitwise_cli-0.33.1 → gitwise_cli-0.34.1}/tests/test_undo.py +0 -0
@@ -3,6 +3,62 @@
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.34.1 (2026-07-22)
7
+
8
+ ### Fix
9
+
10
+ - **stash**: require --yes for pop in JSON mode and use run_gitwise helper in tests
11
+ - **worktree**: make remove dry-run non-destructive
12
+ - **hooks**: isolate pre-push from repository environment
13
+ - **cli**: make agent JSON contract position-independent
14
+
15
+ ## v0.34.0 (2026-06-25)
16
+
17
+ ### BREAKING CHANGE
18
+
19
+ - the --help --json and bare --json output shape changed
20
+ from flat top-level fields (kind/scope/commands/options) to the standard
21
+ v3 envelope with those fields nested under data. Pin to gitwise <0.34 or
22
+ read from payload.data if you consumed the old flat layout.
23
+
24
+ ### Feat
25
+
26
+ - **schema**: add output schemas for all JSON-emitting commands
27
+ - **pr**: add list filters and create action
28
+ - **stash,worktree**: add stash push/apply and worktree remove
29
+ - **diff,log,show,branches**: add --git-arg passthrough with safety deny-list
30
+ - **conflicts**: add --dry-run and --files for safe, scoped resolution
31
+ - expose json-lines capability, scrub git config env, surface sync upstream
32
+
33
+ ### Fix
34
+
35
+ - close last 3 review comments (limit min, health details, test pin)
36
+ - close remaining CodeRabbit comments (JSON contract, schemas, nits)
37
+ - windows installer temp file + complete remaining review comments
38
+ - address PR review comments (security, JSON contract, tests, schemas)
39
+ - resolve multi-review gate findings on the branch
40
+ - **install**: optional SHA-256 verification for the uv installer
41
+ - **schema**: regenerate conflicts input schema to canonical form
42
+ - **diff**: validate refspec before forwarding to git (defense-in-depth)
43
+ - add explicit machine error codes to all error envelopes
44
+ - **cli**: unify help JSON to the v3 envelope shape
45
+ - **diff,commit**: redact secret previews from JSON output
46
+ - **git**: handle subprocess timeout and reject zero GITWISE_GIT_TIMEOUT
47
+ - **show,commit**: emit JSON error envelopes on failure paths
48
+ - **commit**: block --allow-secret bypass in agent (JSON) mode
49
+
50
+ ### Refactor
51
+
52
+ - **health**: centralize score thresholds as named constants
53
+ - **output**: central report_error helper, migrate sync/show/commit
54
+ - **git**: simplify require_root to return Path | None
55
+ - remove dead emoji constant, inline trivial wrapper, type _gh cwd
56
+ - **setup-agents**: use shared schema constants in provider-list JSON
57
+
58
+ ### Perf
59
+
60
+ - **diff,status**: run independent git calls concurrently
61
+
6
62
  ## v0.33.1 (2026-06-23)
7
63
 
8
64
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.33.1
3
+ Version: 0.34.1
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.33.1"
3
+ __version__ = "0.34.1"
4
4
 
5
5
 
6
6
  def get_version() -> str:
@@ -1,11 +1,11 @@
1
- """CLI entry point argparse router for all gitwise subcommands."""
1
+ """CLI entry point -- argparse router for all gitwise subcommands."""
2
2
 
3
3
  import sys
4
4
  import time
5
5
 
6
6
  from ._cli_dispatch import DISPATCH
7
- from ._cli_introspection import extract_command_token, help_payload
8
- from ._cli_parser import build_parser
7
+ from ._cli_introspection import extract_command_token, help_data, help_payload
8
+ from ._cli_parser import _parse_global_options, build_parser
9
9
  from .i18n import t
10
10
  from .output import print_dim, print_json, set_json_mode, set_json_pretty
11
11
 
@@ -40,7 +40,7 @@ def _ensure_utf8_stdio() -> None:
40
40
 
41
41
  Windows defaults to a system codepage (often cp1252) for the Python
42
42
  embedded in console apps. That codepage cannot encode characters like
43
- U+2713 () used throughout gitwise's status output, causing
43
+ U+2713 (check mark) used throughout gitwise's status output, causing
44
44
  UnicodeEncodeError when the user is not running through a wrapper that
45
45
  sets PYTHONIOENCODING. macOS/Linux are already UTF-8 by default, so
46
46
  this reconfigure is a no-op there.
@@ -70,6 +70,7 @@ def main() -> int:
70
70
 
71
71
  parser = build_parser()
72
72
  raw_argv = sys.argv[1:]
73
+ global_options = _parse_global_options(raw_argv)
73
74
  wants_json_pretty = "--json-pretty" in raw_argv or "--pretty" in raw_argv
74
75
  if wants_json_pretty:
75
76
  set_json_pretty(True)
@@ -83,17 +84,25 @@ def main() -> int:
83
84
  return 0
84
85
 
85
86
  args = parser.parse_args()
87
+ for dest in ("lang", "theme", "json", "json_pretty"):
88
+ value = getattr(global_options, dest)
89
+ if value is not None and value is not False:
90
+ setattr(args, dest, value)
86
91
  if args.json_pretty:
87
92
  args.json = True
88
93
 
89
94
  if args.command is None:
90
95
  if args.json:
96
+ from .utils.json_envelope import error_envelope
97
+
91
98
  print_json(
92
- {
93
- **help_payload(parser),
94
- "ok": False,
95
- "error": "missing_command",
96
- }
99
+ error_envelope(
100
+ "gitwise",
101
+ error="no subcommand provided: run `gitwise --help` to list commands",
102
+ code="missing_command",
103
+ hint="try `gitwise --help`",
104
+ data=help_data(parser),
105
+ )
97
106
  )
98
107
  return 1
99
108
  parser.print_usage(sys.stderr)
@@ -35,14 +35,18 @@ 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
37
  from gitwise.i18n import t as _t
38
+ from gitwise.setup_agents.format import (
39
+ _SETUP_AGENTS_SCHEMA_COMPAT,
40
+ _SETUP_AGENTS_SCHEMA_VERSION,
41
+ )
38
42
  from gitwise.setup_agents.providers import list_providers
39
43
 
40
44
  adapter_list = list_providers()
41
45
  if args.json:
42
46
  print_json(
43
47
  {
44
- "v": 3,
45
- "v_compat": [1, 2, 3],
48
+ "v": _SETUP_AGENTS_SCHEMA_VERSION,
49
+ "v_compat": _SETUP_AGENTS_SCHEMA_COMPAT,
46
50
  "command": "setup-agents",
47
51
  "hints": [],
48
52
  "errors": [],
@@ -140,7 +144,11 @@ def _run_worktree(args: argparse.Namespace) -> int:
140
144
  from gitwise.worktree import run_worktree
141
145
 
142
146
  return run_worktree(
143
- args.action, getattr(args, "branch", None), dry_run=args.dry_run, as_json=args.json
147
+ args.action,
148
+ getattr(args, "branch", None),
149
+ dry_run=args.dry_run,
150
+ as_json=args.json,
151
+ force=getattr(args, "force", False),
144
152
  )
145
153
 
146
154
 
@@ -207,6 +215,7 @@ def _run_diff(args: argparse.Namespace) -> int:
207
215
  scan_secrets=args.scan_secrets,
208
216
  as_json=args.json,
209
217
  json_lines=getattr(args, "json_lines", False),
218
+ git_args=getattr(args, "git_args", None),
210
219
  )
211
220
 
212
221
 
@@ -225,6 +234,7 @@ def _run_log(args: argparse.Namespace) -> int:
225
234
  until=args.until,
226
235
  file=args.file,
227
236
  max_count=args.max_count,
237
+ git_args=getattr(args, "git_args", None),
228
238
  )
229
239
 
230
240
 
@@ -232,7 +242,9 @@ def _run_show(args: argparse.Namespace) -> int:
232
242
  """Dispatch to ``show`` subcommand."""
233
243
  from gitwise.show import run_show
234
244
 
235
- return run_show(ref=args.ref, stat=args.stat, as_json=args.json)
245
+ return run_show(
246
+ ref=args.ref, stat=args.stat, as_json=args.json, git_args=getattr(args, "git_args", None)
247
+ )
236
248
 
237
249
 
238
250
  def _run_commit(args: argparse.Namespace) -> int:
@@ -255,7 +267,13 @@ def _run_branches(args: argparse.Namespace) -> int:
255
267
  """Dispatch to ``branches`` subcommand."""
256
268
  from gitwise.branches import run_branches
257
269
 
258
- return run_branches(stale=args.stale, remote=args.remote, sort=args.sort, as_json=args.json)
270
+ return run_branches(
271
+ stale=args.stale,
272
+ remote=args.remote,
273
+ sort=args.sort,
274
+ as_json=args.json,
275
+ git_args=getattr(args, "git_args", None),
276
+ )
259
277
 
260
278
 
261
279
  def _run_sync(args: argparse.Namespace) -> int:
@@ -275,7 +293,21 @@ def _run_pr(args: argparse.Namespace) -> int:
275
293
  """Dispatch to ``pr`` subcommand."""
276
294
  from gitwise.pr import run_pr
277
295
 
278
- return run_pr(action=args.action, selector=args.selector, as_json=args.json)
296
+ return run_pr(
297
+ action=args.action,
298
+ selector=args.selector,
299
+ as_json=args.json,
300
+ state=getattr(args, "state", None),
301
+ author=getattr(args, "author", None),
302
+ label=getattr(args, "label", None),
303
+ limit=getattr(args, "limit", None),
304
+ base=getattr(args, "base", None),
305
+ head=getattr(args, "head", None),
306
+ title=getattr(args, "title", None),
307
+ body=getattr(args, "body", None),
308
+ draft=getattr(args, "draft", False),
309
+ fill=getattr(args, "fill", False),
310
+ )
279
311
 
280
312
 
281
313
  def _run_undo(args: argparse.Namespace) -> int:
@@ -317,6 +349,10 @@ def _run_stash(args: argparse.Namespace) -> int:
317
349
  yes=args.yes,
318
350
  dry_run=args.dry_run,
319
351
  patch=args.patch,
352
+ message=getattr(args, "message", None),
353
+ include_untracked=getattr(args, "include_untracked", False),
354
+ keep_index=getattr(args, "keep_index", False),
355
+ paths=getattr(args, "paths", None),
320
356
  )
321
357
 
322
358
 
@@ -355,7 +391,14 @@ def _run_conflicts(args: argparse.Namespace) -> int:
355
391
  """Dispatch to ``conflicts`` subcommand."""
356
392
  from gitwise.conflicts import run_conflicts
357
393
 
358
- return run_conflicts(ours=args.ours, theirs=args.theirs, union=args.union, as_json=args.json)
394
+ return run_conflicts(
395
+ ours=args.ours,
396
+ theirs=args.theirs,
397
+ union=args.union,
398
+ files=getattr(args, "files", None),
399
+ dry_run=getattr(args, "dry_run", False),
400
+ as_json=args.json,
401
+ )
359
402
 
360
403
 
361
404
  def _run_suggest(args: argparse.Namespace) -> int:
@@ -4,6 +4,7 @@ import argparse
4
4
  from typing import TypedDict
5
5
 
6
6
  from . import __version__
7
+ from .utils.json_envelope import ok_envelope
7
8
 
8
9
 
9
10
  def _json_safe(value: object) -> object:
@@ -67,11 +68,13 @@ def extract_command_token(argv: list[str]) -> str | None:
67
68
  return None
68
69
 
69
70
 
70
- def help_payload(parser: argparse.ArgumentParser, command: str | None = None) -> dict[str, object]:
71
- """Build a structured help payload for the root parser or a specific subcommand."""
71
+ def help_data(parser: argparse.ArgumentParser, command: str | None = None) -> dict[str, object]:
72
+ """Build the inner data dict for a structured help payload.
73
+
74
+ Returned nested under ``data`` by :func:`help_payload` so every ``--json``
75
+ output -- help included -- shares the v3 envelope shape.
76
+ """
72
77
  payload: dict[str, object] = {
73
- "v": 2,
74
- "ok": True,
75
78
  "kind": "help",
76
79
  "schema": "gitwise/help/v1",
77
80
  "version": __version__,
@@ -134,6 +137,11 @@ def help_payload(parser: argparse.ArgumentParser, command: str | None = None) ->
134
137
  return payload
135
138
 
136
139
 
140
+ def help_payload(parser: argparse.ArgumentParser, command: str | None = None) -> dict[str, object]:
141
+ """Build a v3-envelope structured help payload for the root parser or a subcommand."""
142
+ return ok_envelope("help", data=help_data(parser, command))
143
+
144
+
137
145
  class CommandMetadata(TypedDict):
138
146
  """Minimal metadata for a single subcommand."""
139
147
 
@@ -141,6 +149,11 @@ class CommandMetadata(TypedDict):
141
149
  help: str
142
150
  aliases: list[str]
143
151
  supports_json: bool
152
+ supports_json_lines: bool
153
+
154
+
155
+ # Subcommands that stream one JSON envelope per record (NDJSON) via --json-lines.
156
+ _JSON_LINES_COMMANDS: frozenset[str] = frozenset({"diff", "log"})
144
157
 
145
158
 
146
159
  def canonical_command_name(command_parser: argparse.ArgumentParser) -> str:
@@ -191,6 +204,7 @@ def commands_metadata(parser: argparse.ArgumentParser) -> list[CommandMetadata]:
191
204
  "help": help_by_parser_id.get(parser_id, command_parser.description or ""),
192
205
  "aliases": aliases,
193
206
  "supports_json": True,
207
+ "supports_json_lines": name in _JSON_LINES_COMMANDS,
194
208
  }
195
209
  )
196
210
 
@@ -217,6 +231,11 @@ def _action_property_schema(action: argparse.Action) -> dict[str, object]:
217
231
  if action.choices:
218
232
  value_schema["enum"] = [_json_safe(choice) for choice in action.choices]
219
233
 
234
+ # A "limit"/"max-count" argument is a positive-integer bound; surface that
235
+ # in the input schema so consumers know 0/negative are invalid.
236
+ if value_schema["type"] == "integer" and action.dest in {"limit", "max_count", "maxcount"}:
237
+ value_schema["minimum"] = 1
238
+
220
239
  description = "" if action.help is argparse.SUPPRESS else (action.help or "")
221
240
  if description:
222
241
  value_schema["description"] = description
@@ -225,7 +244,8 @@ def _action_property_schema(action: argparse.Action) -> dict[str, object]:
225
244
  value_schema["default"] = _json_safe(action.default)
226
245
 
227
246
  nargs = action.nargs
228
- if nargs in ("*", "+") or (isinstance(nargs, int) and nargs > 1):
247
+ is_append = isinstance(action, argparse._AppendAction)
248
+ if is_append or nargs in ("*", "+") or (isinstance(nargs, int) and nargs > 1):
229
249
  array_schema: dict[str, object] = {
230
250
  "type": "array",
231
251
  "items": value_schema,
@@ -12,8 +12,8 @@ def _root_help_epilog() -> str:
12
12
  return t("help_root_environment_epilog")
13
13
 
14
14
 
15
- def build_parser() -> argparse.ArgumentParser:
16
- """Build and return the top-level argparse parser with all subcommands registered."""
15
+ def _build_common_parser() -> argparse.ArgumentParser:
16
+ """Build the parser shared by the root command and every subcommand."""
17
17
  parent = argparse.ArgumentParser(add_help=False)
18
18
  parent.add_argument(
19
19
  "--lang",
@@ -35,6 +35,18 @@ def build_parser() -> argparse.ArgumentParser:
35
35
  action="store_true",
36
36
  help="pretty-print JSON output",
37
37
  )
38
+ return parent
39
+
40
+
41
+ def _parse_global_options(argv: list[str]) -> argparse.Namespace:
42
+ """Parse common options independently of their position in *argv*."""
43
+ options, _ = _build_common_parser().parse_known_args(argv)
44
+ return options
45
+
46
+
47
+ def build_parser() -> argparse.ArgumentParser:
48
+ """Build and return the top-level argparse parser with all subcommands registered."""
49
+ parent = _build_common_parser()
38
50
 
39
51
  parser = argparse.ArgumentParser(
40
52
  prog="gitwise",
@@ -70,7 +82,7 @@ def build_parser() -> argparse.ArgumentParser:
70
82
  p.add_argument(
71
83
  "--no-symlinks",
72
84
  action="store_true",
73
- help="force @AGENTS.md import fallback (no symlinks) — --local only",
85
+ help="force @AGENTS.md import fallback (no symlinks)",
74
86
  )
75
87
  p.add_argument(
76
88
  "--strict",
@@ -163,9 +175,17 @@ def build_parser() -> argparse.ArgumentParser:
163
175
  p.add_argument("--yes", "-y", action="store_true")
164
176
 
165
177
  p = sub.add_parser("worktree", help="worktree helpers for Claude agents", parents=[parent])
166
- p.add_argument("action", choices=["new", "clean", "list"], nargs="?", metavar="new|clean|list")
178
+ p.add_argument(
179
+ "action",
180
+ choices=["new", "clean", "list", "remove"],
181
+ nargs="?",
182
+ metavar="new|clean|list|remove",
183
+ )
167
184
  p.add_argument("branch", nargs="?")
168
185
  p.add_argument("--dry-run", action="store_true")
186
+ p.add_argument(
187
+ "--force", action="store_true", help="force removal even with modifications (remove only)"
188
+ )
169
189
 
170
190
  p = sub.add_parser(
171
191
  "diff",
@@ -207,6 +227,15 @@ def build_parser() -> argparse.ArgumentParser:
207
227
  metavar="PATH",
208
228
  help="limit to paths (use -- to separate from refspec)",
209
229
  )
230
+ p.add_argument(
231
+ "--git-arg",
232
+ action="append",
233
+ dest="git_args",
234
+ default=None,
235
+ metavar="OPT",
236
+ help="forward an extra option to the underlying git diff (repeatable; "
237
+ "code-exec/write/redirect options like --output/-c/--git-dir are refused)",
238
+ )
210
239
 
211
240
  p = sub.add_parser("log", help="pretty git log with filters", parents=[parent])
212
241
  p.add_argument("--oneline", action="store_true", help="one line per commit")
@@ -223,10 +252,28 @@ def build_parser() -> argparse.ArgumentParser:
223
252
  dest="json_lines",
224
253
  help="stream one JSON envelope per commit (NDJSON; implies JSON mode)",
225
254
  )
255
+ p.add_argument(
256
+ "--git-arg",
257
+ action="append",
258
+ dest="git_args",
259
+ default=None,
260
+ metavar="OPT",
261
+ help="forward an extra option to the underlying git log (repeatable; "
262
+ "code-exec/write/redirect options are refused)",
263
+ )
226
264
 
227
265
  p = sub.add_parser("show", help="commit inspector", parents=[parent])
228
266
  p.add_argument("ref", nargs="?", default="HEAD", help="commit ref (default: HEAD)")
229
267
  p.add_argument("--stat", action="store_true", help="show diffstat")
268
+ p.add_argument(
269
+ "--git-arg",
270
+ action="append",
271
+ dest="git_args",
272
+ default=None,
273
+ metavar="OPT",
274
+ help="forward an extra option to the underlying git show (repeatable; "
275
+ "code-exec/write/redirect options are refused)",
276
+ )
230
277
 
231
278
  p = sub.add_parser("commit", help="smart conventional commit", parents=[parent])
232
279
  p.add_argument("-m", "--message", type=str, default=None, help="commit message")
@@ -250,6 +297,15 @@ def build_parser() -> argparse.ArgumentParser:
250
297
  default="refname",
251
298
  help="sort field: refname, committerdate, -committerdate",
252
299
  )
300
+ p.add_argument(
301
+ "--git-arg",
302
+ action="append",
303
+ dest="git_args",
304
+ default=None,
305
+ metavar="OPT",
306
+ help="forward an extra option to the underlying git for-each-ref (repeatable; "
307
+ "code-exec/write/redirect options are refused)",
308
+ )
253
309
 
254
310
  p = sub.add_parser("sync", help="remote fetch, safe pull/push", parents=[parent])
255
311
  p.add_argument("--pull", action="store_true", help="pull --ff-only after fetch")
@@ -262,7 +318,7 @@ def build_parser() -> argparse.ArgumentParser:
262
318
  "action",
263
319
  nargs="?",
264
320
  default="list",
265
- choices=["list", "checks", "view", "comments"],
321
+ choices=["list", "checks", "view", "comments", "create"],
266
322
  help="pr action",
267
323
  )
268
324
  p.add_argument(
@@ -271,6 +327,23 @@ def build_parser() -> argparse.ArgumentParser:
271
327
  default=None,
272
328
  help="PR number/url/branch (default: current branch PR)",
273
329
  )
330
+ # pr list filters
331
+ p.add_argument(
332
+ "--state",
333
+ default=None,
334
+ choices=["open", "closed", "merged", "all"],
335
+ help="filter by state: open,closed,merged,all (list)",
336
+ )
337
+ p.add_argument("--author", default=None, help="filter by author login (list)")
338
+ p.add_argument("--label", default=None, help="filter by label (list)")
339
+ p.add_argument("--limit", type=int, default=None, help="max PRs to list")
340
+ p.add_argument("--base", default=None, help="base branch (list/create)")
341
+ p.add_argument("--head", default=None, help="head branch (list/create)")
342
+ # pr create
343
+ p.add_argument("--title", default=None, help="PR title (create)")
344
+ p.add_argument("--body", default=None, help="PR body (create)")
345
+ p.add_argument("--draft", action="store_true", help="create as draft")
346
+ p.add_argument("--fill", action="store_true", help="use commit info for title/body (create)")
274
347
 
275
348
  p = sub.add_parser("undo", help="reflog-based undo", parents=[parent])
276
349
  p.add_argument("ref", nargs="?", default=None, help="target ref (default: HEAD~1)")
@@ -292,12 +365,25 @@ def build_parser() -> argparse.ArgumentParser:
292
365
  "action",
293
366
  nargs="?",
294
367
  default="list",
295
- choices=["list", "show", "pop", "drop", "clear", "clean"],
368
+ choices=["list", "show", "pop", "apply", "push", "drop", "clear", "clean"],
296
369
  )
297
370
  p.add_argument("--index", type=int, default=0, help="stash index (default: 0)")
298
371
  p.add_argument("--dry-run", action="store_true", help="dry run (clear only)")
299
372
  p.add_argument("--yes", "-y", action="store_true", help="skip confirmation")
300
373
  p.add_argument("--patch", action="store_true", help="show full patch (show only)")
374
+ p.add_argument("-m", "--message", type=str, default=None, help="stash message (push only)")
375
+ p.add_argument(
376
+ "-u",
377
+ "--include-untracked",
378
+ action="store_true",
379
+ help="include untracked files (push only)",
380
+ )
381
+ p.add_argument(
382
+ "--keep-index", action="store_true", help="keep staged changes in the index (push only)"
383
+ )
384
+ p.add_argument(
385
+ "paths", nargs="*", default=None, help="paths to stash (push only, use -- to separate)"
386
+ )
301
387
 
302
388
  p = sub.add_parser("tag", help="semver-aware tag management", parents=[parent])
303
389
  p.add_argument(
@@ -338,6 +424,17 @@ def build_parser() -> argparse.ArgumentParser:
338
424
  action="store_true",
339
425
  help="resolve all conflicts keeping both sides (union)",
340
426
  )
427
+ p.add_argument(
428
+ "--files",
429
+ nargs="*",
430
+ default=None,
431
+ help="limit resolution to these files (use -- to separate from flags)",
432
+ )
433
+ p.add_argument(
434
+ "--dry-run",
435
+ action="store_true",
436
+ help="show what would be resolved without touching the working tree",
437
+ )
341
438
 
342
439
  p = sub.add_parser(
343
440
  "suggest",
@@ -343,6 +343,10 @@
343
343
  "es": "No hay conflictos",
344
344
  "en": "No conflicts"
345
345
  },
346
+ "conflicts_dry_run": {
347
+ "es": "Se resolverían {count} conflicto(s) con --{strategy} (dry-run):",
348
+ "en": "Would resolve {count} conflict(s) with --{strategy} (dry-run):"
349
+ },
346
350
  "conflicts_resolved_ours": {
347
351
  "es": "{count} conflicto(s) resuelto(s) con ours",
348
352
  "en": "{count} conflict(s) resolved with ours"
@@ -495,6 +499,14 @@
495
499
  "es": "Se detectaron {count} secreto(s) de alta severidad. ¿Commitear de todos modos?",
496
500
  "en": "{count} high-severity secret(s) detected. Commit anyway?"
497
501
  },
502
+ "secret_allow_requires_env": {
503
+ "es": "--allow-secret está bloqueado en modo --json: un agente no puede silenciar la confirmación humana de un secreto sin autorización fuera de banda",
504
+ "en": "--allow-secret is blocked in --json mode: an agent cannot silence the human confirmation of a secret without out-of-band authorization"
505
+ },
506
+ "secret_allow_requires_env_hint": {
507
+ "es": "para forzarlo en modo agente, exporte GITWISE_ALLOW_SECRETS=1 (controlado por el operador/CI, no por el prompt)",
508
+ "en": "to force it in agent mode, export GITWISE_ALLOW_SECRETS=1 (operator/CI-controlled, not prompt-settable)"
509
+ },
498
510
  "secret_scan_medium_warning": {
499
511
  "es": "advertencia: {rule} en {path}:{line} ({preview})",
500
512
  "en": "warning: {rule} at {path}:{line} ({preview})"
@@ -1287,6 +1299,34 @@
1287
1299
  "es": "no hay pull requests abiertos",
1288
1300
  "en": "no open pull requests"
1289
1301
  },
1302
+ "pr_create_needs_title": {
1303
+ "es": "pr create requiere --title (o --fill para usar el commit)",
1304
+ "en": "pr create requires --title (or --fill to use the commit message)"
1305
+ },
1306
+ "pr_list_failed": {
1307
+ "es": "pr list falló",
1308
+ "en": "pr list failed"
1309
+ },
1310
+ "pr_checks_failed": {
1311
+ "es": "pr checks falló",
1312
+ "en": "pr checks failed"
1313
+ },
1314
+ "pr_view_failed": {
1315
+ "es": "pr view falló",
1316
+ "en": "pr view failed"
1317
+ },
1318
+ "pr_comments_failed": {
1319
+ "es": "pr comments falló",
1320
+ "en": "pr comments failed"
1321
+ },
1322
+ "pr_create_failed": {
1323
+ "es": "no se pudo crear el pull request",
1324
+ "en": "failed to create pull request"
1325
+ },
1326
+ "pr_created": {
1327
+ "es": "pull request creado: {url}",
1328
+ "en": "pull request created: {url}"
1329
+ },
1290
1330
  "pr_unknown_action": {
1291
1331
  "es": "acción desconocida: {action}. Usa: list, checks, view, comments",
1292
1332
  "en": "unknown action: {action}. Use: list, checks, view, comments"
@@ -1559,6 +1599,22 @@
1559
1599
  "es": "Stash {ref} restaurado",
1560
1600
  "en": "Stash {ref} restored"
1561
1601
  },
1602
+ "stash_applied": {
1603
+ "es": "Stash {ref} aplicado (sin eliminar)",
1604
+ "en": "Stash {ref} applied (not removed)"
1605
+ },
1606
+ "stash_pushed": {
1607
+ "es": "Cambios guardados en un nuevo stash",
1608
+ "en": "Changes saved to a new stash"
1609
+ },
1610
+ "stash_push_failed": {
1611
+ "es": "No se pudo crear el stash (¿no hay cambios?)",
1612
+ "en": "Failed to create stash (no changes?)"
1613
+ },
1614
+ "stash_clear_failed": {
1615
+ "es": "No se pudieron limpiar los stashes",
1616
+ "en": "Failed to clear stashes"
1617
+ },
1562
1618
  "stash_hint": {
1563
1619
  "es": "Usa 'gitwise stash list' para ver índices válidos antes de show/drop/pop.",
1564
1620
  "en": "Use 'gitwise stash list' to inspect valid indexes before show/drop/pop."
@@ -1827,6 +1883,10 @@
1827
1883
  "es": "pull falló: el branch local y el remoto han divergido (gitwise sync usa --ff-only por seguridad)",
1828
1884
  "en": "pull failed: local and remote have diverged (gitwise sync uses --ff-only for safety)"
1829
1885
  },
1886
+ "sync_pull_failed": {
1887
+ "es": "pull falló (¿sin upstream, error de red o árbol sucio?)",
1888
+ "en": "pull failed (no upstream, network error, or dirty tree?)"
1889
+ },
1830
1890
  "sync_pull_diverged_hint": {
1831
1891
  "es": "Inspecciona el estado con: gitwise sync --dry-run --json. Reconcilia con: git pull --rebase (recomendado) o git pull --no-rebase. Luego: gitwise sync --push.",
1832
1892
  "en": "Inspect state with: gitwise sync --dry-run --json. Reconcile with: git pull --rebase (recommended) or git pull --no-rebase. Then: gitwise sync --push."
@@ -2051,6 +2111,18 @@
2051
2111
  "es": "worktree creado: {path}",
2052
2112
  "en": "worktree created: {path}"
2053
2113
  },
2114
+ "worktree_removed": {
2115
+ "es": "worktree eliminado: {path}",
2116
+ "en": "worktree removed: {path}"
2117
+ },
2118
+ "worktree_not_found": {
2119
+ "es": "no se encontro un worktree para: {target}",
2120
+ "en": "no worktree found for: {target}"
2121
+ },
2122
+ "worktree_remove_primary": {
2123
+ "es": "no se puede eliminar el worktree principal",
2124
+ "en": "cannot remove the primary worktree"
2125
+ },
2054
2126
  "worktree_failed": {
2055
2127
  "es": "no se pudo crear worktree: {error}",
2056
2128
  "en": "could not create worktree: {error}"
@@ -167,18 +167,13 @@ def _check_gpg_findings(gpg: dict) -> list[dict]:
167
167
  return []
168
168
 
169
169
 
170
- _SEVERITY_ICON = {"critical": "🔴", "high": "🟠", "medium": "🟡", "low": "🔵", "info": "ℹ️"}
171
-
172
-
173
170
  def run_audit(*, quick: bool = False, as_json: bool = False) -> int:
174
171
  """Run all diagnostic checks and report findings.
175
172
 
176
173
  Returns 0 when no critical/high/medium findings exist, 1 otherwise.
177
174
  ``--quick`` skips large-blob scanning and git-sizer.
178
175
  """
179
- root, err = require_root()
180
- if err:
181
- return err
176
+ root = require_root(as_json=as_json, command="audit")
182
177
  if root is None:
183
178
  return 1
184
179
  cwd = root