gitwise-cli 0.34.0__tar.gz → 0.34.2__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 (208) hide show
  1. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/CHANGELOG.md +15 -0
  2. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/PKG-INFO +1 -1
  3. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/__init__.py +1 -1
  4. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/__main__.py +6 -1
  5. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_cli_parser.py +14 -2
  6. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_i18n_data.json +4 -0
  7. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/audit.py +13 -7
  8. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/conflicts.py +2 -1
  9. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/stash.py +56 -9
  10. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/worktree.py +28 -4
  11. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/pyproject.toml +1 -1
  12. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_audit.py +32 -0
  13. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_conflicts.py +16 -0
  14. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_main.py +82 -44
  15. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_stash.py +79 -0
  16. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_worktree.py +26 -0
  17. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/.gitignore +0 -0
  18. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/LICENSE +0 -0
  19. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/README.md +0 -0
  20. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/bin/gitwise +0 -0
  21. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/bin/gw +0 -0
  22. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_cli_completions.py +0 -0
  23. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_cli_dispatch.py +0 -0
  24. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_cli_introspection.py +0 -0
  25. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_cli_setup_agents.py +0 -0
  26. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_paths.py +0 -0
  27. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/_runtime_config.py +0 -0
  28. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/branches.py +0 -0
  29. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/clean.py +0 -0
  30. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/commit.py +0 -0
  31. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/context.py +0 -0
  32. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/design.py +0 -0
  33. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/diff.py +0 -0
  34. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/doctor.py +0 -0
  35. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/git.py +0 -0
  36. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/health.py +0 -0
  37. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/i18n.py +0 -0
  38. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/log.py +0 -0
  39. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/merge.py +0 -0
  40. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/optimize.py +0 -0
  41. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/output.py +0 -0
  42. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/pick.py +0 -0
  43. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/pr.py +0 -0
  44. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/py.typed +0 -0
  45. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/schema.py +0 -0
  46. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup.py +0 -0
  47. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/__init__.py +0 -0
  48. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/__init__.py +0 -0
  49. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/aider.py +0 -0
  50. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/base.py +0 -0
  51. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/codex.py +0 -0
  52. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  53. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/cursor.py +0 -0
  54. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/opencode.py +0 -0
  55. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/adapters/pi.py +0 -0
  56. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/exec.py +0 -0
  57. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/format.py +0 -0
  58. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/plan.py +0 -0
  59. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  60. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/plan_skills.py +0 -0
  61. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/__init__.py +0 -0
  62. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/aider.py +0 -0
  63. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/base.py +0 -0
  64. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/claude.py +0 -0
  65. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/codex.py +0 -0
  66. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  67. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/cursor.py +0 -0
  68. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/opencode.py +0 -0
  69. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/providers/pi.py +0 -0
  70. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/state.py +0 -0
  71. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/setup_agents/types.py +0 -0
  72. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/show.py +0 -0
  73. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/snapshot.py +0 -0
  74. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/status.py +0 -0
  75. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/suggest.py +0 -0
  76. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/summarize.py +0 -0
  77. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/sync.py +0 -0
  78. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/tag.py +0 -0
  79. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/undo.py +0 -0
  80. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/update.py +0 -0
  81. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/__init__.py +0 -0
  82. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/git_output.py +0 -0
  83. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/in_progress.py +0 -0
  84. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/json_envelope.py +0 -0
  85. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/parsing.py +0 -0
  86. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/secret_scan.py +0 -0
  87. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/gitwise/utils/types.py +0 -0
  88. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/install.sh +0 -0
  89. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/agents/skills/git-audit/SKILL.md +0 -0
  90. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/agents/skills/git-clean/SKILL.md +0 -0
  91. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/agents/skills/git-optimize/SKILL.md +0 -0
  92. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/aider/CONVENTIONS.md.template +0 -0
  93. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/aider/aider.conf.yml.template +0 -0
  94. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/CLAUDE.md.template +0 -0
  95. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/rules/gitwise.md +0 -0
  96. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/settings.json.template +0 -0
  97. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/skills/git-audit/SKILL.md +0 -0
  98. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/skills/git-clean/SKILL.md +0 -0
  99. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/claude/skills/git-optimize/SKILL.md +0 -0
  100. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/codex/agents/gitwise.toml.template +0 -0
  101. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/continue/rules/gitwise.md.template +0 -0
  102. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/cursor/rules/gitwise.mdc.template +0 -0
  103. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/git-config-modern.txt +0 -0
  104. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/hooks/commit-msg +0 -0
  105. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/hooks/pre-commit +0 -0
  106. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/opencode/agents/gitwise.md.template +0 -0
  107. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/pi/skills/gitwise.md.template +0 -0
  108. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/audit.json +0 -0
  109. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/branches.json +0 -0
  110. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/clean.json +0 -0
  111. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/commands.json +0 -0
  112. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/commit.json +0 -0
  113. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/completions.json +0 -0
  114. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/conflicts.json +0 -0
  115. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/context.json +0 -0
  116. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/diff.json +0 -0
  117. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/doctor.json +0 -0
  118. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/health.json +0 -0
  119. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/log.json +0 -0
  120. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/merge.json +0 -0
  121. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/optimize.json +0 -0
  122. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/pick.json +0 -0
  123. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/pr.json +0 -0
  124. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/schema.json +0 -0
  125. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/setup-agents.json +0 -0
  126. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/setup.json +0 -0
  127. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/show.json +0 -0
  128. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/snapshot.json +0 -0
  129. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/stash.json +0 -0
  130. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/status.json +0 -0
  131. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/suggest.json +0 -0
  132. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/summarize.json +0 -0
  133. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/sync.json +0 -0
  134. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/tag.json +0 -0
  135. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/undo.json +0 -0
  136. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/update.json +0 -0
  137. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/input/worktree.json +0 -0
  138. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/audit.json +0 -0
  139. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/branches.json +0 -0
  140. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/clean.json +0 -0
  141. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/commands.json +0 -0
  142. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/commit.json +0 -0
  143. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/conflicts.json +0 -0
  144. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/context.json +0 -0
  145. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/diff.json +0 -0
  146. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/doctor.json +0 -0
  147. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/health.json +0 -0
  148. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/log.json +0 -0
  149. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/merge.json +0 -0
  150. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/optimize.json +0 -0
  151. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/pick.json +0 -0
  152. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/pr.json +0 -0
  153. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/setup-agents.json +0 -0
  154. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/setup.json +0 -0
  155. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/snapshot.json +0 -0
  156. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/stash.json +0 -0
  157. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/status.json +0 -0
  158. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/suggest.json +0 -0
  159. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/summarize.json +0 -0
  160. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/sync.json +0 -0
  161. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/tag.json +0 -0
  162. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/undo.json +0 -0
  163. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/update.json +0 -0
  164. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/share/schemas/v1/output/worktree.json +0 -0
  165. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/__init__.py +0 -0
  166. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/conftest.py +0 -0
  167. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_adapters.py +0 -0
  168. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_branches.py +0 -0
  169. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_clean.py +0 -0
  170. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_commands.py +0 -0
  171. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_commit.py +0 -0
  172. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_context.py +0 -0
  173. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_design.py +0 -0
  174. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_diff.py +0 -0
  175. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_doctor.py +0 -0
  176. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_edge_cases.py +0 -0
  177. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_envelope_contract.py +0 -0
  178. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_git.py +0 -0
  179. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_git_output_utils.py +0 -0
  180. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_health.py +0 -0
  181. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_i18n.py +0 -0
  182. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_in_progress.py +0 -0
  183. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_json_envelope_utils.py +0 -0
  184. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_log.py +0 -0
  185. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_md_links_script.py +0 -0
  186. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_merge.py +0 -0
  187. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_optimize.py +0 -0
  188. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_output.py +0 -0
  189. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_parsing_utils.py +0 -0
  190. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_pick.py +0 -0
  191. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_pr.py +0 -0
  192. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_roadmap_baseline_script.py +0 -0
  193. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_sa_plan.py +0 -0
  194. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_sa_unit.py +0 -0
  195. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_schema_catalog.py +0 -0
  196. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_secret_scan.py +0 -0
  197. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_setup.py +0 -0
  198. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_setup_agents.py +0 -0
  199. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_show.py +0 -0
  200. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_snapshot.py +0 -0
  201. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_status.py +0 -0
  202. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_suggest.py +0 -0
  203. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_summarize.py +0 -0
  204. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_sync.py +0 -0
  205. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_sync_changelog_es_script.py +0 -0
  206. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_tag.py +0 -0
  207. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_types.py +0 -0
  208. {gitwise_cli-0.34.0 → gitwise_cli-0.34.2}/tests/test_undo.py +0 -0
@@ -3,6 +3,21 @@
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.2 (2026-07-22)
7
+
8
+ ### Fix
9
+
10
+ - **security**: enforce subprocess safety invariants
11
+
12
+ ## v0.34.1 (2026-07-22)
13
+
14
+ ### Fix
15
+
16
+ - **stash**: require --yes for pop in JSON mode and use run_gitwise helper in tests
17
+ - **worktree**: make remove dry-run non-destructive
18
+ - **hooks**: isolate pre-push from repository environment
19
+ - **cli**: make agent JSON contract position-independent
20
+
6
21
  ## v0.34.0 (2026-06-25)
7
22
 
8
23
  ### BREAKING CHANGE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.34.0
3
+ Version: 0.34.2
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.34.0"
3
+ __version__ = "0.34.2"
4
4
 
5
5
 
6
6
  def get_version() -> str:
@@ -5,7 +5,7 @@ import time
5
5
 
6
6
  from ._cli_dispatch import DISPATCH
7
7
  from ._cli_introspection import extract_command_token, help_data, help_payload
8
- from ._cli_parser import build_parser
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
 
@@ -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,6 +84,10 @@ 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
 
@@ -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",
@@ -1611,6 +1611,10 @@
1611
1611
  "es": "No se pudo crear el stash (¿no hay cambios?)",
1612
1612
  "en": "Failed to create stash (no changes?)"
1613
1613
  },
1614
+ "stash_clear_failed": {
1615
+ "es": "No se pudieron limpiar los stashes",
1616
+ "en": "Failed to clear stashes"
1617
+ },
1614
1618
  "stash_hint": {
1615
1619
  "es": "Usa 'gitwise stash list' para ver índices válidos antes de show/drop/pop.",
1616
1620
  "en": "Use 'gitwise stash list' to inspect valid indexes before show/drop/pop."
@@ -8,6 +8,7 @@ from pathlib import Path
8
8
  from typing import Any
9
9
 
10
10
  from gitwise.git import (
11
+ _get_timeout,
11
12
  gpg_status,
12
13
  has_commit_graph,
13
14
  has_remote,
@@ -112,13 +113,18 @@ def _run_git_sizer(cwd: Path) -> dict | None:
112
113
  """Run ``git-sizer`` if available and return its JSON output, or None."""
113
114
  if not shutil.which("git-sizer"):
114
115
  return None
115
- r = subprocess.run(
116
- ["git-sizer", "--threshold=2", "--json"],
117
- cwd=cwd,
118
- capture_output=True,
119
- text=True,
120
- check=False,
121
- )
116
+ try:
117
+ r = subprocess.run(
118
+ ["git-sizer", "--threshold=2", "--json"],
119
+ cwd=cwd,
120
+ capture_output=True,
121
+ text=True,
122
+ check=False,
123
+ timeout=_get_timeout("git-sizer"),
124
+ )
125
+ except subprocess.TimeoutExpired:
126
+ debug("git-sizer timed out")
127
+ return None
122
128
  if r.returncode not in (0, 1):
123
129
  return None
124
130
  import json
@@ -4,7 +4,7 @@ import subprocess
4
4
  import tempfile
5
5
  from pathlib import Path
6
6
 
7
- from gitwise.git import require_root
7
+ from gitwise.git import _GIT_ENV, require_root
8
8
  from gitwise.git import run as git_run
9
9
  from gitwise.i18n import t
10
10
  from gitwise.output import (
@@ -27,6 +27,7 @@ def _git_bytes(args: list[str], *, cwd: Path) -> tuple[int, bytes, bytes]:
27
27
  ["git", *args],
28
28
  cwd=cwd,
29
29
  capture_output=True,
30
+ env=_GIT_ENV,
30
31
  timeout=120,
31
32
  )
32
33
  return r.returncode, r.stdout, r.stderr
@@ -115,13 +115,28 @@ def _cmd_show(root: Path, index: int, *, as_json: bool, patch: bool = False) ->
115
115
  return 0
116
116
 
117
117
 
118
- def _cmd_pop(root: Path, index: int, *, as_json: bool) -> int:
119
- """Execute ``stash pop`` sub-action."""
118
+ def _cmd_pop(root: Path, index: int, *, as_json: bool, yes: bool = False) -> int:
119
+ """Execute ``stash pop`` sub-action with optional confirmation."""
120
120
  ref = f"stash@{{{index}}}"
121
+ if as_json and not yes:
122
+ print_json(
123
+ error_envelope(
124
+ "stash",
125
+ error=t("yes_required_with_json"),
126
+ code="yes_required",
127
+ hint=t("yes_required_hint"),
128
+ )
129
+ )
130
+ return 2
121
131
  r = git_run(["stash", "pop", ref], cwd=root, check=False)
122
132
  if r.returncode != 0:
123
- error(r.stderr.strip())
124
- return 1
133
+ return report_error(
134
+ "stash",
135
+ as_json=as_json,
136
+ msg=r.stderr.strip() or t("stash_not_found", index=str(index)),
137
+ code="stash_pop_failed",
138
+ hint=t("stash_hint"),
139
+ )
125
140
  if as_json:
126
141
  print_json(ok_envelope("stash", popped=ref))
127
142
  return 0
@@ -132,13 +147,28 @@ def _cmd_pop(root: Path, index: int, *, as_json: bool) -> int:
132
147
  def _cmd_drop(root: Path, index: int, *, as_json: bool, yes: bool = False) -> int:
133
148
  """Execute ``stash drop`` sub-action with optional confirmation."""
134
149
  ref = f"stash@{{{index}}}"
150
+ if as_json and not yes:
151
+ print_json(
152
+ error_envelope(
153
+ "stash",
154
+ error=t("yes_required_with_json"),
155
+ code="yes_required",
156
+ hint=t("yes_required_hint"),
157
+ )
158
+ )
159
+ return 2
135
160
  if not yes and not confirm(t("confirm_stash_drop", ref=ref)):
136
161
  warn(t("aborted"))
137
162
  return 1
138
163
  r = git_run(["stash", "drop", ref], cwd=root, check=False)
139
164
  if r.returncode != 0:
140
- error(r.stderr.strip())
141
- return 1
165
+ return report_error(
166
+ "stash",
167
+ as_json=as_json,
168
+ msg=r.stderr.strip() or t("stash_not_found", index=str(index)),
169
+ code="stash_drop_failed",
170
+ hint=t("stash_hint"),
171
+ )
142
172
  if as_json:
143
173
  print_json(ok_envelope("stash", dropped=ref))
144
174
  return 0
@@ -150,6 +180,9 @@ def _cmd_clean(root: Path, *, as_json: bool, yes: bool = False, dry_run: bool =
150
180
  """Execute ``stash clear`` sub-action with optional dry-run and confirmation."""
151
181
  stashes = _stash_list(root)
152
182
  if not stashes:
183
+ if as_json:
184
+ print_json(ok_envelope("stash", cleared=0))
185
+ return 0
153
186
  ok(t("stash_empty"))
154
187
  return 0
155
188
  if dry_run:
@@ -158,13 +191,27 @@ def _cmd_clean(root: Path, *, as_json: bool, yes: bool = False, dry_run: bool =
158
191
  return 0
159
192
  ok(t("stash_clean_dry", count=str(len(stashes))))
160
193
  return 0
194
+ if as_json and not yes:
195
+ print_json(
196
+ error_envelope(
197
+ "stash",
198
+ error=t("yes_required_with_json"),
199
+ code="yes_required",
200
+ hint=t("yes_required_hint"),
201
+ )
202
+ )
203
+ return 2
161
204
  if not yes and not confirm(t("confirm_stash_clean", count=str(len(stashes)))):
162
205
  warn(t("aborted"))
163
206
  return 1
164
207
  r = git_run(["stash", "clear"], cwd=root, check=False)
165
208
  if r.returncode != 0:
166
- error(r.stderr.strip())
167
- return 1
209
+ return report_error(
210
+ "stash",
211
+ as_json=as_json,
212
+ msg=r.stderr.strip() or t("stash_clear_failed"),
213
+ code="stash_clear_failed",
214
+ )
168
215
  if as_json:
169
216
  print_json(ok_envelope("stash", cleared=len(stashes)))
170
217
  return 0
@@ -253,7 +300,7 @@ def run_stash(
253
300
  if action == "apply":
254
301
  return _cmd_apply(root, index, as_json=as_json)
255
302
  if action == "pop":
256
- return _cmd_pop(root, index, as_json=as_json)
303
+ return _cmd_pop(root, index, as_json=as_json, yes=yes)
257
304
  if action == "push":
258
305
  return _cmd_push(
259
306
  root,
@@ -182,7 +182,12 @@ def _worktree_clean(cwd: Path, *, dry_run: bool = False, as_json: bool = False)
182
182
 
183
183
 
184
184
  def _worktree_remove(
185
- target: str, root: Path, *, force: bool = False, as_json: bool = False
185
+ target: str,
186
+ root: Path,
187
+ *,
188
+ force: bool = False,
189
+ dry_run: bool = False,
190
+ as_json: bool = False,
186
191
  ) -> int:
187
192
  """Remove a worktree identified by path or checked-out branch name."""
188
193
  if not target:
@@ -216,6 +221,21 @@ def _worktree_remove(
216
221
  code="worktree_remove_primary",
217
222
  )
218
223
 
224
+ if dry_run:
225
+ if as_json:
226
+ print_json(
227
+ ok_envelope(
228
+ "worktree",
229
+ would_remove=match["path"],
230
+ branch=match.get("branch") or "",
231
+ dry_run=True,
232
+ )
233
+ )
234
+ return 0
235
+ print_dim(match["path"])
236
+ print_dim(t("dry_run_no_exec"))
237
+ return 0
238
+
219
239
  args = ["worktree", "remove"]
220
240
  if force:
221
241
  args.append("--force")
@@ -252,8 +272,12 @@ def run_worktree(
252
272
 
253
273
  if action == "new":
254
274
  if not branch:
255
- error(t("worktree_usage"))
256
- return 1
275
+ return report_error(
276
+ "worktree",
277
+ as_json=as_json,
278
+ msg=t("worktree_usage"),
279
+ code="worktree_branch_required",
280
+ )
257
281
  if as_json:
258
282
  rc, data = _worktree_new_json(branch, root)
259
283
  if rc == 0:
@@ -274,7 +298,7 @@ def run_worktree(
274
298
  return _worktree_clean(root, dry_run=dry_run, as_json=as_json)
275
299
 
276
300
  elif action == "remove":
277
- return _worktree_remove(branch or "", root, force=force, as_json=as_json)
301
+ return _worktree_remove(branch or "", root, force=force, dry_run=dry_run, as_json=as_json)
278
302
 
279
303
  elif action == "list":
280
304
  return _worktree_list(root, as_json=as_json)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gitwise-cli"
3
- version = "0.34.0"
3
+ version = "0.34.2"
4
4
  description = "Python CLI for optimizing git workflows and Claude Code integration"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -4,6 +4,7 @@ import json
4
4
  import os
5
5
  import platform
6
6
  import subprocess
7
+ import sys
7
8
  import time
8
9
 
9
10
  from conftest import run_gitwise as _run
@@ -101,3 +102,34 @@ def test_audit_quick_skips_large_blobs(tmp_git_repo_with_large_blob):
101
102
  large = [f for f in data["data"]["findings"] if f["type"] == "large_blobs"]
102
103
  assert len(large) == 0 # --quick skips blob search
103
104
  assert data["data"]["summary"]["large_blobs"] == 0
105
+
106
+
107
+ def test_audit_git_sizer_timeout_returns_json(tmp_git_repo, tmp_path):
108
+ bin_dir = tmp_path / "bin"
109
+ bin_dir.mkdir()
110
+ script = bin_dir / "slow_git_sizer.py"
111
+ script.write_text('import time\ntime.sleep(8)\nprint("{}")\n')
112
+
113
+ if os.name == "nt":
114
+ executable = bin_dir / "git-sizer.cmd"
115
+ executable.write_text(f'@"{sys.executable}" "{script}" %*\n')
116
+ else:
117
+ executable = bin_dir / "git-sizer"
118
+ executable.write_text(f"#!{sys.executable}\n{script.read_text()}")
119
+ executable.chmod(0o755)
120
+
121
+ start = time.monotonic()
122
+ result = _run(
123
+ "audit",
124
+ "--json",
125
+ cwd=tmp_git_repo,
126
+ env={
127
+ "GITWISE_GIT_TIMEOUT": "1",
128
+ "PATH": f"{bin_dir}{os.pathsep}{os.environ['PATH']}",
129
+ },
130
+ )
131
+ elapsed = time.monotonic() - start
132
+
133
+ assert result.returncode in (0, 1)
134
+ assert json.loads(result.stdout)["command"] == "audit"
135
+ assert elapsed < 6
@@ -86,6 +86,22 @@ def test_conflicts_union_json_envelope(tmp_git_repo):
86
86
  assert env["data"]["resolved"] >= 1
87
87
 
88
88
 
89
+ def test_conflicts_union_scrubs_injected_git_config(tmp_git_repo):
90
+ _setup_text_conflict(tmp_git_repo)
91
+
92
+ r = run_gitwise(
93
+ "conflicts",
94
+ "--union",
95
+ "--json",
96
+ cwd=tmp_git_repo,
97
+ env={"GIT_CONFIG_COUNT": "invalid"},
98
+ )
99
+
100
+ assert r.returncode == 0
101
+ env = json.loads(r.stdout)
102
+ assert env["data"]["resolved"] >= 1
103
+
104
+
89
105
  def test_conflicts_dry_run_does_not_touch_tree(tmp_git_repo):
90
106
  """--dry-run reports the plan but leaves conflict markers in place."""
91
107
  _setup_text_conflict(tmp_git_repo)